1 /*
   2  * Permission is hereby granted, free of charge, to any person obtaining a copy of
   3  * this software and associated documentation files (the "Software"), to deal in
   4  * the Software without restriction, including without limitation the rights to
   5  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
   6  * of the Software, and to permit persons to whom the Software is furnished to do
   7  * so, subject to the following conditions:
   8  *
   9  * The above copyright notice and this permission notice shall be included in all
  10  * copies or substantial portions of the Software.
  11  *
  12  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  13  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  14  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  15  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  16  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  17  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  18  * SOFTWARE.
  19  */
  20 package jdk.nashorn.internal.joni;
  21 
  22 import jdk.nashorn.internal.joni.encoding.IntHolder;
  23 import jdk.nashorn.internal.joni.exception.ErrorMessages;
  24 import jdk.nashorn.internal.joni.exception.InternalException;
  25 import jdk.nashorn.internal.joni.exception.SyntaxException;
  26 import jdk.nashorn.internal.joni.exception.ValueException;
  27 
  28 abstract class ScannerSupport extends IntHolder implements ErrorMessages {
  29 
  30     protected final char[] chars;       // pattern
  31     protected int p;                    // current scanner position
  32     protected int stop;                 // pattern end (mutable)
  33     private int lastFetched;            // last fetched value for unfetch support
  34     protected int c;                    // current code point
  35 
  36     private final int begin;            // pattern begin position for reset() support
  37     private final int end;              // pattern end position for reset() support
  38     protected int _p;                   // used by mark()/restore() to mark positions
  39 
  40     protected ScannerSupport(char[] chars, int p, int end) {
  41         this.chars = chars;
  42         this.begin = p;
  43         this.end = end;
  44 
  45         reset();
  46     }
  47 
  48     protected int getBegin() {
  49         return begin;
  50     }
  51 
  52     protected int getEnd() {
  53         return end;
  54     }
  55 
  56     private final int INT_SIGN_BIT = 1 << 31;
  57 
  58     protected final int scanUnsignedNumber() {
  59         int last = c;
  60         int num = 0; // long ???
  61         while(left()) {
  62             fetch();
  63             if (Character.isDigit(c)) {
  64                 int onum = num;
  65                 num = num * 10 + EncodingHelper.digitVal(c);
  66                 if (((onum ^ num) & INT_SIGN_BIT) != 0) return -1;
  67             } else {
  68                 unfetch();
  69                 break;
  70             }
  71         }
  72         c = last;
  73         return num;
  74     }
  75 
  76     protected final int scanUnsignedHexadecimalNumber(int maxLength) {
  77         int last = c;
  78         int num = 0;
  79         while(left() && maxLength-- != 0) {
  80             fetch();
  81             if (EncodingHelper.isXDigit(c)) {
  82                 int onum = num;
  83                 int val = EncodingHelper.xdigitVal(c);
  84                 num = (num << 4) + val;
  85                 if (((onum ^ num) & INT_SIGN_BIT) != 0) return -1;
  86             } else {
  87                 unfetch();
  88                 break;
  89             }
  90         }
  91         c = last;
  92         return num;
  93     }
  94 
  95     protected final int scanUnsignedOctalNumber(int maxLength) {
  96         int last = c;
  97         int num = 0;
  98         while(left() && maxLength-- != 0) {
  99             fetch();
 100             if (Character.isDigit(c) && c < '8') {
 101                 int onum = num;
 102                 int val = EncodingHelper.odigitVal(c);
 103                 num = (num << 3) + val;
 104                 if (((onum ^ num) & INT_SIGN_BIT) != 0) return -1;
 105             } else {
 106                 unfetch();
 107                 break;
 108             }
 109         }
 110         c = last;
 111         return num;
 112     }
 113 
 114     protected final void reset() {
 115         p = begin;
 116         stop = end;
 117     }
 118 
 119     protected final void mark() {
 120         _p = p;
 121     }
 122 
 123     protected final void restore() {
 124         p = _p;
 125     }
 126 
 127     protected final void inc() {
 128         lastFetched = p;
 129         p++;
 130     }
 131 
 132     protected final void fetch() {
 133         lastFetched = p;
 134         c = chars[p++];
 135     }
 136 
 137     protected int fetchTo() {
 138         lastFetched = p;
 139         return chars[p++];
 140     }
 141 
 142     protected final void unfetch() {
 143         p = lastFetched;
 144     }
 145 
 146     protected final int peek() {
 147         return p < stop ? chars[p] : 0;
 148     }
 149 
 150     protected final boolean peekIs(int c) {
 151         return peek() == c;
 152     }
 153 
 154     protected final boolean left() {
 155         return p < stop;
 156     }
 157 
 158     protected void newSyntaxException(String message) {
 159         throw new SyntaxException(message);
 160     }
 161 
 162     protected void newValueException(String message) {
 163         throw new ValueException(message);
 164     }
 165 
 166     protected void newValueException(String message, String str) {
 167         throw new ValueException(message, str);
 168     }
 169 
 170     protected void newValueException(String message, int p, int end) {
 171         throw new ValueException(message, new String(chars, p, end - p));
 172     }
 173 
 174     protected void newInternalException(String message) {
 175         throw new InternalException(message);
 176     }
 177 
 178 }