1
+ − 1
<?php
+ − 2
+ − 3
/*
+ − 4
* Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
318
+ − 5
* Version 1.0.6 (Roane)
1
+ − 6
* Copyright (C) 2006-2007 Dan Fuhry
+ − 7
* Javascript compression library - used to compact the client-side Javascript code (all 72KB of it!) to save some bandwidth
+ − 8
*
+ − 9
* This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
+ − 10
* as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ − 11
*
+ − 12
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ − 13
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
+ − 14
*
+ − 15
* This class was written by Andrea Giammarchi and was downloaded from PHPClasses.org. The information page stated that
+ − 16
* this class is licensed under the GNU General Public License, the terms of which can be found by reading the file
+ − 17
* "GPL" included with the Enano package.
+ − 18
*/
+ − 19
+ − 20
/**
+ − 21
* JavaScriptCompressor class,
+ − 22
* removes comments or pack JavaScript source[s] code.
+ − 23
* ______________________________________________________________
+ − 24
* JavaScriptCompressor (just 2 public methods)
+ − 25
* |
+ − 26
* |________ getClean(jsSource:mixed):string
+ − 27
* | returns one or more JavaScript code without comments,
+ − 28
* | by default removes some spaces too
+ − 29
* |
+ − 30
* |________ getPacked(jsSource:mixed):string
+ − 31
* returns one or more JavaScript code packed,
+ − 32
* using getClean and obfuscating output
+ − 33
* --------------------------------------------------------------
+ − 34
* Note about $jsSource input varible:
+ − 35
* this var should be a string (i.e. $jsSource = file_get_contents("myFile.js");)
+ − 36
* should be an array of strings (i.e. array(file_get_contents("1.js"), file_get_contents("2.js"), ... ))
+ − 37
* should be an array with 1 or 2 keys:
+ − 38
* (i.e. array('code'=>file_get_contents("mySource.js")))
+ − 39
* (i.e. array('code'=>file_get_contents("mySource.js"), 'name'=>'mySource'))
+ − 40
* ... and should be an array of arrays created with theese rules
+ − 41
* array(
+ − 42
* file_get_contents("secret.js"),
+ − 43
* array('code'=>$anotherJS),
+ − 44
* array('code'=>$myJSapplication, 'name'=>'JSApplication V 1.0')
+ − 45
* )
+ − 46
*
+ − 47
* The name used on dedicated key, will be write on parsed source header
+ − 48
* --------------------------------------------------------------
+ − 49
* Note about returned strings:
+ − 50
* Your browser should wrap very long strings, then don't use
+ − 51
* cut and paste from your browser, save output into your database or directly
+ − 52
* in a file or print them only inside <script> and </script> tags
+ − 53
* --------------------------------------------------------------
+ − 54
* Note about parser performance:
+ − 55
* With pure PHP embed code this class should be slow and not really safe
+ − 56
* for your server performance then don't parse JavaScript runtime for each
+ − 57
* file you need and create some "parsed" caching system
+ − 58
* (at least while i've not created a compiled version of theese class functions).
+ − 59
* Here there's a caching system example: http://www.phpclasses.org/browse/package/3158.html
+ − 60
* --------------------------------------------------------------
+ − 61
* Note about JavaScript packed compatibility:
+ − 62
* To be sure about compatibility include before every script JSL Library:
+ − 63
* http://www.devpro.it/JSL/
+ − 64
* JSL library add some features for old or buggy browsers, one of
+ − 65
* those functions is String.replace with function as second argument,
+ − 66
* used by JavaScript generated packed code to rebuild original code.
+ − 67
*
+ − 68
* Remember that KDE 3.5, Safari and IE5 will not work correctly with packed version
+ − 69
* if you'll not include JSL.
+ − 70
* --------------------------------------------------------------
+ − 71
* @Compatibility >= PHP 4
+ − 72
* @Author Andrea Giammarchi
+ − 73
* @see http://www.devpro.it/
+ − 74
* @since 2006/05/31
+ − 75
* @since 2006/08/01 [requires SourceMap.class.php to parse source faster and better (dojo.js.uncompressed.js file (211Kb) successfull cleaned or packed)]
+ − 76
* @version 0.8
+ − 77
* Dependencies:
+ − 78
* Server: BaseConvert.class.php
+ − 79
* Server: SourceMap.class.php
+ − 80
* Client: JSL.js (http://www.devpro.it/JSL/)
+ − 81
* Convertion is supported by every browser with JSL Library (FF 1+ Opera 8+ and IE5.5+ are supported without JSL too)
+ − 82
* @copyright Dean Edwards for his originally idea [dean.edwards.name] and his JavaScript packer
+ − 83
*/
+ − 84
class JavaScriptCompressor {
+ − 85
+ − 86
/**
+ − 87
* public variables
+ − 88
* stats:string after every compression has some informations
+ − 89
* version:string version of this class
+ − 90
*/
+ − 91
var $stats = '',
+ − 92
$version = '0.8';
+ − 93
+ − 94
/** 'private' variables, any comment sorry */
+ − 95
var $__startTime = 0,
+ − 96
$__sourceLength = 0,
+ − 97
$__sourceNewLength = 0,
+ − 98
$__totalSources = 0,
+ − 99
$__sources = array(),
+ − 100
$__delimeter = array(),
+ − 101
$__cleanFinder = array("/(\n|\r)+/", "/( |\t)+/", "/(\n )|( \n)|( \n )/", "/[[:space:]]+(\)|})/", "/(\(|{)[[:space:]]+/", "/[[:space:]]*(;|,|:|<|>|\&|\||\=|\?|\+|\-|\%)[[:space:]]*/", "/\)[[:space:]]+{/", "/}[[:space:]]+\(/"),
+ − 102
$__cleanReplacer = array("\n", " ", "\n", "\\1", "\\1", "\\1", "){", "}("),
+ − 103
$__BC = null,
+ − 104
$__SourceMap = null;
+ − 105
+ − 106
/**
+ − 107
* public constructor
+ − 108
* creates a new BaseConvert class variable (base 36)
+ − 109
*/
+ − 110
function JavaScriptCompressor() {
+ − 111
$this->__SourceMap = new SourceMap();
+ − 112
$this->__BC = new BaseConvert('0123456789abcdefghijklmnopqrstuvwxyz');
+ − 113
$this->__delimeter = array(
+ − 114
array('name'=>'doublequote', 'start'=>'"', 'end'=>'"', 'noslash'=>true),
+ − 115
array('name'=>'singlequote', 'start'=>"'", 'end'=>"'", 'noslash'=>true),
+ − 116
array('name'=>'singlelinecomment', 'start'=>'//', 'end'=>array("\n", "\r")),
+ − 117
array('name'=>'multilinecomment', 'start'=>'/*', 'end'=>'*/'),
+ − 118
array('name'=>'regexp', 'start'=>'/', 'end'=>'/', 'match'=>"/^\/[^\n\r]+\/$/", 'noslash'=>true)
+ − 119
);
+ − 120
}
+ − 121
+ − 122
/**
+ − 123
* public method
+ − 124
* getClean(mixed [, bool]):string
+ − 125
* compress JavaScript removing comments and somespaces (on by default)
+ − 126
* @param mixed view example and notes on class comments
+ − 127
*/
+ − 128
function getClean($jsSource) {
+ − 129
return $this->__commonInitMethods($jsSource, false);
+ − 130
}
+ − 131
+ − 132
/**
+ − 133
* public method
+ − 134
* getPacked(mixed):string
+ − 135
* compress JavaScript replaceing words and removing comments and some spaces
+ − 136
* @param mixed view example and notes on class comments
+ − 137
*/
+ − 138
function getPacked($jsSource) {
+ − 139
return $this->__commonInitMethods($jsSource, true);
+ − 140
}
+ − 141
+ − 142
/** 'private' methods, any comment sorry */
+ − 143
function __addCleanCode($str) {
+ − 144
return preg_replace($this->__cleanFinder, $this->__cleanReplacer, trim($str));
+ − 145
}
+ − 146
function __addClean(&$arr, &$str, &$start, &$end, $clean) {
+ − 147
if($clean)
+ − 148
array_push($arr, $this->__addCleanCode(substr($str, $start, $end - $start)));
+ − 149
else
+ − 150
array_push($arr, substr($str, $start, $end - $start));
+ − 151
}
+ − 152
function __clean(&$str) {
+ − 153
$len = strlen($str);
+ − 154
$type = '';
+ − 155
$clean = array();
+ − 156
$map = $this->__SourceMap->getMap($str, $this->__delimeter);
+ − 157
for($a = 0, $b = 0, $c = count($map); $a < $c; $a++) {
+ − 158
$type = &$map[$a]['name'];
+ − 159
switch($type) {
+ − 160
case 'code':
+ − 161
case 'regexp':
+ − 162
case 'doublequote':
+ − 163
case 'singlequote':
+ − 164
$this->__addClean($clean, $str, $map[$a]['start'], $map[$a]['end'], ($type === 'code'));
+ − 165
if($type !== 'regexp')
+ − 166
array_push($clean, "\n");
+ − 167
break;
+ − 168
}
+ − 169
}
+ − 170
return preg_replace("/(\n)+/", "\n", trim(implode('', $clean)));
+ − 171
}
+ − 172
function __commonInitMethods(&$jsSource, $packed) {
+ − 173
$header = '';
+ − 174
$this->__startTime = $this->__getTime();
+ − 175
$this->__sourceLength = 0;
+ − 176
$this->__sourceManager($jsSource);
+ − 177
for($a = 0, $b = $this->__totalSources; $a < $b; $a++)
+ − 178
$this->__sources[$a]['code'] = $this->__clean($this->__sources[$a]['code']);
+ − 179
$header = $this->__getHeader();
+ − 180
for($a = 0, $b = $this->__totalSources; $a < $b; $a++)
+ − 181
$this->__sources[$a] = &$this->__sources[$a]['code'];
+ − 182
$this->__sources = implode(';', $this->__sources);
+ − 183
if($packed)
+ − 184
$this->__sources = $this->__pack($this->__sources);
+ − 185
$this->__sourceNewLength = strlen($this->__sources);
+ − 186
$this->__setStats();
+ − 187
return $header.$this->__sources;
+ − 188
}
+ − 189
function __getHeader() {
+ − 190
return implode('', array(
+ − 191
'/* ',$this->__getScriptNames(),'JavaScriptCompressor ',$this->version,' [www.devpro.it], ',
+ − 192
'thanks to Dean Edwards for idea [dean.edwards.name]',
+ − 193
" */\r\n"
+ − 194
));
+ − 195
}
+ − 196
function __getScriptNames() {
+ − 197
$a = 0;
+ − 198
$result = array();
+ − 199
for($b = $this->__totalSources; $a < $b; $a++) {
+ − 200
if($this->__sources[$a]['name'] !== '')
+ − 201
array_push($result, $this->__sources[$a]['name']);
+ − 202
}
+ − 203
$a = count($result);
+ − 204
if($a-- > 0)
+ − 205
$result[$a] .= ' with ';
+ − 206
return $a < 0 ? '' : implode(', ', $result);
+ − 207
}
+ − 208
function __getSize($size, $dec = 2) {
+ − 209
$toEval = '';
+ − 210
$type = array('bytes', 'Kb', 'Mb', 'Gb');
+ − 211
$nsize = $size;
+ − 212
$times = 0;
+ − 213
while($nsize > 1024) {
+ − 214
$nsize = $nsize / 1024;
+ − 215
$toEval .= '/1024';
+ − 216
$times++;
+ − 217
}
+ − 218
if($times === 0)
+ − 219
$fSize = $size.' '.$type[$times];
+ − 220
else {
+ − 221
eval('$size=($size'.$toEval.');');
+ − 222
$fSize = number_format($size, $dec, '.', '').' '.$type[$times];
+ − 223
}
+ − 224
return $fSize;
+ − 225
}
+ − 226
function __getTime($startTime = null) {
+ − 227
list($usec, $sec) = explode(' ', microtime());
+ − 228
$newtime = (float)$usec + (float)$sec;
+ − 229
if($startTime !== null)
+ − 230
$newtime = number_format(($newtime - $startTime), 3);
+ − 231
return $newtime;
+ − 232
}
+ − 233
function __pack(&$str) {
+ − 234
$container = array();
+ − 235
$str = preg_replace("/(\w+)/e", '$this->__BC->toBase($this->__wordsParser("\\1",$container));', $this->__clean($str));
+ − 236
$str = str_replace("\n", '\n', addslashes($str));
+ − 237
return 'eval(function(A,G){return A.replace(/(\\w+)/g,function(a,b){return G[parseInt(b,36)]})}("'.$str.'","'.implode(',', $container).'".split(",")));';
+ − 238
}
+ − 239
function __setStats() {
+ − 240
$this->stats = implode(' ', array(
+ − 241
$this->__getSize($this->__sourceLength),
+ − 242
'to',
+ − 243
$this->__getSize($this->__sourceNewLength),
+ − 244
'in',
+ − 245
$this->__getTime($this->__startTime),
+ − 246
'seconds'
+ − 247
));
+ − 248
}
+ − 249
function __sourceManager(&$jsSource) {
+ − 250
$b = count($jsSource);
+ − 251
$this->__sources = array();
+ − 252
if(is_string($jsSource))
+ − 253
$this->__sourcePusher($jsSource, '');
+ − 254
elseif(is_array($jsSource) && $b > 0) {
+ − 255
if(isset($jsSource['code']))
+ − 256
$this->__sourcePusher($jsSource['code'], (isset($jsSource['name']) ? $jsSource['name'] : ''));
+ − 257
else {
+ − 258
for($a = 0; $a < $b; $a++) {
+ − 259
if(is_array($jsSource[$a]) && isset($jsSource[$a]['code'], $jsSource[$a]['name']))
+ − 260
$this->__sourcePusher($jsSource[$a]['code'], trim($jsSource[$a]['name']));
+ − 261
elseif(is_string($jsSource[$a]))
+ − 262
$this->__sourcePusher($jsSource[$a], '');
+ − 263
}
+ − 264
}
+ − 265
}
+ − 266
$this->__totalSources = count($this->__sources);
+ − 267
}
+ − 268
function __sourcePusher(&$code, $name) {
+ − 269
$this->__sourceLength += strlen($code);
+ − 270
array_push($this->__sources, array('code'=>$code, 'name'=>$name));
+ − 271
}
+ − 272
function __wordsParser($str, &$d) {
+ − 273
if(is_null($key = array_shift($key = array_keys($d,$str))))
+ − 274
$key = array_push($d, $str) - 1;
+ − 275
return $key;
+ − 276
}
+ − 277
}
+ − 278
+ − 279
/**
+ − 280
* BaseConvert class,
+ − 281
* converts an unsigned base 10 integer to a different base and vice versa.
+ − 282
* ______________________________________________________________
+ − 283
* BaseConvert
+ − 284
* |
+ − 285
* |________ constructor(newBase:string)
+ − 286
* | uses newBase string var for convertion
+ − 287
* | [i.e. "0123456789abcdef" for an hex convertion]
+ − 288
* |
+ − 289
* |________ toBase(unsignedInteger:uint):string
+ − 290
* | return base value of input
+ − 291
* |
+ − 292
* |________ fromBase(baseString:string):uint
+ − 293
* return base 10 integer value of base input
+ − 294
* --------------------------------------------------------------
+ − 295
* REMEMBER: PHP < 6 doesn't work correctly with integer greater than 2147483647 (2^31 - 1)
+ − 296
* --------------------------------------------------------------
+ − 297
* @Compatibility >= PHP 4
+ − 298
* @Author Andrea Giammarchi
+ − 299
* @Site http://www.devpro.it/
+ − 300
* @Date 2006/06/05
+ − 301
* @Version 1.0
+ − 302
*/
+ − 303
+ − 304
class BaseConvert {
+ − 305
+ − 306
var $base, $baseLength;
+ − 307
+ − 308
function BaseConvert($base) {
+ − 309
$this->base = &$base;
+ − 310
$this->baseLength = strlen($base);
+ − 311
}
+ − 312
+ − 313
function toBase($num) {
+ − 314
$module = 0; $result = '';
+ − 315
while($num) {
+ − 316
$result = $this->base{($module = $num % $this->baseLength)}.$result;
+ − 317
$num = (int)(($num - $module) / $this->baseLength);
+ − 318
}
+ − 319
return $result !== '' ? $result : $this->base{0};
+ − 320
}
+ − 321
+ − 322
function fromBase($str) {
+ − 323
$pos = 0; $len = strlen($str) - 1; $result = 0;
+ − 324
while($pos < $len)
+ − 325
$result += pow($this->baseLength, ($len - $pos)) * strpos($this->base, $str{($pos++)});
+ − 326
return $len >= 0 ? $result + strpos($this->base, $str{($pos)}) : null;
+ − 327
}
+ − 328
}
+ − 329
+ − 330
/**
+ − 331
* SourceMap class,
+ − 332
* reads a generic language source code and returns its map.
+ − 333
* ______________________________________________________________
+ − 334
* The SourceMap goals is to create a map of a generic script/program language.
+ − 335
* The getMap method returns an array/list of arrays/dictionary/objects
+ − 336
* of source map using delimeters variable to map correctly:
+ − 337
* - multi line comments
+ − 338
* - single line comments
+ − 339
* - double quoted strings
+ − 340
* - single quoted strings
+ − 341
* - pure code
+ − 342
* - everything else (for example regexp [/re/] with javascript), just adding a correct delimeter
+ − 343
* --------------------------------------------------------------
+ − 344
* What about the delimeter
+ − 345
* It's an array/list of arrays/dictionary/obects with some properties to find what you're looking for.
+ − 346
*
+ − 347
* parameters are:
+ − 348
* - name, the name of the delimeter (i.e. "doublequote")
+ − 349
* - start, one or mode chars to find as start delimeter (i.e. " for double quoted string)
+ − 350
* - end, one or mode chars to find as end delimeter (i.e. " for double quoted string) [end should be an array/list too]
+ − 351
*
+ − 352
* optional parameters are:
+ − 353
* - noslash, if true find the end of the delimeter only if last char is not slashed (i.e. "string\"test" find " after test)
+ − 354
* - match, if choosed language has regexp, verify if string from start to end matches used regexp (i.e. /^\/[^\n\r]+\/$/ for JavaScript regexp)
+ − 355
*
+ − 356
* If end parameter is an array, match and noslash are not supported (i.e. ["\n", "\r"] for end delimeter of a single line comment)
+ − 357
* --------------------------------------------------------------
+ − 358
* What about SourceMap usage
+ − 359
* It should be a good solution to create sintax highlighter, parser,
+ − 360
* verifier or some other source code parsing procedure
+ − 361
* --------------------------------------------------------------
+ − 362
* What about SourceMap performance script/languages
+ − 363
* I've created different version of this class to test each script/program language performance too.
+ − 364
* Python with or without Psyco is actually the faster parser.
+ − 365
* However with this PHP version this class has mapped "dojo.js.uncompressed.js" file (about 211Kb) in less than 0.5 second.
+ − 366
* Test has been done with embed class and PHP as module, any accelerator was used for this PHP test.
+ − 367
* --------------------------------------------------------------
+ − 368
* @Compatibility >= PHP 4
+ − 369
* @Author Andrea Giammarchi
+ − 370
* @Site http://www.devpro.it/
+ − 371
* @Date 2006/08/01
+ − 372
* @LastMOd 2006/08/01
+ − 373
* @Version 0.1
+ − 374
* @Application Last version of JavaScriptCompressor class use this one to map source code.
+ − 375
*/
+ − 376
class SourceMap {
+ − 377
+ − 378
/**
+ − 379
* public method
+ − 380
* getMap(&$source:string, &$delimeters:array):array
+ − 381
* Maps the source code using $delimeters rules and returns map as an array
+ − 382
* NOTE: read comments to know more about map and delimeter
+ − 383
*
+ − 384
* @param string generic source code
+ − 385
* @param array array with nested array with code rules
+ − 386
*/
+ − 387
function getMap(&$source, &$delimeters) {
+ − 388
+ − 389
# "unsigned" integer variables
+ − 390
$sourcePosition = 0;
+ − 391
$delimetersPosition = 0;
+ − 392
$findLength = 0;
+ − 393
$len = 0;
+ − 394
$tempIndex = 0;
+ − 395
$sourceLength = strlen($source);
+ − 396
$delimetersLength = count($delimeters);
+ − 397
+ − 398
# integer variables
+ − 399
$tempPosition = -1;
+ − 400
$endPosition = -1;
+ − 401
+ − 402
# array variables
+ − 403
$map = array();
+ − 404
$tempMap = array();
+ − 405
$tempDelimeter = array();
+ − 406
+ − 407
while($sourcePosition < $sourceLength) {
+ − 408
$endPosition = -1;
+ − 409
for($delimetersPosition = 0; $delimetersPosition < $delimetersLength; $delimetersPosition++) {
+ − 410
$tempPosition = strpos($source, $delimeters[$delimetersPosition]['start'], $sourcePosition);
+ − 411
if($tempPosition !== false && ($tempPosition < $endPosition || $endPosition === -1)) {
+ − 412
$endPosition = $tempPosition;
+ − 413
$tempIndex = $delimetersPosition;
+ − 414
}
+ − 415
}
+ − 416
if($endPosition !== -1) {
+ − 417
$sourcePosition = $endPosition;
+ − 418
$tempDelimeter = &$delimeters[$tempIndex];
+ − 419
$findLength = strlen($tempDelimeter['start']);
+ − 420
if(is_array($tempDelimeter['end'])) {
+ − 421
$delimetersPosition = 0;
+ − 422
$endPosition = -1;
+ − 423
for($len = count($tempDelimeter['end']); $delimetersPosition < $len; $delimetersPosition++) {
+ − 424
$tempPosition = strpos($source, $tempDelimeter['end'][$delimetersPosition], $sourcePosition + $findLength);
+ − 425
if($tempPosition !== false && ($tempPosition < $endPosition || $endPosition === -1)) {
+ − 426
$endPosition = $tempPosition;
+ − 427
$tempIndex = $delimetersPosition;
+ − 428
}
+ − 429
}
+ − 430
if($endPosition !== -1)
+ − 431
$endPosition = $endPosition + strlen($tempDelimeter['end'][$tempIndex]);
+ − 432
else
+ − 433
$endPosition = $sourceLength;
+ − 434
array_push($map, array('name'=>$tempDelimeter['name'], 'start'=>$sourcePosition, 'end'=>$endPosition));
+ − 435
$sourcePosition = $endPosition - 1;
+ − 436
}
+ − 437
elseif(isset($tempDelimeter['match'])) {
+ − 438
$tempPosition = strpos($source, $tempDelimeter['end'], $sourcePosition + $findLength);
+ − 439
$len = strlen($tempDelimeter['end']);
+ − 440
if($tempPosition !== false && preg_match($tempDelimeter['match'], substr($source, $sourcePosition, $tempPosition - $sourcePosition + $len))) {
+ − 441
$endPosition = isset($tempDelimeter['noslash']) ? $this->__endCharNoSlash($source, $sourcePosition, $tempDelimeter['end'], $sourceLength) : $tempPosition + $len;
+ − 442
array_push($map, array('name'=>$tempDelimeter['name'], 'start'=>$sourcePosition, 'end'=>$endPosition));
+ − 443
$sourcePosition = $endPosition - 1;
+ − 444
}
+ − 445
}
+ − 446
else {
+ − 447
if(isset($tempDelimeter['noslash']))
+ − 448
$endPosition = $this->__endCharNoSlash($source, $sourcePosition, $tempDelimeter['end'], $sourceLength);
+ − 449
else {
+ − 450
$tempPosition = strpos($source, $tempDelimeter['end'], $sourcePosition + $findLength);
+ − 451
if($tempPosition !== false)
+ − 452
$endPosition = $tempPosition + strlen($tempDelimeter['end']);
+ − 453
else
+ − 454
$endPosition = $sourceLength;
+ − 455
}
+ − 456
array_push($map, array('name'=>$tempDelimeter['name'], 'start'=>$sourcePosition, 'end'=>$endPosition));
+ − 457
$sourcePosition = $endPosition - 1;
+ − 458
}
+ − 459
}
+ − 460
else
+ − 461
$sourcePosition = $sourceLength - 1;
+ − 462
++$sourcePosition;
+ − 463
}
+ − 464
$len = count($map);
+ − 465
if($len === 0)
+ − 466
array_push($tempMap, array('name'=>'code', 'start'=>0, 'end'=>$sourceLength));
+ − 467
else {
+ − 468
for($tempIndex = 0; $tempIndex < $len; $tempIndex++) {
+ − 469
if($tempIndex === 0 && $map[$tempIndex]['start'] > 0)
+ − 470
array_push($tempMap, array('name'=>'code', 'start'=>0, 'end'=>$map[$tempIndex]['start']));
+ − 471
elseif($tempIndex > 0 && $map[$tempIndex]['start'] > $map[$tempIndex-1]['end'])
+ − 472
array_push($tempMap, array('name'=>'code', 'start'=>$map[$tempIndex-1]['end'], 'end'=>$map[$tempIndex]['start']));
+ − 473
array_push($tempMap, array('name'=>$map[$tempIndex]['name'], 'start'=>$map[$tempIndex]['start'], 'end'=>$map[$tempIndex]['end']));
+ − 474
if($tempIndex + 1 === $len && $map[$tempIndex]['end'] < $sourceLength)
+ − 475
array_push($tempMap, array('name'=>'code', 'start'=>$map[$tempIndex]['end'], 'end'=>$sourceLength));
+ − 476
}
+ − 477
}
+ − 478
return $tempMap;
+ − 479
}
+ − 480
+ − 481
function __endCharNoSlash(&$source, $position, &$find, &$len) {
+ − 482
$temp = strlen($find);
+ − 483
do {
+ − 484
$position = strpos($source, $find, $position + 1);
+ − 485
}while($position !== false && !$this->__charNoSlash($source, $position));
+ − 486
if($position === false) $position = $len - $temp;
+ − 487
return $position + $temp;
+ − 488
}
+ − 489
+ − 490
function __charNoSlash(&$source, &$position) {
+ − 491
$next = 1; $len = $position - $next;
+ − 492
while($len > 0 && $source{$len} === '\\') $len = $position - (++$next);
+ − 493
return (($next - 1) % 2 === 0);
+ − 494
}
+ − 495
}
+ − 496
?>