001: /*
002: * Derby - class org.apache.derby.impl.drda.DRDAString
003: *
004: * Licensed to the Apache Software Foundation (ASF) under one or more
005: * contributor license agreements. See the NOTICE file distributed with
006: * this work for additional information regarding copyright ownership.
007: * The ASF licenses this file to You under the Apache License, Version 2.0
008: * (the "License"); you may not use this file except in compliance with
009: * the License. You may obtain a copy of the License at
010: *
011: * http://www.apache.org/licenses/LICENSE-2.0
012: *
013: * Unless required by applicable law or agreed to in writing, software
014: * distributed under the License is distributed on an "AS IS" BASIS,
015: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
016: * implied. See the License for the specific language governing
017: * permissions and limitations under the License.
018: *
019: */
020:
021: package org.apache.derby.impl.drda;
022:
023: /**
024: * This class provides functionality for reusing buffers and strings
025: * when parsing DRDA packets. A byte array representing a string is
026: * stored internally. When the string is requested as a
027: * <code>String</code> object, the byte array is converted to a
028: * string, and the string is cached to avoid unnecessary conversion
029: * later.
030: */
031: final class DRDAString {
032: /** Buffer representing the string. */
033: private byte[] buffer;
034: /** Object used to convert byte buffer to string. */
035: private final CcsidManager ccsidManager;
036:
037: /** True if the contents were modified in the previous call to
038: * <code>setBytes</code>. */
039: private boolean modified;
040:
041: /** The previously generated string. */
042: private String cachedString;
043:
044: /**
045: * Create a new <code>DRDAString</code> instance.
046: *
047: * @param m a <code>CcsidManager</code> value specifying
048: * which encoding is used
049: */
050: DRDAString(CcsidManager m) {
051: this .buffer = new byte[0];
052: this .ccsidManager = m;
053: this .cachedString = null;
054: }
055:
056: /**
057: * Check whether the internal buffer contains the same data as
058: * another byte buffer.
059: *
060: * @param buf a byte array
061: * @param offset start position in the byte array
062: * @param size how many bytes to read from the byte array
063: * @return <code>true</code> if the internal buffer contains the
064: * same data as the specified byte array
065: */
066: private boolean equalTo(byte[] buf, int offset, int size) {
067: int len = buffer.length;
068: if (len != size)
069: return false;
070: for (int i = 0; i < len; ++i) {
071: if (buffer[i] != buf[i + offset])
072: return false;
073: }
074: return true;
075: }
076:
077: /**
078: * Modify the internal byte buffer. If the new data is equal to
079: * the old data, the cached values are not cleared.
080: *
081: * @param src the new bytes
082: * @param offset start offset
083: * @param size number of bytes to use
084: */
085: public void setBytes(byte[] src, int offset, int size) {
086: if (equalTo(src, offset, size)) {
087: modified = false;
088: return;
089: }
090: if (buffer.length != size) {
091: buffer = new byte[size];
092: }
093: System.arraycopy(src, offset, buffer, 0, size);
094: modified = true;
095: cachedString = null;
096: }
097:
098: /**
099: * Check whether the contents of the <code>DRDAString</code> were
100: * modified in the previous call to <code>setBytes()</code>.
101: *
102: * @return <code>true</code> if the contents were modified
103: */
104: public boolean wasModified() {
105: return modified;
106: }
107:
108: /**
109: * Convert the internal byte array to a string. The string value
110: * is cached.
111: *
112: * @return a <code>String</code> value
113: */
114: public String toString() {
115: if (cachedString == null) {
116: cachedString = ccsidManager.convertToUCS2(buffer);
117: }
118: return cachedString;
119: }
120:
121: /**
122: * Return the length in bytes of the internal string
123: * representation.
124: *
125: * @return length of internal representation
126: */
127: public int length() {
128: return buffer.length;
129: }
130:
131: /**
132: * Return the internal byte array. The returned array should not
133: * be modified, as it is used internally in
134: * <code>DRDAString</code>. The value of the array might be
135: * modified by subsequent calls to
136: * <code>DRDAString.setBytes()</code>.
137: *
138: * @return internal buffer
139: */
140: public byte[] getBytes() {
141: return buffer;
142: }
143: }
|