Ejemplo n.º 1
0
  /**
   * Parse a string value and covert it to its proper data type.
   *
   * @param value
   * @return The parsed value.
   * @throws ParsingException Thrown if not Advisory is available and there was an error parsing.
   */
  @SuppressWarnings("unchecked")
  public static <T> T parseValue(String value) throws ParsingException {
    final T result;

    assert value != null;

    /*
     * todo Restructure the whole class so I've got parse and parseArray as
     * static methods and the share code properly.
     */
    if ("null".equals(value)) {
      result = null;
    } else {
      final List<Object> list = new ArrayList<>();
      final Text t = new Text();
      t.append(value);

      if (any(t, list) && t.isEof()) {
        result = (T) list.get(0);
      } else {
        error("Count not parse value: " + value);
        result = null;
      }
    }

    return result;
  }
Ejemplo n.º 2
0
  /**
   * Convert a value to an Oak markup representation.
   *
   * @param value The value to represent.
   * @param tb The buffer in which to write the markup.
   */
  public void toMarkup(Object value, Text t) {
    if (value == null) {
      t.append("null");
    } else {
      switch (this) {
        case z:
        case Z:
        case f:
        case F:
        case bool:
          t.append(value.toString());
          break;

        case cardinality:
          ((Cardinality) value).toString(t);
          break;

        case text:
          escapeForOak((String) value, true, t);
          break;

        case identifier:
          t.append(value.toString());
          break;

        case path:
          ((Path) value).toString(t);
          break;

        case datetime:
          t.append('@');
          t.append(DateU.formatStandardDatetime((LocalDateTime) value));
          break;

        case date:
          t.append('@');
          t.append(DateU.formatStandardDate((LocalDate) value));
          break;

        case time:
          t.append('@');
          t.append(DateU.formatStandardTime((LocalTime) value));
          break;

        case any:
        default:
          throw new UnexpectedException("asString: " + this);
      }
    }
  }
Ejemplo n.º 3
0
  /**
   * Convert a list of values to an Oak markup String, e.g. "[ true, null, false ]".
   *
   * @param values The list of values
   * @return An Oak markup representation of the values.
   * @see #parse(String)
   */
  public String toString(List<Object> values) {
    assert values != null : "Arrays can't be null, only empty";

    final Text t = new Text(true);

    t.append('[');
    if (values.size() > 0) {
      t.space();
      for (final Object value : values) {
        t.delimit();
        toMarkup(value, t);
      }
      t.space();
    }
    t.append(']');

    return t.toString();
  }
Ejemplo n.º 4
0
 public static void toString(Object value, Text t) {
   if (value == null) {
     t.append("null");
   } else {
     final Class<? extends Object> clazz = value.getClass();
     final DataType type = getDataType(clazz);
     if (type == null) {
       throw new RuntimeException("Invalid type: " + clazz.getName());
     }
     type.toMarkup(value, t);
   }
 }
Ejemplo n.º 5
0
  /**
   * Parse a string into a list of data values. White space is supported only in between the [square
   * brackets].
   *
   * @param string A string representation of an Oak property array, e.g. [ true, null, false ]
   * @param type The type of the array, may be 'any'.
   * @return A potentially empty but not null list of values.
   */
  @SuppressWarnings("unchecked")
  public static <T> List<T> parseArray(String string, DataType type) {
    final List<?> result;

    final Text t = new Text();
    t.append(string);
    if (t.consume('[')
        && (result = elementList(t, type)) != null
        && (t.ws() && t.consume(']'))
        && t.isEof()) {
      // OK
    } else {
      throw new ParsingException("Invalid array: " + string);
    }

    return (List<T>) result;
  }
Ejemplo n.º 6
0
 /**
  * Escape a string for Oak. If the string is null then "null" is returned otherwise the string is
  * returned with [tn\"] escaped \r discarded and the whole thing surrounded in quotes if
  * requested.
  *
  * @param string The String to process.
  * @param quote Double quotes are added if true.
  * @param result Where to place the processed String.
  */
 public static void escapeForOak(String string, boolean quote, Text result) {
   if (string == null) {
     result.append("null");
   } else {
     if (quote) {
       result.append('"');
     }
     final char[] ca = string.toCharArray();
     for (final char c : ca) {
       switch (c) {
         case '\t':
           result.append("\\t");
           break;
         case '\n':
           result.append("\\n");
           break;
         case '\"':
           result.append("\\\"");
           break;
         case '\\':
           result.append("\\\\");
           break;
         default:
           if (c < ' ' || c >= '~') {
             // Must be four digits
             result.append("\\u" + Integer.toHexString(c | 0x10000).substring(1));
           } else {
             result.append(c);
           }
       }
     }
     if (quote) {
       result.append('"');
     }
   }
 }
Ejemplo n.º 7
0
  /**
   * Convert a potentially escaped string to text.
   *
   * @param t The source string.
   * @param start Starting offset.
   * @param end Ending offset.
   * @return Return the un-escaped string which may be zero-length but not null.
   */
  private static String unescape(Text t, int start, int end) {
    final Text result = new Text();

    /*
     * We know that there's a starting and ending quote that's been removed
     * from the string but otherwise we can't trust the contents.
     */
    for (int i = start; i < end; i++) {
      final char c = t.charAt(i);
      final char escaped;
      if (c == '\\') {
        if (i < end - 1) {
          i++;
          final char next = t.charAt(i);
          if (next == 't') {
            escaped = '\t';
          } else if (next == 'n') {
            escaped = '\n';
          } else if (next == '"') {
            escaped = '"';
          } else if (next == '\\') {
            escaped = '\\';
          } else {
            error("Invalid escape: '\\" + next + '\'');
            escaped = next;
          }
        } else {
          error("Unterminated string");
          escaped = c;
        }
      } else {
        escaped = c;
      }
      result.append(escaped);
    }

    return result.toString();
  }
Ejemplo n.º 8
0
  /**
   * In Oak it is possible to embed a tab character as an ASCII 8 or as a \t but internally we store
   * this in ASCII. The same goes for newlines and other tables (see the Oak reference). Here we
   * convert external format to internal format.
   *
   * @param source The text to process, may be null. E.g. "Hello\tworld" (with the quotes)
   * @return Return an internal format string.
   */
  @Nullable
  public static String textToInternalFormat(@Nullable String source) throws ParsingException {
    final String result;

    assert source == null
        || source.length() >= 2
            && source.charAt(0) == '"'
            && source.charAt(source.length() - 1) == '"';

    if (source == null) {
      result = null;
    } else {
      final Text t = new Text();
      final char[] ca = source.toCharArray();
      final int length = ca.length - 1; // 1 because remove quotes

      for (int i = 1; i < length; i++) { // 1 because remove quotes
        final char c = ca[i];
        if (c == '\\') {
          if (i == length - 1) {
            error("Invalid text " + source + ", escape at end of line");
          } else {
            i++;
            final char next = ca[i];
            if (next == 't') {
              t.append('\t');
            } else if (next == 'n') {
              t.append('\n');
            } else if (next == '"') {
              t.append('"');
            } else if (next == '\\') {
              t.append('\\');
            } else if (next == 'u') {
              // Unicode, 1-4 hex characters...
              i++;

              final Text hex = new Text();
              hex.append(source);
              hex.setCursor(i);
              final int start = i;
              if (hex.consumeAscii(Text.ASCII_0_F)) {
                final int end = start + Math.min(4, hex.cursor() - start);
                final String string = hex.getString(start, end);
                final char u = (char) Integer.parseInt(string, 16);
                t.append(u);
                i = end - 1;
              } else {
                error("Invalid text " + source + ", incorrect unicode");
              }
            } else {
              error("Invalid text: \\" + next);
            }
          }
        } else {
          t.append(c);
        }
      }
      result = t.toString();
    }

    return result;
  }