001: /*
002: * StrBuffer.java
003: *
004: * This file is part of SQL Workbench/J, http://www.sql-workbench.net
005: *
006: * Copyright 2002-2008, Thomas Kellerer
007: * No part of this code maybe reused without the permission of the author
008: *
009: * To contact the author please send an email to: support@sql-workbench.net
010: *
011: */
012: package workbench.util;
013:
014: import java.io.IOException;
015: import java.io.PrintStream;
016: import java.io.Writer;
017:
018: /**
019: * This is a non-synchronized implementation of StringBuffer, which
020: * offers better performance than the class java.lang.StringBuffer.
021: *
022: * Initially copied from http://h21007.www2.hp.com/dspp/tech/tech_TechDocumentDetailPage_IDX/1,1701,2488,00.html
023: *
024: * This will only have an advantage if this object is not converted to a String object
025: * too often. java.lang.StringBuilder can re-use the internal char[] array when
026: * it's toString() method is called, whereas StrBuffer.toString() will allocate
027: * a new char array due to the constructor of String.
028: *
029: * So StrBuffer is most efficient when it is never converted to a String object.
030: * For this, methods to write to a Stream and a Writer are provided that
031: * write out the internal char array directly.
032: *
033: * @author support@sql-workbench.net
034: * @see java.lang.StringBuilder
035: */
036: public class StrBuffer implements CharSequence {
037: private static final int DEFAULT_LEN = 80;
038:
039: /**
040: * The number of characters in the buffer.
041: */
042: private int numchar;
043:
044: /**
045: * Used for character storage.
046: */
047: private char charData[];
048:
049: public static final StrBuffer emptyBuffer() {
050: return new StrBuffer(0);
051: }
052:
053: /**
054: * Make an empty string buffer with 80 characters of storage.
055: */
056: public StrBuffer() {
057: this (DEFAULT_LEN);
058: }
059:
060: public StrBuffer(String source) {
061: if (source == null) {
062: this .charData = new char[DEFAULT_LEN];
063: this .numchar = 0;
064: } else {
065: this .charData = new char[source.length()];
066: this .append(source);
067: }
068: }
069:
070: public StrBuffer(StrBuffer source) {
071: if (source == null) {
072: this .charData = new char[DEFAULT_LEN];
073: this .numchar = 0;
074: } else {
075: this .charData = new char[source.length()];
076: this .append(source);
077: }
078: }
079:
080: /**
081: * Remove count characters from the end of the buffer
082: */
083: public StrBuffer removeFromEnd(int count) {
084: if (count > this .numchar)
085: this .numchar = 0;
086: this .numchar -= count;
087: return this ;
088: }
089:
090: /**
091: * Make an empty string buffer with 'len' characters of storage.
092: *
093: * @param len the initial storage capacity.
094: * @exception NegativeArraySizeException if the 'len' less than 0.
095: */
096: public StrBuffer(int len) {
097: this .charData = new char[len];
098: this .numchar = 0;
099: }
100:
101: /**
102: * Expand the storage size to at least 'minStorage' number of characters.
103: */
104: private void moreStorage(int minStorage) {
105: int newStorage = (int) ((double) this .charData.length * 1.2) + 5;
106:
107: if (newStorage < minStorage)
108: newStorage = minStorage;
109: if (this .charData == null) {
110: this .charData = new char[newStorage];
111: }
112: if (this .charData != null) {
113: char newBuf[] = new char[newStorage];
114: System.arraycopy(this .charData, 0, newBuf, 0, this .numchar);
115: this .charData = newBuf;
116: }
117: }
118:
119: /**
120: * This is exposed, so that the StrBuffer
121: * can be used when writing to a Writer without
122: * the need to copy the char[] array
123: */
124: public char[] getBuffer() {
125: return this .charData;
126: }
127:
128: public StrBuffer append(long i) {
129: return this .append(Long.toString(i));
130: }
131:
132: public StrBuffer append(int i) {
133: return this .append(NumberStringCache.getNumberString(i));
134: }
135:
136: public StrBuffer append(char[] buf, int start, int len) {
137: int newlen = this .numchar + len;
138:
139: if (newlen > this .charData.length)
140: moreStorage(newlen);
141:
142: System.arraycopy(buf, start, charData, numchar, len);
143: this .numchar = newlen;
144: return this ;
145: }
146:
147: /**
148: * Appends the passed StrBuffer to this StrBuffer
149: */
150: public StrBuffer append(StrBuffer str) {
151: if (str == null)
152: return this ;
153: int len = str.numchar;
154: if (len == 0)
155: return this ;
156: if (len == 1) {
157: return this .append(str.charData[0]);
158: }
159: return append(str.charData, 0, len);
160: }
161:
162: public boolean endsWith(char c) {
163: if (numchar == 0)
164: return false;
165: return this .charData[this .numchar - 1] == c;
166: }
167:
168: public void rtrim() {
169: if (this .numchar == 0)
170: return;
171: while (this .charData[this .numchar - 1] <= (char) 32) {
172: this .numchar--;
173: }
174: }
175:
176: /**
177: * Returns the current length of this StrBuffer
178: */
179: public int length() {
180: return this .numchar;
181: }
182:
183: /**
184: * Appends the character to this StrBuffer.
185: *
186: * @param c the character to append
187: * @return this string buffer
188: */
189: public StrBuffer append(char c) {
190: int newlen = this .numchar + 1;
191: if (newlen > this .charData.length)
192: moreStorage(newlen);
193: this .charData[newlen - 1] = c;
194: this .numchar = newlen;
195: return this ;
196: }
197:
198: public StrBuffer insert(int index, char c) {
199: int newlen = this .numchar + 1;
200: if (newlen > this .charData.length) {
201: char newBuf[] = new char[newlen + 10];
202: System.arraycopy(this .charData, 0, newBuf, 0, index);
203: System.arraycopy(this .charData, index, newBuf, index + 1,
204: (numchar - index));
205: this .charData = newBuf;
206: }
207: this .charData[index] = c;
208: this .numchar = newlen;
209: return this ;
210: }
211:
212: public StrBuffer remove(int index) {
213: int num = this .numchar - index - 1;
214:
215: if (num > 0) {
216: System.arraycopy(charData, index + 1, charData, index, num);
217: }
218: this .numchar--;
219: this .charData[numchar] = 0;
220: return this ;
221: }
222:
223: public StrBuffer append(CharSequence s) {
224: if (s == null)
225: return this ;
226: int len = s.length();
227: if (len == 0)
228: return this ;
229: if (len == 1) {
230: return this .append(s.charAt(0));
231: }
232: int newlen = this .numchar + len;
233: if (newlen > this .charData.length)
234: moreStorage(newlen);
235: for (int i = 0; i < len; i++) {
236: this .charData[i + numchar] = s.charAt(i);
237: }
238: //b.getChars(0, len, this.charData, numchar);
239: this .numchar = newlen;
240: return this ;
241: }
242:
243: /**
244: * Returns a new string based on the contents of this StrBuffer.
245: *
246: * @return a string
247: */
248: public String toString() {
249: return new String(this .charData, 0, this .numchar);
250: }
251:
252: public char charAt(int index) {
253: if (index >= this .numchar)
254: throw new IndexOutOfBoundsException(index + " >= "
255: + this .numchar);
256: return this .charData[index];
257: }
258:
259: public CharSequence subSequence(int start, int end) {
260: if (start < 0)
261: throw new IndexOutOfBoundsException("start must be >= 0");
262: if (end < 0)
263: throw new IndexOutOfBoundsException("end must be >=0");
264: if (end > this .numchar)
265: throw new IndexOutOfBoundsException(end + " >= "
266: + this .numchar);
267: if (start > end)
268: throw new IndexOutOfBoundsException(start + " > " + end);
269:
270: int len = (end - start);
271: StrBuffer result = new StrBuffer(len);
272: result.numchar = len;
273: System.arraycopy(this .charData, start, result.charData, 0, len);
274: return result;
275: }
276:
277: public void appendTo(StringBuilder buff) {
278: buff.append(this .charData, 0, this .numchar);
279: }
280:
281: public void writeTo(Writer out) throws IOException {
282: out.write(this .charData, 0, this .numchar);
283: }
284:
285: public void writeTo(PrintStream out) {
286: for (int i = 0; i < this.numchar; i++) {
287: out.print(this.charData[i]);
288: }
289: }
290:
291: }
|