001: /*
002: * Copyright (c) 1998 - 2005 Versant Corporation
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * Versant Corporation - initial API and implementation
010: */
011: package com.versant.core.util;
012:
013: /**
014: * Fast StringBuffer replacement that allows direct access to the underlying
015: * char[]. This is based com.sosnoski.util.array.CharArray from
016: * Sosnoski Software Solutions, Inc.
017: */
018: public final class CharBuf {
019:
020: private char[] buf;
021: private int size;
022:
023: public CharBuf() {
024: this (64);
025: }
026:
027: public CharBuf(int capacity) {
028: buf = new char[capacity];
029: }
030:
031: public CharBuf(String s) {
032: this (s.length());
033: append(s);
034: }
035:
036: public CharBuf(CharBuf s) {
037: this (s.size);
038: size = s.size;
039: System.arraycopy(s.buf, 0, buf, 0, size);
040: }
041:
042: public int size() {
043: return size;
044: }
045:
046: public void clear() {
047: size = 0;
048: }
049:
050: private void ensureCapacity(int len) {
051: if (size + len > buf.length) {
052: int n = buf.length * 3 / 2 + 1;
053: if (size + len > n) {
054: n = size + len;
055: }
056: char[] a = new char[n];
057: System.arraycopy(buf, 0, a, 0, size);
058: buf = a;
059: }
060: }
061:
062: /**
063: * Append ch and return its index.
064: */
065: public int append(char ch) {
066: ensureCapacity(size + 1);
067: int start = size;
068: buf[size++] = ch;
069: return start;
070: }
071:
072: /**
073: * Append i and return its index.
074: */
075: public int append(int i) {
076: return append(Integer.toString(i));
077: }
078:
079: /**
080: * Append s and return its index.
081: */
082: public int append(String s) {
083: return append(s.toCharArray());
084: }
085:
086: /**
087: * Append a and return its index.
088: */
089: public int append(char[] a) {
090: int n = a.length;
091: ensureCapacity(size + n);
092: int start = size;
093: System.arraycopy(a, 0, buf, size, n);
094: size += n;
095: return start;
096: }
097:
098: /**
099: * Replace characters from i onwards with supplied characters. This does
100: * not do any error checking or make any attempt to expand the buffer
101: * for performance reasons.
102: */
103: public void replace(int i, char[] text) {
104: System.arraycopy(text, 0, buf, i, text.length);
105: }
106:
107: /**
108: * Replace characters from first to last - 1 with c. This does
109: * not do any error checking for performance reasons.
110: */
111: public void replace(int first, int last, char c) {
112: for (int i = first; i < last; i++) {
113: buf[i] = c;
114: }
115: }
116:
117: public String toString() {
118: return new String(buf, 0, size);
119: }
120:
121: /**
122: * Constructs and returns a simple array containing the same data as held
123: * in a portion of this growable array.
124: */
125: public char[] toArray(int offset, int length) {
126: char[] a = new char[length];
127: System.arraycopy(buf, offset, a, 0, length);
128: return a;
129: }
130:
131: public void setSize(int sz) {
132: size = sz;
133: }
134:
135: /**
136: * Construct a <code>String</code> from a portion of the character sequence
137: * present.
138: */
139: public String toString(int offset, int length) {
140: return new String(buf, offset, length);
141: }
142:
143: /**
144: * Insert the characters from a <code>char[]</code> into the array.
145: */
146: public void insert(int offset, char[] text) {
147: adjust(offset, offset, text.length);
148: System.arraycopy(text, 0, buf, offset, text.length);
149: }
150:
151: /**
152: * Insert the characters from a <code>String</code> into the array.
153: */
154: public void insert(int offset, String text) {
155: adjust(offset, offset, text.length());
156: text.getChars(0, text.length(), buf, offset);
157: }
158:
159: /**
160: * Replace a character range in the array with the characters from a
161: * <code>String</code>.
162: */
163: public void replace(int from, int to, String text) {
164: adjust(from, to, text.length());
165: text.getChars(0, text.length(), buf, from);
166: }
167:
168: /**
169: * Replace a character range in the array with the characters from a
170: * <code>char[]</code>.
171: */
172: public void replace(int from, int to, char[] text) {
173: adjust(from, to, text.length);
174: System.arraycopy(text, 0, buf, from, text.length);
175: }
176:
177: /**
178: * Adjust the characters in the array to make room for an insertion or
179: * replacement. Depending on the relative sizes of the range being
180: * replaced and the range being inserted, this may move characters past
181: * the start of the replacement range up or down in the array.
182: *
183: * @param from index number of first character to be replaced
184: * @param to index number past last character to be replaced
185: * @param length length of character range being inserted
186: */
187: protected void adjust(int from, int to, int length) {
188: if (from >= 0 && to < size && from <= to) {
189: int change = from + length - to;
190: if (change > 0) {
191: ensureCapacity(size + change);
192: }
193: if (to < size) {
194: System.arraycopy(buf, to, buf, to + change, size - to);
195: size += change;
196: }
197: } else {
198: throw new ArrayIndexOutOfBoundsException(
199: "Invalid remove range");
200: }
201: }
202:
203: /**
204: * Set the value at an index position in the array.
205: */
206: public void set(int index, char value) {
207: buf[index] = value;
208: }
209:
210: /**
211: * Remove a range of value from the array. The index positions for values
212: * above the range removed are decreased by the number of values removed.
213: *
214: * @param from index number of first value to be removed
215: * @param to index number past last value to be removed
216: */
217: public void remove(int from, int to) {
218: if (from >= 0 && to <= size && from <= to) {
219: if (to < size) {
220: int change = from - to;
221: System.arraycopy(buf, to, buf, from, size - to);
222: size += change;
223: }
224: } else {
225: throw new ArrayIndexOutOfBoundsException(
226: "Invalid remove range");
227: }
228: }
229:
230: }
|