Source code: com/mysql/jdbc/EscapeTokenizer.java
1 /*
2 Copyright (C) 2002-2004 MySQL AB
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of version 2 of the GNU General Public License as
6 published by the Free Software Foundation.
7
8
9 There are special exceptions to the terms and conditions of the GPL
10 as it is applied to this software. View the full text of the
11 exception exception in file EXCEPTIONS-CONNECTOR-J in the directory of this
12 software distribution.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
23 */
24 package com.mysql.jdbc;
25
26
27 /**
28 * EscapeTokenizer breaks up an SQL statement into SQL and
29 * escape code parts.
30 *
31 * @author Mark Matthews
32 */
33 public class EscapeTokenizer {
34 private String source = null;
35 private boolean emittingEscapeCode = false;
36 private boolean inComment = false;
37 private boolean inQuotes = false;
38 private char lastChar = 0;
39 private char lastLastChar = 0;
40 private char quoteChar = 0;
41 private int bracesLevel = 0;
42 private int pos = 0;
43 private int sourceLength = 0;
44
45 /**
46 * Creates a new EscapeTokenizer object.
47 *
48 * @param s the string to tokenize
49 */
50 public EscapeTokenizer(String s) {
51 source = s;
52 sourceLength = s.length();
53 pos = 0;
54 }
55
56 /**
57 * Does this tokenizer have more tokens available?
58 *
59 * @return if this tokenizer has more tokens available
60 */
61 public synchronized boolean hasMoreTokens() {
62 return (pos < sourceLength);
63 }
64
65 /**
66 * Returns the next token
67 *
68 * @return the next token.
69 */
70 public synchronized String nextToken() {
71 StringBuffer tokenBuf = new StringBuffer();
72
73 if (emittingEscapeCode) {
74 tokenBuf.append("{");
75 emittingEscapeCode = false;
76 }
77
78 for (; pos < sourceLength; pos++) {
79 char c = source.charAt(pos);
80
81 if (c == '\'') {
82 if (lastChar != '\\') {
83 if (inQuotes) {
84 if (quoteChar == c) {
85 inQuotes = false;
86 }
87 } else {
88 inQuotes = true;
89 quoteChar = c;
90 }
91 } else if (lastLastChar == '\\') {
92 if (inQuotes) {
93 if (quoteChar == c) {
94 inQuotes = false;
95 }
96 } else {
97 inQuotes = true;
98 quoteChar = c;
99 }
100 }
101
102 tokenBuf.append(c);
103 } else if (c == '"') {
104 if ((lastChar != '\\') && (lastChar != '"')) {
105 if (inQuotes) {
106 if (quoteChar == c) {
107 inQuotes = false;
108 }
109 } else {
110 inQuotes = true;
111 quoteChar = c;
112 }
113 } else if (lastLastChar == '\\') {
114 if (inQuotes) {
115 if (quoteChar == c) {
116 inQuotes = false;
117 }
118 } else {
119 inQuotes = true;
120 quoteChar = c;
121 }
122 }
123
124 tokenBuf.append(c);
125 } else if (c == '-') {
126 if ((lastChar == '-') && ((lastLastChar != '\\') & !inQuotes)) {
127 inComment = true;
128 }
129
130 tokenBuf.append(c);
131 } else if ((c == '\n') || (c == '\r')) {
132 inComment = false;
133
134 tokenBuf.append(c);
135 } else if (c == '{') {
136 if (inQuotes || inComment) {
137 tokenBuf.append(c);
138 } else {
139 bracesLevel++;
140
141 if (bracesLevel == 1) {
142 pos++;
143 emittingEscapeCode = true;
144
145 return tokenBuf.toString();
146 } else {
147 tokenBuf.append(c);
148 }
149 }
150 } else if (c == '}') {
151 tokenBuf.append(c);
152
153 if (!inQuotes && !inComment) {
154 lastChar = c;
155
156 bracesLevel--;
157
158 if (bracesLevel == 0) {
159 pos++;
160
161 return tokenBuf.toString();
162 }
163 }
164 } else {
165 tokenBuf.append(c);
166 }
167
168 lastLastChar = lastChar;
169 lastChar = c;
170 }
171
172 return tokenBuf.toString();
173 }
174 }