summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Young <consult.awy@gmail.com>2015-07-08 10:43:39 (GMT)
committerKevin Smith <kevin.smith@isode.com>2015-08-13 08:08:30 (GMT)
commit563ab00f95281f61a0aa5ae96fb5aacedac9b900 (patch)
treefc8fd98d13d4a8c616fabcacb95b87201c49f018
parent9bf162922691c1f45813da6a21f2e274bfad3114 (diff)
downloadstroke-563ab00f95281f61a0aa5ae96fb5aacedac9b900.zip
stroke-563ab00f95281f61a0aa5ae96fb5aacedac9b900.tar.bz2
Rework ByteArray implementation
Use and ArrayList<byte[]> as the internal storage, instead of Vector<Byte>. Constructors and methods that supply a byte[] to add to the instance will have that value copied, rather than just taking ownership of the byte[]. There is an argument, on efficiency grounds, for providing methods that take ownership of the supplied argument. The earlier discussions about use of synchronization in the class are revisited. This is a low-level container that should be thread-safe or take precautions against non-thread-safe use. It is anticipated that the vast majority of uses will be thread-safe. Use of synchronization permits occasional deviations from this without imposing any significant overhead for the normal case - uncontended synchronization is close to free. Change-Id: Ifb7b2915d5c96345c53aec8e33673d892c430431
-rw-r--r--src/com/isode/stroke/base/ByteArray.java79
-rw-r--r--src/com/isode/stroke/base/SafeByteArray.java25
2 files changed, 50 insertions, 54 deletions
diff --git a/src/com/isode/stroke/base/ByteArray.java b/src/com/isode/stroke/base/ByteArray.java
index d3942ce..997cc6e 100644
--- a/src/com/isode/stroke/base/ByteArray.java
+++ b/src/com/isode/stroke/base/ByteArray.java
@@ -3,7 +3,7 @@
* All rights reserved.
*/
/*
- * Copyright (c) 2010-2012, Isode Limited, London, England.
+ * Copyright (c) 2010-2015, Isode Limited, London, England.
* All rights reserved.
*/
package com.isode.stroke.base;
@@ -13,7 +13,8 @@ import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
-import java.util.Vector;
+import java.util.ArrayList;
+import java.util.Arrays;
/**
* Maintains an arbitrarily long array of bytes.
@@ -36,7 +37,7 @@ public class ByteArray {
*/
public ByteArray(String s) {
try {
- fromBytes(s.getBytes("UTF-8"));
+ appendInternal(s.getBytes("UTF-8"));
} catch (UnsupportedEncodingException ex) {
throw new IllegalStateException("JVM has no 'UTF-8' encoding");
}
@@ -49,7 +50,7 @@ public class ByteArray {
* zero elements.
*/
public ByteArray(byte[] c) {
- fromBytes(c);
+ append(c);
}
/**
@@ -58,11 +59,6 @@ public class ByteArray {
* @param b another ByteArray; must not be null
*/
public ByteArray(ByteArray b) {
- fromBytes(b.getData());
- }
-
- private void fromBytes(final byte[] b) {
- clear();
append(b);
}
@@ -77,11 +73,17 @@ public class ByteArray {
* @return array copy of internal data, will never be null, but may
* contain zero elements.
*/
- public byte[] getData() {
+ public synchronized byte[] getData() {
if (dataCopy_ == null) {
- dataCopy_ = new byte[getSize()];
- for (int i = 0; i < data_.size(); i++) {
- dataCopy_[i] = data_.get(i).byteValue();
+ if (data_.size() == 1) {
+ dataCopy_ = data_.get(0);
+ } else {
+ dataCopy_ = new byte[getSize()];
+ int pos = 0;
+ for (byte[] chunk : data_) {
+ System.arraycopy(chunk, 0, dataCopy_, pos, chunk.length);
+ pos += chunk.length;
+ }
}
}
return dataCopy_;
@@ -92,7 +94,7 @@ public class ByteArray {
* @return number of bytes
*/
public int getSize() {
- return data_.size();
+ return dataSize_;
}
/**
@@ -117,7 +119,7 @@ public class ByteArray {
* followed by all the elements of <em>b</em>.
*/
public static ByteArray plus(ByteArray a, ByteArray b) {
- ByteArray x = new ByteArray(a.getData());
+ ByteArray x = new ByteArray(a);
x.append(b);
return x;
}
@@ -135,8 +137,10 @@ public class ByteArray {
* @param b an existing ByteArray. Must not be null, but may be empty
* @return a reference to the updated object
*/
- public ByteArray append(ByteArray b) {
- append(b.getData());
+ public synchronized ByteArray append(ByteArray b) {
+ dataCopy_ = null; /* Invalidate cache */
+ data_.addAll(b.data_);
+ dataSize_ += b.getSize();
return this;
}
@@ -155,9 +159,14 @@ public class ByteArray {
/** Mutable add */
public ByteArray append(byte[] b, int len) {
- for (int i = 0; i < len; i++) {
- append(b[i]);
- }
+ return appendInternal(Arrays.copyOf(b, len));
+ }
+
+ /* Does not copy data - all calls must provide a copy as necessary */
+ private synchronized ByteArray appendInternal(byte[] b) {
+ dataCopy_ = null; /* Invalidate cache */
+ data_.add(b);
+ dataSize_ += b.length;
return this;
}
@@ -168,9 +177,7 @@ public class ByteArray {
* @return a reference to the updated object
*/
public ByteArray append(byte b) {
- dataCopy_ = null; /* Invalidate cache */
- data_.add(Byte.valueOf(b));
- return this;
+ return appendInternal(new byte[]{b});
}
/**
@@ -180,26 +187,21 @@ public class ByteArray {
* @return a reference to the updated object.
*/
public ByteArray append(String s) {
- byte[] bytes;
try {
- bytes = s.getBytes("UTF-8");
+ return appendInternal(s.getBytes("UTF-8"));
} catch (UnsupportedEncodingException ex) {
throw new IllegalStateException("JVM has no 'UTF-8' encoding");
}
- append(bytes);
- return this;
}
@Override
public synchronized int hashCode() {
- int hash = 3;
- hash = 97 * hash + (this.data_ != null ? this.data_.hashCode() : 0);
- return hash;
+ return Arrays.hashCode(getData());
}
@Override
public boolean equals(Object other) {
- return other instanceof ByteArray && toString().equals(other.toString());
+ return other instanceof ByteArray && Arrays.equals(getData(), ((ByteArray)other).getData());
}
/*public char charAt(int i) {
@@ -250,7 +252,7 @@ public class ByteArray {
bos.write(fis.read());
}
byte[] bytes = bos.toByteArray();
- append(bytes);
+ appendInternal(bytes);
}
catch (FileNotFoundException e) {
// Leave things as they were
@@ -272,16 +274,19 @@ public class ByteArray {
catch (IOException e) {
// Needs a catch clause
}
- }
+ }
}
/**
* Clears the contents of this ByteArray, leaving it with zero elements.
*/
- public void clear() {
- data_ = new Vector<Byte>();
+ public synchronized void clear() {
+ data_.clear();
+ dataSize_ = 0;
dataCopy_ = null;
}
- Vector<Byte> data_ = new Vector<Byte>();
- byte[] dataCopy_ = null;
+
+ private final ArrayList<byte[]> data_ = new ArrayList<byte[]>(1);
+ private int dataSize_ = 0;
+ private byte[] dataCopy_ = null;
}
diff --git a/src/com/isode/stroke/base/SafeByteArray.java b/src/com/isode/stroke/base/SafeByteArray.java
index ac8960f..e193299 100644
--- a/src/com/isode/stroke/base/SafeByteArray.java
+++ b/src/com/isode/stroke/base/SafeByteArray.java
@@ -6,7 +6,6 @@ package com.isode.stroke.base;
import com.isode.stroke.base.SafeByteArray;
import com.isode.stroke.base.ByteArray;
-import java.io.UnsupportedEncodingException;
/**
* It's currently not actually secure,
@@ -23,7 +22,7 @@ public class SafeByteArray extends ByteArray {
}
public SafeByteArray(ByteArray b) {
- this.append(b.getData());
+ super(b);
}
/**
@@ -46,7 +45,7 @@ public class SafeByteArray extends ByteArray {
* followed by all the elements of <em>b</em>.
*/
public static SafeByteArray plus(SafeByteArray a, SafeByteArray b) {
- SafeByteArray x = new SafeByteArray().append(a.getData());
+ SafeByteArray x = new SafeByteArray(a);
x.append(b);
return x;
}
@@ -58,7 +57,7 @@ public class SafeByteArray extends ByteArray {
* @return a reference to the updated object
*/
public SafeByteArray append(ByteArray b) {
- append(b.getData());
+ super.append(b);
return this;
}
@@ -72,14 +71,13 @@ public class SafeByteArray extends ByteArray {
* @return a reference to the updated object
*/
public SafeByteArray append(byte[] b) {
- return append(b, b.length);
+ super.append(b);
+ return this;
}
/** Mutable add */
public SafeByteArray append(byte[] b, int len) {
- for (int i = 0; i < len; i++) {
- append(b[i]);
- }
+ super.append(b, len);
return this;
}
@@ -90,8 +88,7 @@ public class SafeByteArray extends ByteArray {
* @return a reference to the updated object
*/
public SafeByteArray append(byte b) {
- dataCopy_ = null; /* Invalidate cache */
- data_.add(Byte.valueOf(b));
+ super.append(b);
return this;
}
@@ -102,13 +99,7 @@ public class SafeByteArray extends ByteArray {
* @return a reference to the updated object.
*/
public SafeByteArray append(String s) {
- byte[] bytes;
- try {
- bytes = s.getBytes("UTF-8");
- } catch (UnsupportedEncodingException ex) {
- throw new IllegalStateException("JVM has no 'UTF-8' encoding");
- }
- append(bytes);
+ super.append(s);
return this;
}
} \ No newline at end of file