001: // serverCharBuffer.java
002: // ---------------------------
003: // (C) by Michael Peter Christen; mc@anomic.de
004: // first published on http://www.anomic.de
005: // Frankfurt, Germany, 2004
006: //
007: // $LastChangedDate: 2006-02-20 23:57:42 +0100 (Mo, 20 Feb 2006) $
008: // $LastChangedRevision: 1715 $
009: // $LastChangedBy: borg-0300 $
010: //
011: // This program is free software; you can redistribute it and/or modify
012: // it under the terms of the GNU General Public License as published by
013: // the Free Software Foundation; either version 2 of the License, or
014: // (at your option) any later version.
015: //
016: // This program is distributed in the hope that it will be useful,
017: // but WITHOUT ANY WARRANTY; without even the implied warranty of
018: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
019: // GNU General Public License for more details.
020: //
021: // You should have received a copy of the GNU General Public License
022: // along with this program; if not, write to the Free Software
023: // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
024: //
025: // Using this software in any meaning (reading, learning, copying, compiling,
026: // running) means that you agree that the Author(s) is (are) not responsible
027: // for cost, loss of data or any harm that may be caused directly or indirectly
028: // by usage of this softare or this documentation. The usage of this software
029: // is on your own risk. The installation and usage (starting/running) of this
030: // software may allow other people or application to access your computer and
031: // any attached devices and is highly dependent on the configuration of the
032: // software which must be done by the user of the software; the author(s) is
033: // (are) also not responsible for proper configuration and usage of the
034: // software, even if provoked by documentation provided together with
035: // the software.
036: //
037: // Any changes to this file according to the GPL as documented in the file
038: // gpl.txt aside this file in the shipment you received can be done to the
039: // lines that follows this copyright notice here, but changes must not be
040: // done inside the copyright notive above. A re-distribution must contain
041: // the intact and unchanged copyright notice.
042: // Contributions and changes to the program code must be marked as such.
043:
044: package de.anomic.server;
045:
046: import java.io.File;
047: import java.io.FileNotFoundException;
048: import java.io.FileReader;
049: import java.io.IOException;
050: import java.io.Writer;
051: import java.util.Properties;
052:
053: public final class serverCharBuffer extends Writer {
054:
055: public static final char singlequote = '\'';
056: public static final char doublequote = '"';
057: public static final char equal = '=';
058:
059: private char[] buffer;
060: private int offset;
061: private int length;
062:
063: public serverCharBuffer() {
064: buffer = new char[10];
065: length = 0;
066: offset = 0;
067: }
068:
069: public serverCharBuffer(int initLength) {
070: this .buffer = new char[initLength];
071: this .length = 0;
072: this .offset = 0;
073: }
074:
075: public serverCharBuffer(char[] bb) {
076: buffer = bb;
077: length = bb.length;
078: offset = 0;
079: }
080:
081: public serverCharBuffer(char[] bb, int initLength) {
082: this .buffer = new char[initLength];
083: System.arraycopy(bb, 0, buffer, 0, bb.length);
084: length = bb.length;
085: offset = 0;
086: }
087:
088: public serverCharBuffer(char[] bb, int of, int le) {
089: if (of * 2 > bb.length) {
090: buffer = new char[le];
091: System.arraycopy(bb, of, buffer, 0, le);
092: length = le;
093: offset = 0;
094: } else {
095: buffer = bb;
096: length = le;
097: offset = of;
098: }
099: }
100:
101: public serverCharBuffer(serverCharBuffer bb) {
102: buffer = bb.buffer;
103: length = bb.length;
104: offset = bb.offset;
105: }
106:
107: public serverCharBuffer(File f) throws IOException {
108: // initially fill the buffer with the content of a file
109: if (f.length() > Integer.MAX_VALUE)
110: throw new IOException("file is too large for buffering");
111:
112: length = (int) f.length();
113: buffer = new char[length * 2];
114: offset = 0;
115:
116: try {
117: FileReader fr = new FileReader(f);
118: char[] temp = new char[256];
119: int c;
120: while ((c = fr.read(temp)) > 0) {
121: this .append(temp, 0, c);
122: }
123: } catch (FileNotFoundException e) {
124: throw new IOException("File not found: " + f.toString()
125: + "; " + e.getMessage());
126: }
127: }
128:
129: public void clear() {
130: this .buffer = new char[0];
131: length = 0;
132: offset = 0;
133: }
134:
135: public int length() {
136: return length;
137: }
138:
139: private void grow() {
140: int newsize = buffer.length * 2 + 1;
141: if (newsize < 256)
142: newsize = 256;
143: char[] tmp = new char[newsize];
144: System.arraycopy(buffer, offset, tmp, 0, length);
145: buffer = tmp;
146: tmp = null;
147: offset = 0;
148: }
149:
150: public void write(int b) {
151: write((char) b);
152: }
153:
154: public void write(char b) {
155: if (offset + length + 1 > buffer.length)
156: grow();
157: buffer[offset + length++] = b;
158: }
159:
160: public void write(char[] bb) {
161: write(bb, 0, bb.length);
162: }
163:
164: public void write(char[] bb, int of, int le) {
165: while (offset + length + le > buffer.length)
166: grow();
167: System.arraycopy(bb, of, buffer, offset + length, le);
168: length += le;
169: }
170:
171: // do not use/implement the following method, a
172: // "overridden method is a bridge method"
173: // will occur
174: // public serverCharBuffer append(char b) {
175: // write(b);
176: // return this;
177: // }
178:
179: public serverCharBuffer append(int i) {
180: write((char) (i));
181: return this ;
182: }
183:
184: public serverCharBuffer append(char[] bb) {
185: write(bb);
186: return this ;
187: }
188:
189: public serverCharBuffer append(char[] bb, int of, int le) {
190: write(bb, of, le);
191: return this ;
192: }
193:
194: public serverCharBuffer append(String s) {
195: return append(s, 0, s.length());
196: }
197:
198: public serverCharBuffer append(String s, int off, int len) {
199: char[] temp = new char[len];
200: s.getChars(off, (off + len), temp, 0);
201: return append(temp);
202: }
203:
204: public serverCharBuffer append(serverCharBuffer bb) {
205: return append(bb.buffer, bb.offset, bb.length);
206: }
207:
208: // public serverCharBuffer append(Object o) {
209: // if (o instanceof String) return append((String) o);
210: // if (o instanceof char[]) return append((char[]) o);
211: // return null;
212: // }
213:
214: public char charAt(int pos) {
215: if (pos < 0)
216: throw new IndexOutOfBoundsException();
217: if (pos > length)
218: throw new IndexOutOfBoundsException();
219: return buffer[offset + pos];
220: }
221:
222: public void deleteCharAt(int pos) {
223: if (pos < 0)
224: return;
225: if (pos >= length)
226: return;
227: if (pos == length - 1) {
228: length--;
229: } else {
230: System.arraycopy(buffer, offset + pos + 1, buffer, offset
231: + pos, length - pos - 1);
232: }
233: }
234:
235: public int indexOf(char b) {
236: return indexOf(b, 0);
237: }
238:
239: public int indexOf(char[] bs) {
240: return indexOf(bs, 0);
241: }
242:
243: public int indexOf(char b, int start) {
244: if (start >= length)
245: return -1;
246: for (int i = start; i < length; i++)
247: if (buffer[offset + i] == b)
248: return i;
249: return -1;
250: }
251:
252: public int indexOf(char[] bs, int start) {
253: if (start + bs.length > length)
254: return -1;
255: loop: for (int i = start; i <= length - bs.length; i++) {
256: // first test only first char
257: if (buffer[offset + i] != bs[0])
258: continue loop;
259:
260: // then test all remaining char
261: for (int j = 1; j < bs.length; j++) {
262: if (buffer[offset + i + j] != bs[j])
263: continue loop;
264: }
265:
266: // found hit
267: return i;
268: }
269: return -1;
270: }
271:
272: public int lastIndexOf(char b) {
273: for (int i = length - 1; i >= 0; i--)
274: if (buffer[offset + i] == b)
275: return i;
276: return -1;
277: }
278:
279: public boolean startsWith(char[] bs) {
280: if (length < bs.length)
281: return false;
282: for (int i = 0; i < bs.length; i++) {
283: if (buffer[offset + i] != bs[i])
284: return false;
285: }
286: return true;
287: }
288:
289: public char[] getChars() {
290: return getChars(0);
291: }
292:
293: public char[] getChars(int start) {
294: return getChars(start, length);
295: }
296:
297: public char[] getChars(int start, int end) {
298: // start is inclusive, end is exclusive
299: if (end > length)
300: throw new IndexOutOfBoundsException(
301: "getBytes: end > length");
302: if (start > length)
303: throw new IndexOutOfBoundsException(
304: "getBytes: start > length");
305: char[] tmp = new char[end - start];
306: System.arraycopy(buffer, offset + start, tmp, 0, end - start);
307: return tmp;
308: }
309:
310: public serverCharBuffer trim(int start) {
311: // the end value is outside (+1) of the wanted target array
312: if (start > length)
313: throw new IndexOutOfBoundsException("trim: start > length");
314: offset = offset + start;
315: length = length - start;
316: return this ;
317: }
318:
319: public serverCharBuffer trim(int start, int end) {
320: // the end value is outside (+1) of the wanted target array
321: if (start > length)
322: throw new IndexOutOfBoundsException("trim: start > length");
323: if (end > length)
324: throw new IndexOutOfBoundsException("trim: end > length");
325: if (start > end)
326: throw new IndexOutOfBoundsException("trim: start > end");
327: offset = offset + start;
328: length = end - start;
329: return this ;
330: }
331:
332: public serverCharBuffer trim() {
333: int l = 0;
334: while ((l < length) && (buffer[offset + l] <= ' '))
335: l++;
336: int r = length;
337: while ((r > 0) && (buffer[offset + r - 1] <= ' '))
338: r--;
339: if (l > r)
340: r = l;
341: return trim(l, r);
342: }
343:
344: public boolean isWhitespace(boolean includeNonLetterBytes) {
345: // returns true, if trim() would result in an empty serverByteBuffer
346: if (includeNonLetterBytes) {
347: char b;
348: for (int i = 0; i < length; i++) {
349: b = buffer[offset + i];
350: if (((b >= '0') && (b <= '9'))
351: || ((b >= 'A') && (b <= 'Z'))
352: || ((b >= 'a') && (b <= 'z')))
353: return false;
354: }
355: } else {
356: for (int i = 0; i < length; i++)
357: if (buffer[offset + i] > 32)
358: return false;
359: }
360: return true;
361: }
362:
363: public int whitespaceStart(boolean includeNonLetterBytes) {
364: // returns number of whitespace char at the beginning of text
365: if (includeNonLetterBytes) {
366: char b;
367: for (int i = 0; i < length; i++) {
368: b = buffer[offset + i];
369: if (((b >= '0') && (b <= '9'))
370: || ((b >= 'A') && (b <= 'Z'))
371: || ((b >= 'a') && (b <= 'z')))
372: return i;
373: }
374: } else {
375: for (int i = 0; i < length; i++)
376: if (buffer[offset + i] > 32)
377: return i;
378: }
379: return length;
380: }
381:
382: public int whitespaceEnd(boolean includeNonLetterBytes) {
383: // returns position of whitespace at the end of text
384: if (includeNonLetterBytes) {
385: char b;
386: for (int i = length - 1; i >= 0; i--) {
387: b = buffer[offset + i];
388: if (((b >= '0') && (b <= '9'))
389: || ((b >= 'A') && (b <= 'Z'))
390: || ((b >= 'a') && (b <= 'z')))
391: return i + 1;
392: }
393: } else {
394: for (int i = length - 1; i >= 0; i--)
395: if (buffer[offset + i] > 32)
396: return i + 1;
397: }
398: return 0;
399: }
400:
401: public String toString() {
402: return new String(buffer, offset, length);
403: }
404:
405: public String toString(int left, int rightbound) {
406: return new String(buffer, offset + left, rightbound - left);
407: }
408:
409: public Properties propParser() {
410: // extract a=b or a="b" - relations from the buffer
411: int pos = offset;
412: int start;
413: String key;
414: Properties p = new Properties();
415: // eat up spaces at beginning
416: while ((pos < length) && (buffer[pos] <= 32))
417: pos++;
418: while (pos < length) {
419: // pos is at start of next key
420: start = pos;
421: while ((pos < length) && (buffer[pos] != equal))
422: pos++;
423: if (pos >= length)
424: break; // this is the case if we found no equal
425: key = new String(buffer, start, pos - start).trim()
426: .toLowerCase();
427: // we have a key
428: pos++;
429: // find start of value
430: while ((pos < length) && (buffer[pos] <= 32))
431: pos++;
432: // doublequotes are obligatory. However, we want to be fuzzy if they
433: // are ommittet
434: if (pos >= length) {
435: // error case: input ended too early
436: break;
437: } else if (buffer[pos] == doublequote) {
438: // search next doublequote
439: pos++;
440: start = pos;
441: while ((pos < length) && (buffer[pos] != doublequote))
442: pos++;
443: if (pos >= length)
444: break; // this is the case if we found no parent doublequote
445: p.setProperty(key, new String(buffer, start, pos
446: - start).trim());
447: pos++;
448: } else if (buffer[pos] == singlequote) {
449: // search next singlequote
450: pos++;
451: start = pos;
452: while ((pos < length) && (buffer[pos] != singlequote))
453: pos++;
454: if (pos >= length)
455: break; // this is the case if we found no parent singlequote
456: p.setProperty(key, new String(buffer, start, pos
457: - start).trim());
458: pos++;
459: } else {
460: // search next whitespace
461: start = pos;
462: while ((pos < length) && (buffer[pos] > 32))
463: pos++;
464: p.setProperty(key, new String(buffer, start, pos
465: - start).trim());
466: }
467: // pos should point now to a whitespace: eat up spaces
468: while ((pos < length) && (buffer[pos] <= 32))
469: pos++;
470: // go on with next loop
471: }
472: return p;
473: }
474:
475: public static boolean equals(char[] buffer, char[] pattern) {
476: return equals(buffer, 0, pattern);
477: }
478:
479: public static boolean equals(char[] buffer, int offset,
480: char[] pattern) {
481: // compares two char arrays: true, if pattern appears completely at offset position
482: if (buffer.length < offset + pattern.length)
483: return false;
484: for (int i = 0; i < pattern.length; i++)
485: if (buffer[offset + i] != pattern[i])
486: return false;
487: return true;
488: }
489:
490: public void reset() {
491: this .length = 0;
492: this .offset = 0;
493: }
494:
495: public void reset(int newSize) {
496: this .resize(newSize);
497: this .reset();
498: }
499:
500: public void resize(int newSize) {
501: if (newSize < 0)
502: throw new IllegalArgumentException("Illegal array size: "
503: + newSize);
504: char[] v = new char[newSize];
505: System.arraycopy(this .buffer, 0, v, 0,
506: newSize > this .buffer.length ? this .buffer.length
507: : newSize);
508: this .buffer = v;
509: }
510:
511: public char toCharArray()[] {
512: char[] newbuf = new char[this .length];
513: System.arraycopy(this .buffer, 0, newbuf, 0, this .length);
514: return newbuf;
515: }
516:
517: public void close() throws IOException {
518: // TODO Auto-generated method stub
519: }
520:
521: public void flush() throws IOException {
522: // TODO Auto-generated method stub
523: }
524:
525: }
|