All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.snapscript.parse.TextDecoder Maven / Gradle / Ivy

package org.snapscript.parse;

public class TextDecoder {
   
   private StringInterner interner;
   private char[] source;
   private int count;
   private int start;

   public TextDecoder(char[] source) {
      this(source, 0, source.length);
   }
   
   public TextDecoder(char[] source, int off, int count) {
      this.interner = new StringInterner();
      this.source = source;
      this.count = count;
      this.start = off;      
   }
   
   public String decode(int off, int length) {
      return decode(off, length, true);
   }
   
   public String decode(int off, int length, boolean escape) {
      int limit = start + length + off; 
      int read = start + off;
      int write = 0;

      if(length > 0 && escape) {
         char[] result = new char[length];
         
         while(read < limit) {
            char current = source[read];
            
            if(current == '\\' && read + 1 < limit) {
               char next = source[read + 1];
               
               if(next == 'u' || next == 'U') {         
                  result[write++] = escape(read + 2, 4);
                  read += 6;
               } else {
                  if(literal(next)){ // skip
                     result[write++] = source[read + 1];
                  } else if(next == 'r') {                  
                     result[write++] = '\r';
                  } else if(next == 'b') {                  
                     result[write++] = '\b';                     
                  } else if(next == 'n') {                  
                     result[write++] = '\n';
                  } else if(next == 't') {
                     result[write++] = '\t';
                  } else if(next == 'f') {
                     result[write++] = '\f';
                  } 
                  read += 2;
               }
            } else {
               result[write++] = source[read++];
            }
         }
         return interner.intern(result, 0, write);
      }
      return interner.intern(source, off, length);
   }
   
   private char escape(int off, int length) {
      int value = 0;
      
      for(int i = 0; i < length; i++) {
         char next = source[off + i];
         
         value <<= 4;
         value |= hexidecimal(next);
      }
      return (char)value;
   }
   
   private boolean literal(char value) {
      switch(value) {
      case '\\': case '\'':
      case '\"': case '`':
         return true;
      default:
         return false;
      }
   }
   
   public long binary(char value) {
      if(value == '0') {
         return 0; 
      }
      if(value == '1') {
         return 1; 
      }
      throw new IllegalArgumentException("Character '" + value + "' is not binary");
   }
   
   public long hexidecimal(char value) {
      if(value >= '0' && value <= '9') {
         return value - '0'; 
      }
      if(value >= 'a' && value <= 'f') {
         return 10 + (value - 'a'); 
      }
      if(value >= 'A' && value <= 'F') {
         return 10 + (value - 'A'); 
      }
      throw new IllegalArgumentException("Character '" + value + "' is not hexidecimal");
   }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy