001: package com.quadcap.util;
002:
003: /* Copyright 1997 - 2003 Quadcap Software. All rights reserved.
004: *
005: * This software is distributed under the Quadcap Free Software License.
006: * This software may be used or modified for any purpose, personal or
007: * commercial. Open Source redistributions are permitted. Commercial
008: * redistribution of larger works derived from, or works which bundle
009: * this software requires a "Commercial Redistribution License"; see
010: * http://www.quadcap.com/purchase.
011: *
012: * Redistributions qualify as "Open Source" under one of the following terms:
013: *
014: * Redistributions are made at no charge beyond the reasonable cost of
015: * materials and delivery.
016: *
017: * Redistributions are accompanied by a copy of the Source Code or by an
018: * irrevocable offer to provide a copy of the Source Code for up to three
019: * years at the cost of materials and delivery. Such redistributions
020: * must allow further use, modification, and redistribution of the Source
021: * Code under substantially the same terms as this license.
022: *
023: * Redistributions of source code must retain the copyright notices as they
024: * appear in each source code file, these license terms, and the
025: * disclaimer/limitation of liability set forth as paragraph 6 below.
026: *
027: * Redistributions in binary form must reproduce this Copyright Notice,
028: * these license terms, and the disclaimer/limitation of liability set
029: * forth as paragraph 6 below, in the documentation and/or other materials
030: * provided with the distribution.
031: *
032: * The Software is provided on an "AS IS" basis. No warranty is
033: * provided that the Software is free of defects, or fit for a
034: * particular purpose.
035: *
036: * Limitation of Liability. Quadcap Software shall not be liable
037: * for any damages suffered by the Licensee or any third party resulting
038: * from use of the Software.
039: */
040:
041: import java.io.ByteArrayInputStream;
042: import java.io.InputStream;
043: import java.io.IOException;
044: import java.io.OutputStream;
045:
046: /**
047: * An OctetString is a variable length string of octets.
048: *
049: * @author Stan Bailes
050: */
051: public class OctetString {
052: byte[] data;
053:
054: /**
055: * Construct a new OctetString using the specified byte array. Note
056: * that we simply acquire the byte array -- no copying is done!
057: *
058: * @param data the byte array making up the string
059: */
060: public OctetString(byte[] data) {
061: this .data = data;
062: }
063:
064: /**
065: * Construct a new OctetString using a substring from the specified byte
066: * array. This constructor <b>does</b> allocate a new byte array and
067: * copies data from the original array.
068: *
069: * @param data the source byte array
070: * @param offset the position of the first character in the substring
071: * @param len the number of bytes in the new string
072: */
073: public OctetString(byte[] data, int offset, int len) {
074: this .data = new byte[len];
075: System.arraycopy(data, offset, this .data, 0, len);
076: }
077:
078: /**
079: * Construct a new OctetString from the specified java.lang.String value.
080: *
081: * @param str the string value
082: */
083: public OctetString(String str) {
084: this .data = str.getBytes();
085: }
086:
087: /**
088: * Return the string representation of this item.
089: *
090: * @return the string value
091: */
092: public String toString() {
093: return new String(data);
094: }
095:
096: /**
097: * For types which can be directly handled by comparators, return this
098: * object as a byte array. For special types (e.g., NIL or List),
099: * return null.
100: */
101: public byte[] getBytes() {
102: return data;
103: }
104:
105: public int hashCode() {
106: return new String(data).hashCode();
107: }
108:
109: public boolean equals(Object obj) {
110: if (obj instanceof OctetString) {
111: return OctetComparator.cmp.compare(this , (OctetString) obj) == 0;
112: }
113: return false;
114: }
115:
116: public boolean equalsIgnoreCase(Object obj) {
117: if (obj instanceof OctetString) {
118: OctetString other = (OctetString) obj;
119: return OctetComparator.casecmp.compare(this , other) == 0;
120: }
121: return false;
122: }
123:
124: /**
125: * Return the size of this string.
126: */
127: public int size() {
128: return data.length;
129: }
130:
131: /**
132: * String comparison using the binary equality comparator
133: */
134: public static boolean equals(OctetString s1, int pos1,
135: OctetString s2, int pos2, int len) {
136: for (int i = 0; i < len; i++) {
137: if (pos1 + i >= s1.data.length
138: || pos2 + i >= s2.data.length)
139: return false;
140: if (s1.data[pos1 + i] != s2.data[pos2 + i])
141: return false;
142: }
143: return true;
144: }
145:
146: /**
147: * String search for character. Should this use a comparator? XXX
148: *
149: * @param c the character to search for
150: * @return the index of the first occurrence of the character in this
151: * string, or -1 if the character does not occur in the string.
152: */
153: public int indexOf(char c) {
154: byte b = (byte) c;
155: for (int i = 0; i < data.length; i++)
156: if (data[i] == b)
157: return i;
158: return -1;
159: }
160:
161: /**
162: * String search for character. Should this use a comparator? XXX
163: *
164: * @param c the character to search for
165: * @return the index of the last occurrence of the character in this
166: * string, or -1 if the character does not occur in the string.
167: */
168: public int lastIndexOf(char c) {
169: byte b = (byte) c;
170: for (int i = data.length - 1; i >= 0; i--)
171: if (data[i] == b)
172: return i;
173: return -1;
174: }
175:
176: /**
177: * Return a new string containing the specified substring of this string.
178: *
179: * @param start the position of the first character of the substring
180: * @param end the position of the character after the substring
181: * @return the substring
182: */
183: public OctetString substring(int start, int end) {
184: return new OctetString(data, start, end - start);
185: }
186:
187: /**
188: * Return a new string containing the specified substring of this string,
189: * starting with the specified character, and ending with the last
190: * character of the string.
191: *
192: * @param start the position of the first character of the substring
193: * @return the substring
194: */
195: public OctetString substring(int start) {
196: return substring(start, size());
197: }
198:
199: /**
200: * A truly general purpose function designed for a specified task,
201: * this returns a new string containing the portion of this string
202: * after the last occurrence of the specified character.
203: *
204: * <p>For example:<pre>
205: * "/addressbook/user/stan/ABC457".afterLast('/') returns "ABC457"
206: * </pre>
207: *
208: * @param c the character
209: * @return a new <code>OctetString</code> containing the required suffix
210: */
211: public OctetString afterLast(char c) {
212: int pos = data.length;
213: while (pos >= 0 && c != data[--pos])
214: continue;
215: pos++;
216: int len = data.length - pos;
217: return substring(pos);
218: }
219:
220: /**
221: * Return substring containing the portion of this string before the
222: * first occurence of the specified character.
223: *
224: * @param c the character
225: * @return a new <code>OctetString</code> containing the substring.
226: */
227: public OctetString before(char c) {
228: int idx = indexOf(c);
229: if (idx < 0)
230: return null;
231: return substring(0, idx);
232: }
233:
234: /**
235: * A truly general purpose function designed for a specified task,
236: * this returns a new string containing the portion of this string
237: * before the last occurrence of the specified character.
238: *
239: * <p>For example:<pre>
240: * "/addressbook/user/stan/ABC457".beforeLast('/') returns
241: * "/addressbook/user/stan"
242: * </pre>
243: *
244: * @param c the character
245: * @return a new <code>OctetString</code> containing the required prefix
246: */
247: public OctetString beforeLast(char c) {
248: int len = data.length;
249: while (len >= 0 && c != data[--len])
250: continue;
251: return substring(0, len);
252: }
253:
254: /**
255: * Another general purpose routine :-)
256: * This one converts a particular substring of this string to an
257: * integer.
258: *
259: * @param start the position of the first character of the substring
260: * @param end the position of the character after the substring
261: *
262: */
263: public int getIntSubString(int start, int end) {
264: int val = 0;
265: for (int i = 0; i < end; i++) {
266: val *= 10;
267: val += Character.digit((char) (data[i]), 10);
268: }
269: return val;
270: }
271:
272: /**
273: * String concatenation
274: */
275: public OctetString append(String s) {
276: return append(s.getBytes());
277: }
278:
279: /**
280: * String concatenation
281: */
282: public OctetString append(OctetString s) {
283: return append(s.data);
284: }
285:
286: /**
287: * String concatenation
288: */
289: public OctetString append(byte[] b) {
290: int len = data.length + b.length;
291: byte[] ret = new byte[len];
292: System.arraycopy(data, 0, ret, 0, data.length);
293: System.arraycopy(b, 0, ret, data.length, b.length);
294: return new OctetString(ret);
295: }
296:
297: }
|