001: /* Copyright (c) 2001-2005, The HSQL Development Group
002: * All rights reserved.
003: *
004: * Redistribution and use in source and binary forms, with or without
005: * modification, are permitted provided that the following conditions are met:
006: *
007: * Redistributions of source code must retain the above copyright notice, this
008: * list of conditions and the following disclaimer.
009: *
010: * Redistributions in binary form must reproduce the above copyright notice,
011: * this list of conditions and the following disclaimer in the documentation
012: * and/or other materials provided with the distribution.
013: *
014: * Neither the name of the HSQL Development Group nor the names of its
015: * contributors may be used to endorse or promote products derived from this
016: * software without specific prior written permission.
017: *
018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
020: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
021: * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
022: * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
023: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
024: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
025: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
026: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
027: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
028: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029: */
030:
031: package org.hsqldb.rowio;
032:
033: import java.io.IOException;
034:
035: import org.hsqldb.Trace;
036:
037: /**
038: * Fields in the source file need not be quoted. Methods in this class unquote
039: * the fields if they are quoted and handle quote character doubling in this
040: * case.
041: *
042: * @author sqlbob@users (RMP)
043: * @version 1.7.2
044: * @since 1.7.0
045: */
046: public class RowInputTextQuoted extends RowInputText {
047:
048: private static final int NORMAL_FIELD = 0;
049: private static final int NEED_END_QUOTE = 1;
050: private static final int FOUND_QUOTE = 2;
051: private char[] qtext;
052:
053: public RowInputTextQuoted(String fieldSep, String varSep,
054: String longvarSep, boolean allQuoted) {
055: super (fieldSep, varSep, longvarSep, allQuoted);
056: }
057:
058: public void setSource(String text, int pos, int byteSize) {
059:
060: super .setSource(text, pos, byteSize);
061:
062: qtext = text.toCharArray();
063: }
064:
065: protected String getField(String sep, int sepLen, boolean isEnd)
066: throws IOException {
067:
068: //fredt - now the only supported behaviour is emptyIsNull
069: String s = null;
070:
071: if (next >= qtext.length || qtext[next] != '\"') {
072: return (super .getField(sep, sepLen, isEnd));
073: }
074:
075: try {
076: field++;
077:
078: StringBuffer ret = new StringBuffer();
079: boolean done = false;
080: int state = NORMAL_FIELD;
081: int end = -1;
082:
083: if (!isEnd) {
084: end = text.indexOf(sep, next);
085: }
086:
087: for (; next < qtext.length; next++) {
088: switch (state) {
089:
090: case NORMAL_FIELD:
091: default:
092: if (next == end) {
093: next += sepLen;
094: done = true;
095: } else if (qtext[next] == '\"') {
096:
097: //-- Beginning of field
098: state = NEED_END_QUOTE;
099: } else {
100: ret.append(qtext[next]);
101: }
102: break;
103:
104: case NEED_END_QUOTE:
105: if (qtext[next] == '\"') {
106: state = FOUND_QUOTE;
107: } else {
108: ret.append(qtext[next]);
109: }
110: break;
111:
112: case FOUND_QUOTE:
113: if (qtext[next] == '\"') {
114:
115: //-- Escaped quote
116: ret.append(qtext[next]);
117:
118: state = NEED_END_QUOTE;
119: } else {
120: next += sepLen - 1;
121: state = NORMAL_FIELD;
122:
123: if (!isEnd) {
124: next++;
125:
126: done = true;
127: }
128: }
129: break;
130: }
131:
132: if (done) {
133: break;
134: }
135: }
136:
137: s = ret.toString();
138: } catch (Exception e) {
139: throw new IOException(Trace.getMessage(
140: Trace.QuotedTextDatabaseRowInput_getField2, true,
141: new Object[] { new Integer(field), e.toString() }));
142: }
143:
144: return s;
145: }
146: }
|