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.runtime.regexp.joni;
  21 
  22 import jdk.nashorn.internal.runtime.regexp.joni.encoding.IntHolder;
  23 import jdk.nashorn.internal.runtime.regexp.joni.exception.ErrorMessages;
  24 
  25 abstract class ScannerSupport extends IntHolder implements ErrorMessages {
  26 
  27     protected final char[] chars;       // pattern
  28     protected int p;                    // current scanner position
  29     protected int stop;                 // pattern end (mutable)
  30     private int lastFetched;            // last fetched value for unfetch support
  31     protected int c;                    // current code point
  32 
  33     private final int begin;            // pattern begin position for reset() support
  34     private final int end;              // pattern end position for reset() support
  35     protected int _p;                   // used by mark()/restore() to mark positions
  36 
  37     private final static int INT_SIGN_BIT = 1 << 31;
  38 
  39     protected ScannerSupport(final char[] chars, final int p, final int end) {
  40         this.chars = chars;
  41         this.begin = p;
  42         this.end = end;
  43 
  44         reset();
  45     }
  46 
  47     protected int getBegin() {
  48         return begin;
  49     }
  50 
  51     protected int getEnd() {
  52         return end;
  53     }
  54 
  55     protected final int scanUnsignedNumber() {
  56         final int last = c;
  57         int num = 0; // long ???
  58         while(left()) {
  59             fetch();
  60             if (Character.isDigit(c)) {
  61                 final int onum = num;
  62                 num = num * 10 + EncodingHelper.digitVal(c);
  63                 if (((onum ^ num) & INT_SIGN_BIT) != 0) {
  64                     return -1;
  65                 }
  66             } else {
  67                 unfetch();
  68                 break;
  69             }
  70         }
  71         c = last;
  72         return num;
  73     }
  74 
  75     protected final int scanUnsignedHexadecimalNumber(final int maxLength) {
  76         final int last = c;
  77         int num = 0;
  78         int ml = maxLength;
  79         while(left() && ml-- != 0) {
  80             fetch();
  81             if (EncodingHelper.isXDigit(c)) {
  82                 final int onum = num;
  83                 final int val = EncodingHelper.xdigitVal(c);
  84                 num = (num << 4) + val;
  85                 if (((onum ^ num) & INT_SIGN_BIT) != 0) {
  86                     return -1;
  87                 }
  88             } else {
  89                 unfetch();
  90                 break;
  91             }
  92         }
  93         c = last;
  94         return num;
  95     }
  96 
  97     protected final int scanUnsignedOctalNumber(final int maxLength) {
  98         final int last = c;
  99         int num = 0;
 100         int ml = maxLength;
 101         while(left() && ml-- != 0) {
 102             fetch();
 103             if (Character.isDigit(c) && c < '8') {
 104                 final int onum = num;
 105                 final int val = EncodingHelper.odigitVal(c);
 106                 num = (num << 3) + val;
 107                 if (((onum ^ num) & INT_SIGN_BIT) != 0) {
 108                     return -1;
 109                 }
 110             } else {
 111                 unfetch();
 112                 break;
 113             }
 114         }
 115         c = last;
 116         return num;
 117     }
 118 
 119     protected final void reset() {
 120         p = begin;
 121         stop = end;
 122     }
 123 
 124     protected final void mark() {
 125         _p = p;
 126     }
 127 
 128     protected final void restore() {
 129         p = _p;
 130     }
 131 
 132     protected final void inc() {
 133         lastFetched = p;
 134         p++;
 135     }
 136 
 137     protected final void fetch() {
 138         lastFetched = p;
 139         c = chars[p++];
 140     }
 141 
 142     protected int fetchTo() {
 143         lastFetched = p;
 144         return chars[p++];
 145     }
 146 
 147     protected final void unfetch() {
 148         p = lastFetched;
 149     }
 150 
 151     protected final int peek() {
 152         return p < stop ? chars[p] : 0;
 153     }
 154 
 155     protected final boolean peekIs(final int ch) {
 156         return peek() == ch;
 157     }
 158 
 159     protected final boolean left() {
 160         return p < stop;
 161     }
 162 
 163 }