371 * @LastMOd 2006/08/01 |
371 * @LastMOd 2006/08/01 |
372 * @Version 0.1 |
372 * @Version 0.1 |
373 * @Application Last version of JavaScriptCompressor class use this one to map source code. |
373 * @Application Last version of JavaScriptCompressor class use this one to map source code. |
374 */ |
374 */ |
375 class SourceMap { |
375 class SourceMap { |
376 |
376 |
377 /** |
377 /** |
378 * public method |
378 * public method |
379 * getMap(&$source:string, &$delimeters:array):array |
379 * getMap(&$source:string, &$delimeters:array):array |
380 * Maps the source code using $delimeters rules and returns map as an array |
380 * Maps the source code using $delimeters rules and returns map as an array |
381 * NOTE: read comments to know more about map and delimeter |
381 * NOTE: read comments to know more about map and delimeter |
382 * |
382 * |
383 * @param string generic source code |
383 * @param string generic source code |
384 * @param array array with nested array with code rules |
384 * @param array array with nested array with code rules |
385 */ |
385 */ |
386 function getMap(&$source, &$delimeters) { |
386 function getMap(&$source, &$delimeters) { |
387 |
387 |
388 # "unsigned" integer variables |
388 # "unsigned" integer variables |
389 $sourcePosition = 0; |
389 $sourcePosition = 0; |
390 $delimetersPosition = 0; |
390 $delimetersPosition = 0; |
391 $findLength = 0; |
391 $findLength = 0; |
392 $len = 0; |
392 $len = 0; |
393 $tempIndex = 0; |
393 $tempIndex = 0; |
394 $sourceLength = strlen($source); |
394 $sourceLength = strlen($source); |
395 $delimetersLength = count($delimeters); |
395 $delimetersLength = count($delimeters); |
396 |
396 |
397 # integer variables |
397 # integer variables |
398 $tempPosition = -1; |
398 $tempPosition = -1; |
399 $endPosition = -1; |
399 $endPosition = -1; |
400 |
400 |
401 # array variables |
401 # array variables |
402 $map = array(); |
402 $map = array(); |
403 $tempMap = array(); |
403 $tempMap = array(); |
404 $tempDelimeter = array(); |
404 $tempDelimeter = array(); |
405 |
405 |
406 while($sourcePosition < $sourceLength) { |
406 while($sourcePosition < $sourceLength) { |
407 $endPosition = -1; |
407 $endPosition = -1; |
408 for($delimetersPosition = 0; $delimetersPosition < $delimetersLength; $delimetersPosition++) { |
408 for($delimetersPosition = 0; $delimetersPosition < $delimetersLength; $delimetersPosition++) { |
409 $tempPosition = strpos($source, $delimeters[$delimetersPosition]['start'], $sourcePosition); |
409 $tempPosition = strpos($source, $delimeters[$delimetersPosition]['start'], $sourcePosition); |
410 if($tempPosition !== false && ($tempPosition < $endPosition || $endPosition === -1)) { |
410 if($tempPosition !== false && ($tempPosition < $endPosition || $endPosition === -1)) { |
411 $endPosition = $tempPosition; |
411 $endPosition = $tempPosition; |
412 $tempIndex = $delimetersPosition; |
412 $tempIndex = $delimetersPosition; |
413 } |
413 } |
414 } |
414 } |
415 if($endPosition !== -1) { |
415 if($endPosition !== -1) { |
416 $sourcePosition = $endPosition; |
416 $sourcePosition = $endPosition; |
417 $tempDelimeter = &$delimeters[$tempIndex]; |
417 $tempDelimeter = &$delimeters[$tempIndex]; |
418 $findLength = strlen($tempDelimeter['start']); |
418 $findLength = strlen($tempDelimeter['start']); |
419 if(is_array($tempDelimeter['end'])) { |
419 if(is_array($tempDelimeter['end'])) { |
420 $delimetersPosition = 0; |
420 $delimetersPosition = 0; |
421 $endPosition = -1; |
421 $endPosition = -1; |
422 for($len = count($tempDelimeter['end']); $delimetersPosition < $len; $delimetersPosition++) { |
422 for($len = count($tempDelimeter['end']); $delimetersPosition < $len; $delimetersPosition++) { |
423 $tempPosition = strpos($source, $tempDelimeter['end'][$delimetersPosition], $sourcePosition + $findLength); |
423 $tempPosition = strpos($source, $tempDelimeter['end'][$delimetersPosition], $sourcePosition + $findLength); |
424 if($tempPosition !== false && ($tempPosition < $endPosition || $endPosition === -1)) { |
424 if($tempPosition !== false && ($tempPosition < $endPosition || $endPosition === -1)) { |
425 $endPosition = $tempPosition; |
425 $endPosition = $tempPosition; |
426 $tempIndex = $delimetersPosition; |
426 $tempIndex = $delimetersPosition; |
427 } |
427 } |
428 } |
428 } |
429 if($endPosition !== -1) |
429 if($endPosition !== -1) |
430 $endPosition = $endPosition + strlen($tempDelimeter['end'][$tempIndex]); |
430 $endPosition = $endPosition + strlen($tempDelimeter['end'][$tempIndex]); |
431 else |
431 else |
432 $endPosition = $sourceLength; |
432 $endPosition = $sourceLength; |
433 array_push($map, array('name'=>$tempDelimeter['name'], 'start'=>$sourcePosition, 'end'=>$endPosition)); |
433 array_push($map, array('name'=>$tempDelimeter['name'], 'start'=>$sourcePosition, 'end'=>$endPosition)); |
434 $sourcePosition = $endPosition - 1; |
434 $sourcePosition = $endPosition - 1; |
435 } |
435 } |
436 elseif(isset($tempDelimeter['match'])) { |
436 elseif(isset($tempDelimeter['match'])) { |
437 $tempPosition = strpos($source, $tempDelimeter['end'], $sourcePosition + $findLength); |
437 $tempPosition = strpos($source, $tempDelimeter['end'], $sourcePosition + $findLength); |
438 $len = strlen($tempDelimeter['end']); |
438 $len = strlen($tempDelimeter['end']); |
439 if($tempPosition !== false && preg_match($tempDelimeter['match'], substr($source, $sourcePosition, $tempPosition - $sourcePosition + $len))) { |
439 if($tempPosition !== false && preg_match($tempDelimeter['match'], substr($source, $sourcePosition, $tempPosition - $sourcePosition + $len))) { |
440 $endPosition = isset($tempDelimeter['noslash']) ? $this->__endCharNoSlash($source, $sourcePosition, $tempDelimeter['end'], $sourceLength) : $tempPosition + $len; |
440 $endPosition = isset($tempDelimeter['noslash']) ? $this->__endCharNoSlash($source, $sourcePosition, $tempDelimeter['end'], $sourceLength) : $tempPosition + $len; |
441 array_push($map, array('name'=>$tempDelimeter['name'], 'start'=>$sourcePosition, 'end'=>$endPosition)); |
441 array_push($map, array('name'=>$tempDelimeter['name'], 'start'=>$sourcePosition, 'end'=>$endPosition)); |
442 $sourcePosition = $endPosition - 1; |
442 $sourcePosition = $endPosition - 1; |
443 } |
443 } |
444 } |
444 } |
445 else { |
445 else { |
446 if(isset($tempDelimeter['noslash'])) |
446 if(isset($tempDelimeter['noslash'])) |
447 $endPosition = $this->__endCharNoSlash($source, $sourcePosition, $tempDelimeter['end'], $sourceLength); |
447 $endPosition = $this->__endCharNoSlash($source, $sourcePosition, $tempDelimeter['end'], $sourceLength); |
448 else { |
448 else { |
449 $tempPosition = strpos($source, $tempDelimeter['end'], $sourcePosition + $findLength); |
449 $tempPosition = strpos($source, $tempDelimeter['end'], $sourcePosition + $findLength); |
450 if($tempPosition !== false) |
450 if($tempPosition !== false) |
451 $endPosition = $tempPosition + strlen($tempDelimeter['end']); |
451 $endPosition = $tempPosition + strlen($tempDelimeter['end']); |
452 else |
452 else |
453 $endPosition = $sourceLength; |
453 $endPosition = $sourceLength; |
454 } |
454 } |
455 array_push($map, array('name'=>$tempDelimeter['name'], 'start'=>$sourcePosition, 'end'=>$endPosition)); |
455 array_push($map, array('name'=>$tempDelimeter['name'], 'start'=>$sourcePosition, 'end'=>$endPosition)); |
456 $sourcePosition = $endPosition - 1; |
456 $sourcePosition = $endPosition - 1; |
457 } |
457 } |
458 } |
458 } |
459 else |
459 else |
460 $sourcePosition = $sourceLength - 1; |
460 $sourcePosition = $sourceLength - 1; |
461 ++$sourcePosition; |
461 ++$sourcePosition; |
462 } |
462 } |
463 $len = count($map); |
463 $len = count($map); |
464 if($len === 0) |
464 if($len === 0) |
465 array_push($tempMap, array('name'=>'code', 'start'=>0, 'end'=>$sourceLength)); |
465 array_push($tempMap, array('name'=>'code', 'start'=>0, 'end'=>$sourceLength)); |
466 else { |
466 else { |
467 for($tempIndex = 0; $tempIndex < $len; $tempIndex++) { |
467 for($tempIndex = 0; $tempIndex < $len; $tempIndex++) { |
468 if($tempIndex === 0 && $map[$tempIndex]['start'] > 0) |
468 if($tempIndex === 0 && $map[$tempIndex]['start'] > 0) |
469 array_push($tempMap, array('name'=>'code', 'start'=>0, 'end'=>$map[$tempIndex]['start'])); |
469 array_push($tempMap, array('name'=>'code', 'start'=>0, 'end'=>$map[$tempIndex]['start'])); |
470 elseif($tempIndex > 0 && $map[$tempIndex]['start'] > $map[$tempIndex-1]['end']) |
470 elseif($tempIndex > 0 && $map[$tempIndex]['start'] > $map[$tempIndex-1]['end']) |
471 array_push($tempMap, array('name'=>'code', 'start'=>$map[$tempIndex-1]['end'], 'end'=>$map[$tempIndex]['start'])); |
471 array_push($tempMap, array('name'=>'code', 'start'=>$map[$tempIndex-1]['end'], 'end'=>$map[$tempIndex]['start'])); |
472 array_push($tempMap, array('name'=>$map[$tempIndex]['name'], 'start'=>$map[$tempIndex]['start'], 'end'=>$map[$tempIndex]['end'])); |
472 array_push($tempMap, array('name'=>$map[$tempIndex]['name'], 'start'=>$map[$tempIndex]['start'], 'end'=>$map[$tempIndex]['end'])); |
473 if($tempIndex + 1 === $len && $map[$tempIndex]['end'] < $sourceLength) |
473 if($tempIndex + 1 === $len && $map[$tempIndex]['end'] < $sourceLength) |
474 array_push($tempMap, array('name'=>'code', 'start'=>$map[$tempIndex]['end'], 'end'=>$sourceLength)); |
474 array_push($tempMap, array('name'=>'code', 'start'=>$map[$tempIndex]['end'], 'end'=>$sourceLength)); |
475 } |
475 } |
476 } |
476 } |
477 return $tempMap; |
477 return $tempMap; |
478 } |
478 } |
479 |
479 |
480 function __endCharNoSlash(&$source, $position, &$find, &$len) { |
480 function __endCharNoSlash(&$source, $position, &$find, &$len) { |
481 $temp = strlen($find); |
481 $temp = strlen($find); |
482 do { |
482 do { |
483 $position = strpos($source, $find, $position + 1); |
483 $position = strpos($source, $find, $position + 1); |
484 }while($position !== false && !$this->__charNoSlash($source, $position)); |
484 }while($position !== false && !$this->__charNoSlash($source, $position)); |
485 if($position === false) $position = $len - $temp; |
485 if($position === false) $position = $len - $temp; |
486 return $position + $temp; |
486 return $position + $temp; |
487 } |
487 } |
488 |
488 |
489 function __charNoSlash(&$source, &$position) { |
489 function __charNoSlash(&$source, &$position) { |
490 $next = 1; $len = $position - $next; |
490 $next = 1; $len = $position - $next; |
491 while($len > 0 && $source{$len} === '\\') $len = $position - (++$next); |
491 while($len > 0 && $source{$len} === '\\') $len = $position - (++$next); |
492 return (($next - 1) % 2 === 0); |
492 return (($next - 1) % 2 === 0); |
493 } |
493 } |
494 } |
494 } |
495 |
495 |
496 /** |
496 /** |
497 * Wrapper for the JavaScriptCompressor class. |
497 * Wrapper for the JavaScriptCompressor class. |
498 * @param string Javascript code to compact. If this doesn't contain any newline characters, will be treated as a filename. |
498 * @param string Javascript code to compact. If this doesn't contain any newline characters, will be treated as a filename. |