/* $Id$ */ /** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.manifoldcf.connectorcommon.jsongen; import java.io.*; /** This class describes a JSON string reader. */ public class JSONStringReader extends JSONReader { // Strings need to be escaped, therefore we have our own. /* All Unicode characters may be placed within the quotation marks except for the characters that must be escaped: quotation mark, reverse solidus, and the control characters (U+0000 through U+001F). Any character may be escaped. If the character is in the Basic Multilingual Plane (U+0000 through U+FFFF), then it may be represented as a six-character sequence: a reverse solidus, followed by the lowercase letter u, followed by four hexadecimal digits that encode the character's code point. The hexadecimal letters A though F can be upper or lowercase. So, for example, a string containing only a single reverse solidus character may be represented as "\u005C". Alternatively, there are two-character sequence escape representations of some popular characters. So, for example, a string containing only a single reverse solidus character may be represented more compactly as "\\". */ protected final static int STATE_PREQUOTE = 0; protected final static int STATE_U = 1; protected final static int STATE_1ST = 2; protected final static int STATE_2ND = 3; protected final static int STATE_3RD = 4; protected final static int STATE_4TH = 5; protected final static int STATE_NEXTCHAR = 6; protected final static int STATE_DONE = 7; protected final Reader inputReader; protected int state = STATE_PREQUOTE; protected String escapedChar; public JSONStringReader(String value) { inputReader = new StringReader(value); } public JSONStringReader(Reader value) { inputReader = value; } @Override public int read() throws IOException { int x; switch (state) { case STATE_PREQUOTE: state = STATE_NEXTCHAR; return '"'; case STATE_NEXTCHAR: x = inputReader.read(); if (x == -1) { state = STATE_DONE; return '"'; } else { if (x < ' ' || x == '"' || x == '\\') { escapedChar = "000" + Integer.toHexString(x); escapedChar = escapedChar.substring(escapedChar.length()-4); state = STATE_U; return '\\'; } return x; } case STATE_U: state = STATE_1ST; return 'u'; case STATE_1ST: state = STATE_2ND; return escapedChar.charAt(0); case STATE_2ND: state = STATE_3RD; return escapedChar.charAt(1); case STATE_3RD: state = STATE_4TH; return escapedChar.charAt(2); case STATE_4TH: state = STATE_NEXTCHAR; return escapedChar.charAt(3); case STATE_DONE: return -1; default: throw new IllegalStateException("Unknown state: "+state); } } }