001/** 002 * 003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved. 004 * 005 * This library is free software; you can redistribute it and/or 006 * modify it under the terms of the GNU Lesser General Public 007 * License as published by the Free Software Foundation; either 008 * version 2.1 of the License, or (at your option) any later version. 009 * 010 * This library is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013 * Lesser General Public License for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public 016 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 017 * 018 **/ 019package lucee.transformer.util; 020 021import java.io.IOException; 022import java.io.InputStream; 023import java.nio.charset.Charset; 024import java.util.ArrayList; 025 026import lucee.commons.io.IOUtil; 027import lucee.commons.io.SystemUtil; 028import lucee.commons.lang.ClassUtil; 029import lucee.runtime.PageSource; 030import lucee.transformer.bytecode.Position; 031 032/** 033 * this class is a Parser String optimized for the transfomer (CFML Parser) 034 */ 035public final class CFMLString { 036 037 /** 038 * Mindestens einen Space 039 */ 040 public static final short AT_LEAST_ONE_SPACE=0; 041 042 /** 043 * Mindestens ein Space 044 */ 045 public static final short ZERO_OR_MORE_SPACE=1; 046 047 /** 048 * Field <code>pos</code> 049 */ 050 protected int pos=0; 051 /** 052 * Field <code>text</code> 053 */ 054 protected char[] text; 055 /** 056 * Field <code>lcText</code> 057 */ 058 protected char[] lcText; 059 /** 060 * Field <code>lines</code> 061 */ 062 protected Integer[] lines;// TODO to int[] 063 /** 064 * Field <code>file</code> 065 */ 066 protected PageSource ps; 067 068 private Charset charset; 069 070 private boolean writeLog; 071 072 private String source; 073 074 //private static final String NL=System.getProperty("line.separator"); 075 076 077 078 public CFMLString(PageSource ps,Charset charset,boolean writeLog) throws IOException { 079 this.writeLog=writeLog; 080 this.charset=charset; 081 this.ps=ps; 082 this.source=ps.getPhyscalFile().getAbsolutePath(); 083 String content; 084 InputStream is=null; 085 try { 086 is = IOUtil.toBufferedInputStream(ps.getPhyscalFile().getInputStream()); 087 //print.e(ps.getDisplayPath()+":"+ClassUtil.isEncryptedBytecode(is)+":"+ClassUtil.isBytecode(is)); 088 089 if(ClassUtil.isEncryptedBytecode(is))throw new AlreadyClassException(ps.getPhyscalFile(),true); 090 if(ClassUtil.isBytecode(is)) throw new AlreadyClassException(ps.getPhyscalFile(),false); 091 092 content=IOUtil.toString(is,charset); 093 } 094 finally { 095 IOUtil.closeEL(is); 096 } 097 init(ps,content.toString().toCharArray()); 098 } 099 100 /** 101 * Constructor of the class 102 * in this case source file is just for information 103 * @param text 104 * @param charset 105 * @param writeLog 106 * @param ps 107 */ 108 public CFMLString(String text,Charset charset,boolean writeLog,PageSource ps) { 109 init(null,text.toCharArray()); 110 this.charset=charset; 111 this.writeLog=writeLog; 112 this.ps=ps; 113 } 114 115 /** 116 * Constructor of the class 117 * @param text 118 * @param charset 119 */ 120 public CFMLString(String text,Charset charset) { 121 init(null,text.toCharArray()); 122 this.charset=charset; 123 this.writeLog=false; 124 } 125 126 /** 127 * initialize the CFMLString, used by all constructors 128 * @param text 129 */ 130 protected void init(PageSource ps, char[] text) {// TO NOT REMOVE PageSource THIS IS NEEDED by Bytecode refactoring!!!! 131 this.text=text; 132 lcText=new char[text.length]; 133 134 ArrayList<Integer> arr=new ArrayList<Integer>(); 135 136 for(int i=0;i<text.length;i++) { 137 pos=i; 138 if(text[i]=='\n') { 139 arr.add(new Integer(i)); 140 lcText[i]=' '; 141 } 142 else if(text[i]=='\r') { 143 if(isNextRaw('\n')){ 144 lcText[i++]=' '; 145 } 146 arr.add(new Integer(i)); 147 lcText[i]=' '; 148 } 149 else if(text[i]=='\t') lcText[i]=' '; 150 else lcText[i]=Character.toLowerCase(text[i]); 151 } 152 pos=0; 153 arr.add(new Integer(text.length)); 154 lines=arr.toArray(new Integer[arr.size()]); 155 } 156 157 /** 158 * returns if the internal pointer is not on the last positions 159 */ 160 public boolean hasNext() { 161 return pos+1<lcText.length; 162 } 163 164 /** 165 * moves the internal pointer to the next position, no check if the next position is still valid 166 */ 167 public void next(){ 168 pos++; 169 } 170 /** 171 * moves the internal pointer to the previous position, no check if the next position is still valid 172 */ 173 public void previous(){ 174 pos--; 175 } 176 177 /** 178 * returns the character of the current position of the internal pointer 179 */ 180 public char getCurrent() { 181 return text[pos]; 182 } 183 184 /** 185 * returns the lower case representation of the character of the current position 186 */ 187 public char getCurrentLower() { 188 return lcText[pos]; 189 } 190 191 /** 192 * returns the character at the given position 193 */ 194 public char charAt(int pos) { 195 return text[pos]; 196 } 197 198 /** 199 * returns the character at the given position as lower case representation 200 */ 201 public char charAtLower(int pos) { 202 return lcText[pos]; 203 } 204 205 /** 206 * is the character at the next position the same as the character provided by the input parameter 207 */ 208 public boolean isNext(char c) { 209 if(!hasNext()) return false; 210 return lcText[pos+1]==c; 211 } 212 213 private boolean isNextRaw(char c) { 214 if(!hasNext()) return false; 215 return text[pos+1]==c; 216 } 217 218 219 /** 220 * is the character at the current position (internal pointer) in the range of the given input characters? 221 * @param left lower value. 222 * @param right upper value. 223 */ 224 public boolean isCurrentBetween(char left, char right) { 225 if(!isValidIndex()) return false; 226 return lcText[pos]>=left && lcText[pos]<=right; 227 } 228 229 230 /** 231 * returns if the character at the current position (internal pointer) is a valid variable character 232 */ 233 public boolean isCurrentVariableCharacter() { 234 if(!isValidIndex()) return false; 235 return isCurrentLetter() || isCurrentNumber() || isCurrent('$') || isCurrent('_'); 236 } 237 238 /** 239 * returns if the current character is a letter (a-z,A-Z) 240 * @return is a letter 241 */ 242 public boolean isCurrentLetter() { 243 if(!isValidIndex()) return false; 244 return lcText[pos]>='a' && lcText[pos]<='z'; 245 } 246 247 /** 248 * returns if the current character is a number (0-9) 249 * @return is a letter 250 */ 251 public boolean isCurrentNumber() { 252 if(!isValidIndex()) return false; 253 return lcText[pos]>='0' && lcText[pos]<='9'; 254 } 255 256 257 /** 258 * retuns if the current character (internal pointer) is a valid special sign (_, $, Pound Symbol, Euro Symbol) 259 */ 260 public boolean isCurrentSpecial() { 261 if(!isValidIndex()) return false; 262 return lcText[pos]=='_' || lcText[pos]=='$' || lcText[pos]==SystemUtil.CHAR_EURO || lcText[pos]==SystemUtil.CHAR_POUND; 263 } 264 265 /** 266 * is the current character (internal pointer) the same as the given 267 */ 268 public boolean isCurrent(char c) { 269 if(!isValidIndex()) return false; 270 return lcText[pos]==c; 271 } 272 273 /** 274 * forward the internal pointer plus one if the next character is the same as the given input 275 */ 276 public boolean forwardIfCurrent(char c) { 277 if(isCurrent(c)) { 278 pos++; 279 return true; 280 } 281 return false; 282 } 283 284 /** 285 * returns if the current character (internal pointer) and the following are the same as the given input 286 */ 287 public boolean isCurrent(String str) { 288 if(pos+str.length()>lcText.length) return false; 289 for(int i=str.length()-1;i>=0;i--) { 290 if(str.charAt(i)!=lcText[pos+i]) return false; 291 } 292 return true; 293 /*char[] c=str.toCharArray(); 294 // @ todo not shure for length 295 if(pos+c.length>text.length) return false; 296 for(int i=c.length-1;i>=0;i--) { 297 if(c[i]!=lcText[pos+i]) return false; 298 } 299 return true;*/ 300 } 301 302 /** 303 * forwards if the current character (internal pointer) and the following are the same as the given input 304 */ 305 public boolean forwardIfCurrent(String str) { 306 boolean is=isCurrent(str); 307 if(is)pos+=str.length(); 308 return is; 309 } 310 311 /** 312 * @param str string to check against current position 313 * @param startWithSpace if true there must be whitespace at the current position 314 * @return does the criteria match? 315 */ 316 public boolean forwardIfCurrent(String str, boolean startWithSpace) { 317 if(!startWithSpace) return forwardIfCurrent(str); 318 319 int start=pos; 320 if(!removeSpace())return false; 321 322 if(!forwardIfCurrent(str)){ 323 pos=start; 324 return false; 325 } 326 return true; 327 } 328 329 /** 330 * @param str string to check against current position 331 * @param startWithSpace if true there must be whitespace at the current position 332 * @param followedByNoVariableCharacter the character following the string must be a none variable character (!a-z,A-Z,0-9,_$) (not eaten) 333 * @return does the criteria match? 334 */ 335 public boolean forwardIfCurrent(String str, boolean startWithSpace, boolean followedByNoVariableCharacter) { 336 337 int start=pos; 338 if(startWithSpace && !removeSpace())return false; 339 340 if(!forwardIfCurrent(str)){ 341 pos=start; 342 return false; 343 } 344 if(followedByNoVariableCharacter && isCurrentVariableCharacter()) { 345 pos=start; 346 return false; 347 } 348 return true; 349 } 350 351 352 353 354 355 /** 356 * forwards if the current character (internal pointer) and the following are the same as the given input, followed by a none word character 357 */ 358 public boolean forwardIfCurrentAndNoWordAfter(String str) { 359 int c=pos; 360 if(forwardIfCurrent(str)) { 361 if(!isCurrentBetween('a','z') && !isCurrent('_'))return true; 362 } 363 pos=c; 364 return false; 365 } 366 367 /** 368 * forwards if the current character (internal pointer) and the following are the same as the given input, followed by a none word character or a number 369 */ 370 public boolean forwardIfCurrentAndNoVarExt(String str) { 371 int c=pos; 372 if(forwardIfCurrent(str)) { 373 if(!isCurrentBetween('a','z') &&!isCurrentBetween('0','9') && !isCurrent('_'))return true; 374 } 375 pos=c; 376 return false; 377 } 378 379 /** 380 * Gibt zurueck ob first den folgenden Zeichen entspricht, gefolgt von Leerzeichen und second. 381 * @param first Erste Zeichen zum Vergleich (Vor den Leerzeichen). 382 * @param second Zweite Zeichen zum Vergleich (Nach den Leerzeichen). 383 * @return Gibt zurueck ob die eingegebenen Werte dem Inhalt beim aktuellen Stand des Zeigers entsprechen. 384 */ 385 public boolean isCurrent(String first,char second) { 386 int start=pos; 387 if(!forwardIfCurrent(first)) return false; 388 removeSpace(); 389 boolean rtn=isCurrent(second); 390 pos=start; 391 return rtn; 392 } 393 394 /** 395 * Gibt zurueck ob first den folgenden Zeichen entspricht, gefolgt von Leerzeichen und second. 396 * @param first Erstes Zeichen zum Vergleich (Vor den Leerzeichen). 397 * @param second Zweites Zeichen zum Vergleich (Nach den Leerzeichen). 398 * @return Gibt zurueck ob die eingegebenen Werte dem Inhalt beim aktuellen Stand des Zeigers entsprechen. 399 */ 400 public boolean isCurrent(char first,char second) { 401 int start=pos; 402 if(!forwardIfCurrent(first)) return false; 403 removeSpace(); 404 boolean rtn=isCurrent(second); 405 pos=start; 406 return rtn; 407 } 408 409 /** 410 * Gibt zurueck ob first den folgenden Zeichen entspricht, 411 * gefolgt von Leerzeichen und second, 412 * wenn ja wird der Zeiger um die Laenge der uesbereinstimmung nach vorne gestellt. 413 * @param first Erste Zeichen zum Vergleich (Vor den Leerzeichen). 414 * @param second Zweite Zeichen zum Vergleich (Nach den Leerzeichen). 415 * @return Gibt zurueck ob der Zeiger vorwaerts geschoben wurde oder nicht. 416 */ 417 public boolean forwardIfCurrent(String first,char second) { 418 int start=pos; 419 if(!forwardIfCurrent(first)) return false; 420 removeSpace(); 421 boolean rtn=forwardIfCurrent(second); 422 if(!rtn)pos=start; 423 return rtn; 424 } 425 426 /** 427 * Gibt zurueck ob ein Wert folgt und vor und hinterher Leerzeichen folgen. 428 * @param before Definition der Leerzeichen vorher. 429 * @param val Gefolgter Wert der erartet wird. 430 * @param after Definition der Leerzeichen nach dem Wert. 431 * @return Gibt zurueck ob der Zeiger vorwaerts geschoben wurde oder nicht. 432 */ 433 public boolean forwardIfCurrent(short before, String val,short after) { 434 int start=pos; 435 // space before 436 if(before==AT_LEAST_ONE_SPACE) { 437 if(!removeSpace()) return false; 438 } 439 else removeSpace(); 440 441 // value 442 if(!forwardIfCurrent(val)) { 443 setPos(start); 444 return false; 445 } 446 447 // space after 448 if(after==AT_LEAST_ONE_SPACE) { 449 if(!removeSpace()) { 450 setPos(start); 451 return false; 452 } 453 } 454 else removeSpace(); 455 return true; 456 } 457 458 /** 459 * Gibt zurueck ob first den folgenden Zeichen entspricht, 460 * gefolgt von Leerzeichen und second, 461 * wenn ja wird der Zeiger um die Laenge der uebereinstimmung nach vorne gestellt. 462 * @param first Erste Zeichen zum Vergleich (Vor den Leerzeichen). 463 * @param second Zweite Zeichen zum Vergleich (Nach den Leerzeichen). 464 * @return Gibt zurueck ob der Zeiger vorwaerts geschoben wurde oder nicht. 465 */ 466 public boolean forwardIfCurrent(char first,char second) { 467 int start=pos; 468 if(!forwardIfCurrent(first)) return false; 469 removeSpace(); 470 boolean rtn=forwardIfCurrent(second); 471 if(!rtn)pos=start; 472 return rtn; 473 } 474 475 /** 476 * Gibt zurueck ob first den folgenden Zeichen entspricht, gefolgt von Leerzeichen und second. 477 * @param first Erste Zeichen zum Vergleich (Vor den Leerzeichen). 478 * @param second Zweite Zeichen zum Vergleich (Nach den Leerzeichen). 479 * @return Gibt zurueck ob die eingegebenen Werte dem Inhalt beim aktuellen Stand des Zeigers entsprechen. 480 */ 481 public boolean isCurrent(String first,String second) { 482 int start=pos; 483 if(!forwardIfCurrent(first)) return false; 484 removeSpace(); 485 boolean rtn=isCurrent(second); 486 pos=start; 487 return rtn; 488 } 489 490 /** 491 * Gibt zurueck ob first den folgenden Zeichen entspricht, 492 * gefolgt von Leerzeichen und second, 493 * wenn ja wird der Zeiger um die Laenge der uebereinstimmung nach vorne gestellt. 494 * @param first Erste Zeichen zum Vergleich (Vor den Leerzeichen). 495 * @param second Zweite Zeichen zum Vergleich (Nach den Leerzeichen). 496 * @return Gibt zurueck ob der Zeiger vorwaerts geschoben wurde oder nicht. 497 */ 498 public boolean forwardIfCurrent(String first,String second) { 499 int start=pos; 500 if(!forwardIfCurrent(first)) return false; 501 if(!removeSpace()){ 502 pos=start; 503 return false; 504 } 505 boolean rtn=forwardIfCurrent(second); 506 if(!rtn)pos=start; 507 return rtn; 508 } 509 510 public boolean forwardIfCurrent(String first,String second,String third) { 511 int start=pos; 512 if(!forwardIfCurrent(first)) return false; 513 514 if(!removeSpace()){ 515 pos=start; 516 return false; 517 } 518 519 if(!forwardIfCurrent(second)){ 520 pos=start; 521 return false; 522 } 523 524 if(!removeSpace()){ 525 pos=start; 526 return false; 527 } 528 529 boolean rtn=forwardIfCurrent(third); 530 if(!rtn)pos=start; 531 return rtn; 532 } 533 534 public boolean forwardIfCurrent(String first,String second,String third, boolean startWithSpace) { 535 if(!startWithSpace) return forwardIfCurrent(first, second, third); 536 int start=pos; 537 538 if(!removeSpace())return false; 539 540 if(!forwardIfCurrent(first,second,third)){ 541 pos=start; 542 return false; 543 } 544 return true; 545 } 546 547 public boolean forwardIfCurrent(String first,String second,String third, boolean startWithSpace, boolean followedByNoVariableCharacter) { 548 int start=pos; 549 550 if(startWithSpace && !removeSpace())return false; 551 552 if(!forwardIfCurrent(first,second,third)){ 553 pos=start; 554 return false; 555 } 556 if(followedByNoVariableCharacter && isCurrentVariableCharacter()) { 557 pos=start; 558 return false; 559 } 560 return true; 561 } 562 563 564 public boolean forwardIfCurrent(String first,String second, boolean startWithSpace, boolean followedByNoVariableCharacter) { 565 int start=pos; 566 567 if(startWithSpace && !removeSpace())return false; 568 569 if(!forwardIfCurrent(first,second)){ 570 pos=start; 571 return false; 572 } 573 if(followedByNoVariableCharacter && isCurrentVariableCharacter()) { 574 pos=start; 575 return false; 576 } 577 return true; 578 } 579 580 581 582 public boolean forwardIfCurrent(String first,String second,String third, String forth) { 583 int start=pos; 584 if(!forwardIfCurrent(first)) return false; 585 586 if(!removeSpace()){ 587 pos=start; 588 return false; 589 } 590 591 if(!forwardIfCurrent(second)){ 592 pos=start; 593 return false; 594 } 595 596 if(!removeSpace()){ 597 pos=start; 598 return false; 599 } 600 601 602 if(!forwardIfCurrent(third)){ 603 pos=start; 604 return false; 605 } 606 607 if(!removeSpace()){ 608 pos=start; 609 return false; 610 } 611 612 boolean rtn=forwardIfCurrent(forth); 613 if(!rtn)pos=start; 614 return rtn; 615 616 } 617 618 619 /** 620 * Gibt zurueck ob sich vor dem aktuellen Zeichen Leerzeichen befinden. 621 * @return Gibt zurueck ob sich vor dem aktuellen Zeichen Leerzeichen befinden. 622 */ 623 public boolean hasSpaceBefore() { 624 return pos > 0 && lcText[pos - 1] == ' '; 625 } 626 627 public boolean hasNLBefore() { 628 int index=0; 629 while(pos-(++index) >= 0){ 630 if(text[pos - index] == '\n')return true; 631 if(text[pos - index] == '\r')return true; 632 if(lcText[pos - index] != ' ') return false; 633 } 634 return false; 635 } 636 637 /** 638 * Stellt den Zeiger nach vorne, wenn er sich innerhalb von Leerzeichen befindet, 639 * bis die Leerzeichen fertig sind. 640 * @return Gibt zurueck ob der Zeiger innerhalb von Leerzeichen war oder nicht. 641 */ 642 public boolean removeSpace() { 643 int start=pos; 644 while(pos<lcText.length && lcText[pos]==' ') { 645 pos++; 646 } 647 return (start<pos); 648 } 649 650 public void revertRemoveSpace() { 651 while(hasSpaceBefore()){ 652 previous(); 653 } 654 } 655 656 public String removeAndGetSpace() { 657 int start=pos; 658 while(pos<lcText.length && lcText[pos]==' ') { 659 pos++; 660 } 661 return substring(start,pos-start); 662 } 663 664 /** 665 * Stellt den internen Zeiger an den Anfang der naechsten Zeile, 666 * gibt zurueck ob eine weitere Zeile existiert oder ob es bereits die letzte Zeile war. 667 * @return Existiert eine weitere Zeile. 668 */ 669 public boolean nextLine() { 670 while(isValidIndex() && text[pos]!='\n' && text[pos]!='\r') { 671 next(); 672 } 673 if(!isValidIndex()) return false; 674 675 if(text[pos]=='\n') { 676 next(); 677 return isValidIndex(); 678 } 679 if(text[pos]=='\r') { 680 next(); 681 if(isValidIndex() && text[pos]=='\n') { 682 next(); 683 } 684 return isValidIndex(); 685 } 686 return false; 687 } 688 689 /** 690 * Gibt eine Untermenge des CFMLString als Zeichenkette zurueck, 691 * ausgehend von start bis zum Ende des CFMLString. 692 * @param start Von wo aus die Untermege ausgegeben werden soll. 693 * @return Untermenge als Zeichenkette 694 */ 695 public String substring(int start) { 696 return substring(start,lcText.length-start); 697 } 698 699 /** 700 * Gibt eine Untermenge des CFMLString als Zeichenkette zurueck, 701 * ausgehend von start mit einer maximalen Laenge count. 702 * @param start Von wo aus die Untermenge ausgegeben werden soll. 703 * @param count Wie lange die zurueckgegebene Zeichenkette maximal sein darf. 704 * @return Untermenge als Zeichenkette. 705 */ 706 public String substring(int start, int count) { 707 return String.valueOf(text,start,count); 708 } 709 710 /** 711 * Gibt eine Untermenge des CFMLString als Zeichenkette in Kleinbuchstaben zurueck, 712 * ausgehend von start bis zum Ende des CFMLString. 713 * @param start Von wo aus die Untermenge ausgegeben werden soll. 714 * @return Untermenge als Zeichenkette in Kleinbuchstaben. 715 */ 716 public String substringLower(int start) { 717 return substringLower(start,lcText.length-start); 718 } 719 720 /** 721 * Gibt eine Untermenge des CFMLString als Zeichenkette in Kleinbuchstaben zurueck, 722 * ausgehend von start mit einer maximalen Laenge count. 723 * @param start Von wo aus die Untermenge ausgegeben werden soll. 724 * @param count Wie lange die zurueckgegebene Zeichenkette maximal sein darf. 725 * @return Untermenge als Zeichenkette in Kleinbuchstaben. 726 */ 727 public String substringLower(int start, int count) { 728 return String.valueOf(lcText,start,count); 729 } 730 731 /** 732 * Gibt eine Untermenge des CFMLString als CFMLString zurueck, 733 * ausgehend von start bis zum Ende des CFMLString. 734 * @param start Von wo aus die Untermenge ausgegeben werden soll. 735 * @return Untermenge als CFMLString 736 */ 737 public CFMLString subCFMLString(int start) { 738 return subCFMLString(start,text.length-start); 739 } 740 741 /** 742 * Gibt eine Untermenge des CFMLString als CFMLString zurueck, 743 * ausgehend von start mit einer maximalen Laenge count. 744 * @param start Von wo aus die Untermenge ausgegeben werden soll. 745 * @param count Wie lange die zurueckgegebene Zeichenkette maximal sein darf. 746 * @return Untermenge als CFMLString 747 */ 748 public CFMLString subCFMLString(int start, int count) { 749 return new CFMLString(String.valueOf(text,start,count),charset,writeLog,ps); 750 751 } 752 753 /** Gibt den CFMLString als String zurueck. 754 * @see java.lang.Object#toString() 755 */ 756 public String toString() { 757 return new String(this.text); 758 } 759 760 /** 761 * Gibt die aktuelle Position des Zeigers innerhalb des CFMLString zurueck. 762 * @return Position des Zeigers 763 */ 764 public int getPos() { 765 return pos; 766 } 767 768 /** 769 * Setzt die Position des Zeigers innerhalb des CFMLString, ein ungueltiger index wird ignoriert. 770 * @param pos Position an die der Zeiger gestellt werde soll. 771 */ 772 public void setPos(int pos) { 773 this.pos= pos; 774 } 775 776 /** 777 * Gibt die aktuelle Zeile zurueck in der der Zeiger des CFMLString steht. 778 * @return Zeilennummer 779 */ 780 public int getLine() { 781 return getLine(pos); 782 } 783 784 785 public Position getPosition() { 786 return getPosition(pos); 787 } 788 789 public Position getPosition(int pos) { 790 int line=0; 791 int posAtStart=0; 792 for(int i=0;i<lines.length;i++) { 793 if(pos<=lines[i].intValue()) { 794 line=i+1; 795 if(i>0)posAtStart=lines[i-1].intValue(); 796 break; 797 } 798 } 799 if(line==0) 800 throw new RuntimeException("syntax error"); 801 802 int column=pos-posAtStart; 803 804 return new Position(line,column,pos); 805 } 806 807 808 809 810 811 /** 812 * Gibt zurueck in welcher Zeile die angegebene Position ist. 813 * @param pos Position von welcher die Zeile erfragt wird 814 * @return Zeilennummer 815 */ 816 public int getLine(int pos) { 817 for(int i=0;i<lines.length;i++) { 818 if(pos<=lines[i].intValue()) 819 return i+1; 820 } 821 return lines.length; 822 } 823 824 /** 825 * Gibt die Stelle in der aktuelle Zeile zurueck, in welcher der Zeiger steht. 826 * @return Position innerhalb der Zeile. 827 */ 828 public int getColumn() { 829 return getColumn(pos); 830 } 831 832 /** 833 * Gibt die Stelle in der Zeile auf die pos zeigt zurueck. 834 * @param pos Position von welcher die Zeile erfragt wird 835 * @return Position innerhalb der Zeile. 836 */ 837 public int getColumn(int pos) { 838 int line=getLine(pos)-1; 839 if(line==0) return pos+1; 840 return pos-lines[line-1].intValue(); 841 } 842 843 /** 844 * Gibt die Zeile auf welcher der Zeiger steht als String zurueck. 845 * @return Zeile als Zeichenkette 846 */ 847 public String getLineAsString() { 848 return getLineAsString(getLine(pos)); 849 } 850 /** 851 * Gibt die angegebene Zeile als String zurueck. 852 * @param line Zeile die zurueck gegeben werden soll 853 * @return Zeile als Zeichenkette 854 */ 855 public String getLineAsString(int line) { 856 int index=line-1; 857 if(lines.length<=index) return null; 858 int max=lines[index].intValue(); 859 int min=0; 860 if(index!=0) 861 min=lines[index-1].intValue()+1; 862 863 if(min<max && max-1<lcText.length) 864 return this.substring(min, max-min); 865 return ""; 866 } 867 868 /** 869 * Gibt zurueck ob der Zeiger auf dem letzten Zeichen steht. 870 * @return Gibt zurueck ob der Zeiger auf dem letzten Zeichen steht. 871 */ 872 public boolean isLast() { 873 return pos==lcText.length-1; 874 } 875 876 /** 877 * Gibt zurueck ob der Zeiger nach dem letzten Zeichen steht. 878 * @return Gibt zurueck ob der Zeiger nach dem letzten Zeichen steht. 879 */ 880 public boolean isAfterLast() { 881 return pos>=lcText.length; 882 } 883 /** 884 * Gibt zurueck ob der Zeiger einen korrekten Index hat. 885 * @return Gibt zurueck ob der Zeiger einen korrekten Index hat. 886 */ 887 public boolean isValidIndex() { 888 return pos<lcText.length && pos>-1; 889 } 890 891 /** 892 * Gibt zurueck, ausgehend von der aktuellen Position, 893 * wann das naechste Zeichen folgt das gleich ist wie die Eingabe, 894 * falls keines folgt wird -1 zurueck gegeben. 895 * Gross- und Kleinschreibung der Zeichen werden igoriert. 896 * @param c gesuchtes Zeichen 897 * @return Zeichen das gesucht werden soll. 898 */ 899 public int indexOfNext(char c) { 900 for(int i=pos;i<lcText.length;i++) { 901 if(lcText[i]==c) return i; 902 } 903 return -1; 904 } 905 906 /** 907 * Gibt das letzte Wort das sich vor dem aktuellen Zeigerstand befindet zurueck, 908 * falls keines existiert wird null zurueck gegeben. 909 * @return Word vor dem aktuellen Zeigerstand. 910 */ 911 public String lastWord() { 912 int size = 1; 913 while (pos - size > 0 && lcText[pos - size] == ' ') { 914 size++; 915 } 916 while (pos - size > 0 917 && lcText[pos - size] != ' ' 918 && lcText[pos - size] != ';') { 919 size++; 920 } 921 return this.substring((pos - size + 1), (pos - 1)); 922 } 923 924 /** 925 * Gibt die Laenge des CFMLString zurueck. 926 * @return Laenge des CFMLString. 927 */ 928 public int length() { 929 return lcText.length; 930 } 931 932 /** 933 * Gibt die Quelle aus dem der CFML Code stammt als File Objekt zurueck, 934 * falls dies nicht aud einem File stammt wird null zurueck gegeben. 935 * @return source Quelle des CFML Code. 936 */ 937 public PageSource getPageSource() { 938 return ps; 939 } 940 941 /** 942 * Prueft ob das uebergebene Objekt diesem Objekt entspricht. 943 * @param o Object zum vergleichen. 944 * @return Ist das uebergebene Objekt das selbe wie dieses. 945 */ 946 public boolean equals(Object o) { 947 if(!(o instanceof CFMLString))return false; 948 return o.toString().equals(this.toString()); 949 } 950 951 public String getCharset() { 952 return charset.name(); // FUTURE return Charset 953 } 954 955 956 public boolean getWriteLog() { 957 return writeLog; 958 } 959 960 961 public String getText() { 962 return new String(text); 963 } 964 965 966 967 /** 968 * @return the source 969 */ 970 public String getSource() { 971 return source; 972 } 973}