using System; using Microsoft.SPOT; namespace CPF { public class ByteString { public const int DefaultCapacity = 512; protected byte[] _internalBuffer; protected int _head; protected int _tail; private static bool strcmp(ByteString lhs, ByteString rhs) { if (lhs.Length == rhs.Length) { int pos = 0; while (lhs._internalBuffer[pos] == rhs._internalBuffer[pos] && pos < lhs.Length) pos++; return (pos == lhs.Length) ? true : false; } else return false; } public class NotEnoughCapacity : Exception { public NotEnoughCapacity() : base() { } } public class IndexOutOfRange : Exception { public IndexOutOfRange() : base() { } } public int Length { get { return _tail - _head; } } public int Available { get { return _internalBuffer.Length - Length; } } public int Capacity { get; private set; } public ByteString Clear() { _head = 0; _tail = 0; _internalBuffer = new byte[DefaultCapacity]; return this; } public ByteString() { Clear(); } public ByteString(byte ch) { Clear(); _internalBuffer[_tail++] = ch; } public ByteString(byte[] bytes) { Clear(); CheckCapacity(bytes.Length); for (int pos = 0; _tail < bytes.Length; ) _internalBuffer[_tail++] = (byte)bytes[pos++]; } public ByteString(string s) { Clear(); CheckCapacity(s.Length); char[] chars = s.ToCharArray(); for (int pos = 0; _tail < s.Length; ) _internalBuffer[_tail++] = (byte)chars[pos++]; } public byte this[int i] { get { if (i < 0 || i > Length) throw new IndexOutOfRange(); return _internalBuffer[i]; } set { if (i < 0 || i > Length) throw new IndexOutOfRange(); _internalBuffer[i] = value; } } public byte[] AddressOf() { return _internalBuffer; } public byte Deref() { if (_head < 0 || _head > _tail) throw new IndexOutOfRange(); return _internalBuffer[_head]; } public byte DerefPostInc() { if (_head < 0 || _head > _tail) throw new IndexOutOfRange(); return _internalBuffer[_head++]; } public byte DerefPreInc() { if (_head < 0 || _head > _tail) throw new IndexOutOfRange(); return _internalBuffer[++_head]; } public void Advance(int amount) { _head += amount; } public static bool operator ==(ByteString lhs, ByteString rhs) { return strcmp(lhs, rhs); } public static bool operator !=(ByteString lhs, ByteString rhs) { return !strcmp(lhs, rhs); } public override bool Equals(object obj) { if (obj is ByteString) return this == (ByteString)obj; return false; } public override int GetHashCode() { return GetHashCode(); // unique hash for each area } public ByteString Append(string s) { CheckCapacity(s.Length); char[] chars = s.ToCharArray(); foreach (char t in chars) _internalBuffer[_tail++] = (byte)t; return this; } public ByteString Append(byte[] bytes, int length) { //check if space is available for additional data CheckCapacity(length); for (int i = 0; i < length; i++) _internalBuffer[_tail++] = bytes[i]; return this; } public ByteString Append(byte ch) { //check if space is available for additional data CheckCapacity(1); _internalBuffer[_tail++] = ch; return this; } public ByteString Append(char ch) { //check if space is available for additional data CheckCapacity(1); _internalBuffer[_tail++] = (byte)ch; return this; } public ByteString Append(ByteString s) { CheckCapacity(s.Length); for (int i = 0; i < s.Length; i++) this._internalBuffer[_tail++] = s._internalBuffer[i]; return this; } public byte[] GetByteArray() { return _internalBuffer; } public override string ToString() { char[] chars = new char[Length]; for (int pos = 0; pos < Length; pos++) chars[pos] = (char)_internalBuffer[_head + pos]; return new string(chars); } public int Begin() { return _head; } public int End() { return _tail; } private void InternalExpandBuffer() { //double capacity by default Capacity *= 2; //copy to new array var tmpBuffer = new byte[Capacity]; for (int i = 0; i < _internalBuffer.Length; i++) { byte c = _internalBuffer[i]; tmpBuffer[i] = c; } _internalBuffer = tmpBuffer; } private void CheckCapacity(int additionalLength) { if (Length + additionalLength > DefaultCapacity) // Allow room for null terminator throw new NotEnoughCapacity(); } } }