Coverage Report - com.sun.tools.javafx.antlr.StringLiteralProcessor
 
Classes in this File Line Coverage Branch Coverage Complexity
StringLiteralProcessor
91%
80/88
65%
41/63
0
 
 1  
 /*
 2  
  * Copyright 1999-2007 Sun Microsystems, Inc.  All Rights Reserved.
 3  
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 4  
  *
 5  
  * This code is free software; you can redistribute it and/or modify it
 6  
  * under the terms of the GNU General Public License version 2 only, as
 7  
  * published by the Free Software Foundation.  Sun designates this
 8  
  * particular file as subject to the "Classpath" exception as provided
 9  
  * by Sun in the LICENSE file that accompanied this code.
 10  
  *
 11  
  * This code is distributed in the hope that it will be useful, but WITHOUT
 12  
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  
  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  
  * version 2 for more details (a copy is included in the LICENSE file that
 15  
  * accompanied this code).
 16  
  *
 17  
  * You should have received a copy of the GNU General Public License version
 18  
  * 2 along with this work; if not, write to the Free Software Foundation,
 19  
  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  
  *
 21  
  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 22  
  * CA 95054 USA or visit www.sun.com if you need additional information or
 23  
  * have any questions.
 24  
  */
 25  
 
 26  
 package com.sun.tools.javafx.antlr;
 27  
 
 28  
 import com.sun.tools.javac.util.Log;
 29  
 import com.sun.tools.javafx.util.MsgSym;
 30  
 
 31  
 /**
 32  
  * Convert escapes in string literals
 33  
  * 
 34  
  * @author Robert Field
 35  
  * 
 36  
  * Stolen liberally from the javac Scanner
 37  
  */
 38  
 
 39  
 public class StringLiteralProcessor {
 40  
 
 41  
     private final int basepos;
 42  
     
 43  
     /** A character buffer for literals.
 44  
      */
 45  
     private char[] sbuf;
 46  
     private int sp;
 47  
 
 48  
     /** The input buffer, index of next chacter to be read,
 49  
      *  index of one past last character in buffer.
 50  
      */
 51  
     private final char[] buf;
 52  
     private int bp;
 53  
     private final int buflen;
 54  
     
 55  
     /** The current character.
 56  
      */
 57  
     private char ch;
 58  
 
 59  
     /** The buffer index of the last converted unicode character
 60  
      */
 61  3514
     private int unicodeConversionBp = -1;
 62  
 
 63  
     /** The log to be used for error reporting.
 64  
      */
 65  
     private final Log log;
 66  
 
 67  
     public static String convert(Log log, int pos, String str) {
 68  3514
         StringLiteralProcessor slp = new StringLiteralProcessor(log, pos, str);
 69  3514
         return slp.convert();
 70  
     }
 71  
     
 72  3514
     private StringLiteralProcessor(Log log, int pos, String str) {
 73  3514
         this.log = log;
 74  3514
         this.basepos = pos;
 75  3514
             this.buf = str.toCharArray();
 76  3514
             this.buflen = buf.length - 1;  // skip trailing quote
 77  3514
             this.bp = 0; // scanChar pre-increments so we skip the leading quote
 78  3514
             this.sbuf = new char[buflen];
 79  3514
             this.sp = 0;
 80  3514
     }
 81  
     
 82  
     private String convert() {
 83  3514
         scanChar();
 84  32220
         while (bp < buflen) {
 85  28706
             scanLitChar();
 86  
         }
 87  3514
         return new String(sbuf, 0, sp);
 88  
     }
 89  
 
 90  
     /** Report an error at the given position using the provided arguments.
 91  
      */
 92  
     private void lexError(String key, Object... args) {
 93  2
         log.error(basepos+bp-1-buflen, key, args);
 94  2
     }
 95  
 
 96  
     /** Convert an ASCII digit from its base (8, 10, or 16)
 97  
      *  to its value.
 98  
      */
 99  
     private int digit(int base) {
 100  165
         char c = ch;
 101  165
         int result = Character.digit(c, base);
 102  165
         if (result >= 0 && c > 0x7f) {
 103  0
             lexError(MsgSym.MESSAGE_ILLEGAL_NONASCII_DIGIT);
 104  0
             ch = "0123456789abcdef".charAt(result);
 105  
         }
 106  165
         return result;
 107  
     }
 108  
 
 109  
 
 110  
     /** Append a character to sbuf.
 111  
      */
 112  
     private void putChar(char ch) {
 113  28705
         if (sp == sbuf.length) {
 114  0
             char[] newsbuf = new char[sbuf.length * 2];
 115  0
             System.arraycopy(sbuf, 0, newsbuf, 0, sbuf.length);
 116  0
             sbuf = newsbuf;
 117  
         }
 118  28705
         sbuf[sp++] = ch;
 119  28705
     }
 120  
 
 121  
     /** Convert unicode escape; bp points to initial '\' character
 122  
      *  (Spec 3.3).
 123  
      */
 124  
     private void convertUnicode() {
 125  131
         if (ch == '\\' && unicodeConversionBp != bp) {
 126  131
             bp++; ch = buf[bp];
 127  131
             if (ch == 'u') {
 128  
                 do {
 129  38
                     bp++; ch = buf[bp];
 130  38
                 } while (ch == 'u');
 131  37
                 int limit = bp + 3;
 132  37
                 if (limit < buflen) {
 133  37
                     int d = digit(16);
 134  37
                     int code = d;
 135  148
                     while (bp < limit && d >= 0) {
 136  111
                         bp++; ch = buf[bp];
 137  111
                         d = digit(16);
 138  111
                         code = (code << 4) + d;
 139  
                     }
 140  37
                     if (d >= 0) {
 141  36
                         ch = (char)code;
 142  36
                         unicodeConversionBp = bp;
 143  36
                         return;
 144  
                     }
 145  
                 }
 146  1
                 lexError(MsgSym.MESSAGE_ILLEGAL_UNICODE_ESC);
 147  1
             } else {
 148  94
                 bp--;
 149  94
                 ch = '\\';
 150  
             }
 151  
         }
 152  95
     }
 153  
 
 154  
     /** Read next character.
 155  
      */
 156  
     private void scanChar() {
 157  32322
         ch = buf[++bp];
 158  32322
         if (ch == '\\') {
 159  131
             convertUnicode();
 160  
         }
 161  32322
     }
 162  
 
 163  
     /** Read next character in character or string literal and copy into sbuf.
 164  
      */
 165  
     private void scanLitChar() {
 166  28706
         if (ch == '\\') {
 167  94
             if (buf[bp+1] == '\\' && unicodeConversionBp != bp) {
 168  2
                 bp++;
 169  2
                 putChar('\\');
 170  2
                 scanChar();
 171  
             } else {
 172  92
                 scanChar();
 173  92
                 switch (ch) {
 174  
                 case '0': case '1': case '2': case '3':
 175  
                 case '4': case '5': case '6': case '7':
 176  6
                     char leadch = ch;
 177  6
                     int oct = digit(8);
 178  6
                     scanChar();
 179  6
                     if ('0' <= ch && ch <= '7') {
 180  6
                         oct = oct * 8 + digit(8);
 181  6
                         scanChar();
 182  6
                         if (leadch <= '3' && '0' <= ch && ch <= '7') {
 183  5
                             oct = oct * 8 + digit(8);
 184  5
                             scanChar();
 185  
                         }
 186  
                     }
 187  6
                     putChar((char)oct);
 188  6
                     break;
 189  
                 case 'b':
 190  0
                     putChar('\b'); scanChar(); break;
 191  
                 case 't':
 192  4
                     putChar('\t'); scanChar(); break;
 193  
                 case 'n':
 194  7
                     putChar('\n'); scanChar(); break;
 195  
                 case 'f':
 196  0
                     putChar('\f'); scanChar(); break;
 197  
                 case 'r':
 198  2
                     putChar('\r'); scanChar(); break;
 199  
                 case '\'':
 200  5
                     putChar('\''); scanChar(); break;
 201  
                 case '\"':
 202  13
                     putChar('\"'); scanChar(); break;
 203  
                 case '{':
 204  29
                     putChar('{'); scanChar(); break;
 205  
                 case '}':
 206  25
                     putChar('}'); scanChar(); break;
 207  
                 case '\\':
 208  0
                     putChar('\\'); scanChar(); break;
 209  
                 default:
 210  1
                     lexError(MsgSym.MESSAGE_ILLEGAL_ESC_CHAR);
 211  
                 }
 212  
             }
 213  28612
         } else if (bp != buflen) {
 214  28612
             putChar(ch); scanChar();
 215  
         }
 216  28706
     }
 217  
 }