Logo Search packages:      
Sourcecode: f-spot version File versions  Download package

ByteVector.cs

//
// ByteVector.cs: represents and performs operations on variable length list of
// bytes.
//
// Author:
//   Brian Nickel (brian.nickel@gmail.com)
//   Aaron Bockover (abockover@novell.com)
//
// Original Source:
//   tbytevector.cpp from TagLib
//
// Copyright (C) 2005-2007 Brian Nickel
// Copyright (C) 2006 Novell, Inc.
// Copyright (C) 2002-2004 Scott Wheeler (Original Implementation)
//
// This library is free software; you can redistribute it and/or modify
// it  under the terms of the GNU Lesser General Public License version
// 2.1 as published by the Free Software Foundation.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
// USA
//

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;

namespace TagLib {
      /// <summary>
      ///    Specifies the text encoding used when converting between a <see
      ///    cref="string" /> and a <see cref="ByteVector" />.
      /// </summary>
      /// <remarks>
      ///    This enumeration is used by <see
      ///    cref="ByteVector.FromString(string,StringType)" /> and <see
      ///    cref="ByteVector.ToString(StringType)" />.
      /// </remarks>
      public enum StringType {
            /// <summary>
            ///    The string is to be Latin-1 encoded.
            /// </summary>
            Latin1 = 0,
            
            /// <summary>
            ///    The string is to be UTF-16 encoded.
            /// </summary>
            UTF16 = 1,
            
            /// <summary>
            ///    The string is to be UTF-16BE encoded.
            /// </summary>
            UTF16BE = 2,
            
            /// <summary>
            ///    The string is to be UTF-8 encoded.
            /// </summary>
            UTF8 = 3,
            
            /// <summary>
            ///    The string is to be UTF-16LE encoded.
            /// </summary>
            UTF16LE = 4
      }
      
      /// <summary>
      ///    This class represents and performs operations on variable length
      ///    list of <see cref="byte" /> elements.
      /// </summary>
00077       public class ByteVector : IList<byte>, IComparable<ByteVector>
      {
#region Private Static Fields
            
            /// <summary>
            ///    Contains values to use in CRC calculation.
            /// </summary>
00084             private static uint [] crc_table = new uint[256] {
                  0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
                  0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
                  0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
                  0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
                  0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9,
                  0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
                  0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011,
                  0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
                  0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
                  0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
                  0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81,
                  0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
                  0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49,
                  0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
                  0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
                  0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
                  0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae,
                  0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
                  0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
                  0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
                  0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
                  0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
                  0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066,
                  0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
                  0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e,
                  0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
                  0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
                  0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
                  0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
                  0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
                  0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686,
                  0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
                  0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
                  0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
                  0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f,
                  0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
                  0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47,
                  0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
                  0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
                  0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
                  0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7,
                  0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
                  0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f,
                  0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
                  0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
                  0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
                  0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f,
                  0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
                  0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
                  0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
                  0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
                  0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
                  0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,
                  0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
                  0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088,
                  0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
                  0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
                  0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
                  0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
                  0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
                  0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0,
                  0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
                  0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
                  0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
            };
            
            /// <summary>
            ///    Specifies whether or not to use a broken Latin-1
            ///    behavior.
            /// </summary>
00155             private static bool use_broken_latin1 = false;
            
            /// <summary>
            ///    Contains a one byte text delimiter.
            /// </summary>
00160             private static readonly ReadOnlyByteVector td1 =
                  new ReadOnlyByteVector ((int)1);
            
            /// <summary>
            ///    Contains a two byte text delimiter.
            /// </summary>
00166             private static readonly ReadOnlyByteVector td2 =
                  new ReadOnlyByteVector ((int)2);
            
            /// <summary>
            ///    Contains the last generic UTF-16 encoding read.
            /// </summary>
            /// <remarks>
            ///    When reading a collection of UTF-16 strings, sometimes
            ///    only the first one will contain the BOM. In that case,
            ///    this field will inform the file what encoding to use for
            ///    the second string.
            /// </remarks>
00178             private static System.Text.Encoding last_utf16_encoding =
                  System.Text.Encoding.Unicode;
            
#endregion
            
            
            
#region Private Fields
            
            /// <summary>
            ///    Contains the internal byte list.
            /// </summary>
00190             private List<byte> data = new List<byte>();
            
#endregion
            
            
            
#region Constructors
            
            /// <summary>
            ///    Constructs and initializes a new instance of <see
            ///    cref="ByteVector" /> with a length of zero.
            /// </summary>
00202             public ByteVector ()
            {
            }
            
            /// <summary>
            ///    Constructs and initializes a new instance of <see
            ///    cref="ByteVector" /> by copying the values from another
            ///    instance.
            /// </summary>
            /// <param name="vector">
            ///    A <see cref="ByteVector" /> object containing the bytes
            ///    to be stored in the new instance.
            /// </param>
00215             public ByteVector (ByteVector vector)
            {
                  if (vector != null)
                        this.data.AddRange (vector);
            }
            
            /// <summary>
            ///    Constructs and initializes a new instance of <see
            ///    cref="ByteVector" /> by copying the values from a
            ///    specified <see cref="byte[]" />.
            /// </summary>
            /// <param name="data">
            ///    A <see cref="byte[]" /> containing the bytes to be stored
            ///    in the new instance.
            /// </param>
00230             public ByteVector (params byte [] data)
            {
                  if (data != null)
                        this.data.AddRange (data);
            }
            
            
            /// <summary>
            ///    Constructs and initializes a new instance of <see
            ///    cref="ByteVector" /> by copying a specified number of
            ///    values from a specified <see cref="byte[]" />.
            /// </summary>
            /// <param name="data">
            ///    A <see cref="byte[]" /> containing the bytes to be stored
            ///    in the new instance.
            /// </param>
            /// <param name="length">
            ///    A <see cref="int" /> value specifying the number of bytes
            ///    to be copied to the new instance.
            /// </param>
            /// <exception cref="ArgumentOutOfRangeException">
            ///    <paramref name="length" /> is less than zero or greater
            ///    than the length of the data.
            /// </exception>
00254             public ByteVector (byte [] data, int length)
            {
                  if (length > data.Length)
                        throw new ArgumentOutOfRangeException ("length",
                              "Length exceeds size of data.");
                  
                  if (length < 0)
                        throw new ArgumentOutOfRangeException ("length",
                              "Length is less than zero.");
                  
                  if (length == data.Length) {
                        this.data.AddRange (data);
                  } else {
                        byte [] array = new byte[length];
                        System.Array.Copy (data, 0, array, 0, length);
                        this.data.AddRange (array);
                  }
            }
            
            /// <summary>
            ///    Constructs and initializes a new instance of <see
            ///    cref="ByteVector" /> of specified size containing bytes
            ///    with a zeroed value.
            /// </summary>
            /// <param name="size">
            ///    A <see cref="int" /> value specifying the number of bytes
            ///    to be stored in the new instance.
            /// </param>
            /// <remarks>
            ///    Each element of the new instance will have a value of
            ///    <c>0x00</c>. <see cref="ByteVector(int,byte)" /> to fill
            ///    a new instance with a specified value.
            /// </remarks>
            /// <exception cref="ArgumentOutOfRangeException">
            ///    <paramref name="size" /> is less than zero.
            /// </exception>
00290             public ByteVector (int size) : this (size, 0)
            {
            }
            
            /// <summary>
            ///    Constructs and initializes a new instance of <see
            ///    cref="ByteVector" /> of specified size containing bytes
            ///    of a specified value.
            /// </summary>
            /// <param name="size">
            ///    A <see cref="int" /> value specifying the number of bytes
            ///    to be stored in the new instance.
            /// </param>
            /// <param name="value">
            ///    A <see cref="byte" /> value specifying the value to be
            ///    stored in the new instance.
            /// </param>
            /// <exception cref="ArgumentOutOfRangeException">
            ///    <paramref name="size" /> is less than zero.
            /// </exception>
00310             public ByteVector (int size, byte value)
            {
                  if (size < 0)
                        throw new ArgumentOutOfRangeException ("size",
                              "Size is less than zero.");
                  
                  if(size == 0)
                        return;
                  
                  byte [] data = new byte [size];
                  
                  for (int i = 0; i < size; i ++)
                        data[i] = value;
                  
                  this.data.AddRange (data);
            }
            
            #endregion
            
            
            
            #region Public Properties
            
            /// <summary>
            ///    Gets the data stored in the current instance.
            /// </summary>
            /// <value>
            ///    A <see cref="byte[]" /> containing the data stored in the
            ///    current instance.
            /// </value>
00340             public byte [] Data {
                  get {return this.data.ToArray();}
            }
            
            /// <summary>
            ///    Gets whether or not the current instance is empty.
            /// </summary>
            /// <value>
            ///    A <see cref="bool" /> value indicating whether or not the
            ///    current instance is empty.
            /// </value>
00351             public bool IsEmpty {
                  get {return this.data.Count == 0;}
            }
            
            /// <summary>
            ///    Gets the CRC-32 checksum of the current instance.
            /// </summary>
            /// <value>
            ///    A <see cref="int" /> value containing the CRC-32 checksum
            ///    of the current instance.
            /// </value>
00362             public uint Checksum {
                  get {
                        uint sum = 0;
                        
                        foreach(byte b in this.data)
                              sum = (sum << 8) ^ crc_table
                                    [((sum >> 24) & 0xFF) ^ b];
                        
                        return sum;
                  }
            }
            
#endregion
            
            
            
#region Public Static Properties
            
            /// <summary>
            ///    Gets and sets whether or not to use a broken behavior for
            ///    Latin-1 strings, common to ID3v1 and ID3v2 tags.
            /// </summary>
            /// <value>
            ///    <see langword="true" /> if the broken behavior is to be
            ///    used. Otherwise, <see langword="false" />.
            /// </value>
            /// <remarks>
            ///    <para>Many media players and taggers incorrectly treat
            ///    Latin-1 fields as "default encoding" fields. As such, a
            ///    tag may end up with Windows-1250 encoded text. While this
            ///    problem would be apparent when moving a file from one
            ///    computer to another, it would not be apparent on the
            ///    original machine. By setting this property to <see
            ///    langword="true" />, your program will behave like Windows
            ///    Media Player and others, who read tags with this broken
            ///    behavior.</para>
            ///    <para>Please note that TagLib# stores tag data in Unicode
            ///    formats at every possible instance to avoid these
            ///    problems in tags it has written.</para>
            /// </remarks>
00402             public static bool UseBrokenLatin1Behavior {
                  get {return use_broken_latin1;}
                  set {use_broken_latin1 = value;}
            }
            
#endregion
            
            
            
#region Public Methods
            
            /// <summary>
            ///    Creates a new instance of <see cref="ByteVector" />
            ///    containing a specified range of elements from the current
            ///    instance.
            /// </summary>
            /// <param name="startIndex">
            ///    A <see cref="int" /> value specifying the index at which
            ///    to start copying elements from the current instance.
            /// </param>
            /// <param name="length">
            ///    A <see cref="int" /> value specifying the number of
            ///    elements to copy from the current instance.
            /// </param>
            /// <exception cref="ArgumentOutOfRangeException">
            ///    <paramref name="startIndex" /> is less than zero or
            ///    greater than or equal to <see cref="Count" />. OR
            ///    <paramref name="length" /> is less than zero or greater
            ///    than the amount of available data.
            /// </exception>
00432             public ByteVector Mid (int startIndex, int length)
            {
                  if (startIndex < 0 || startIndex > Count)
                        throw new ArgumentOutOfRangeException (
                              "startIndex");
                  
                  if (length < 0 || startIndex + length > Count)
                        throw new ArgumentOutOfRangeException (
                              "length");
                  
                  if (length == 0)
                        return new ByteVector ();
                        
                  if(startIndex + length > this.data.Count)
                        length = this.data.Count - startIndex;
                  
                  byte [] data = new byte [length];
                  
                  this.data.CopyTo (startIndex, data, 0, length);
                  
                  return data;
            }
            
            /// <summary>
            ///    Creates a new instance of <see cref="ByteVector" />
            ///    containing elements from the current instance starting
            ///    from a specified point.
            /// </summary>
            /// <param name="index">
            ///    A <see cref="int" /> value specifying the index at which
            ///    to start copying elements from the current instance.
            /// </param>
            /// <exception cref="ArgumentOutOfRangeException">
            ///    <paramref name="ndex" /> is less than zero or greater
            ///    than or equal to <see cref="Count" />.
            /// </exception>
00468             public ByteVector Mid (int index)
            {
                  return Mid(index, Count - index);
            }
            
            /// <summary>
            ///    Finds the first byte-aligned occurance of a pattern in
            ///    the current instance, starting at a specified position.
            /// </summary>
            /// <param name="pattern">
            ///    A <see cref="ByteVector"/> object containing the pattern
            ///    to search for in the current instance.
            /// </param>
            /// <param name="offset">
            ///    A <see cref="int"/> value specifying the index in the
            ///    current instance at which to start searching.
            /// </param>
            /// <param name="byteAlign">
            ///    A <see cref="int"/> value specifying the byte alignment
            ///    of the pattern to search for, relative to <paramref
            ///    name="offset" />.
            /// </param>
            /// <returns>
            ///    A <see cref="int"/> value containing the index at which
            ///    <paramref name="pattern" /> was found in the current
            ///    instance, or -1 if the pattern was not found. The
            ///    difference between the position and <paramref
            ///    name="offset" /> will be divisible by <paramref
            ///    name="byteAlign" />.
            /// </returns>
            /// <exception cref="ArgumentNullException">
            ///    <paramref name="pattern" /> is <see langword="null" />.
            /// </exception>
            /// <exception cref="ArgumentOutOfRangeException">
            ///    <paramref name="offset" /> is less than zero or
            ///    <paramref name="byteAlign" /> is less than 1.
            /// </exception>
00505             public int Find (ByteVector pattern, int offset, int byteAlign)
            {
                  if (pattern == null)
                        throw new ArgumentNullException ("pattern");
                  
                  if (offset < 0)
                        throw new ArgumentOutOfRangeException (
                              "offset", "offset must be at least 0.");
                  
                  if (byteAlign < 1)
                        throw new ArgumentOutOfRangeException (
                              "byteAlign",
                              "byteAlign must be at least 1.");
                  
                  if (pattern.Count > Count - offset)
                        return -1;
                  
                  // Let's go ahead and special case a pattern of size one
                  // since that's common and easy to make fast.
                  
                  if (pattern.Count == 1) {
                        byte p = pattern [0];
                        for (int i = offset; i < this.data.Count;
                              i += byteAlign)
                              if (this.data [i] == p)
                                    return i;
                        return -1;
                  }
                  
                  int [] last_occurrence = new int [256];
                  for (int i = 0; i < 256; ++i)
                        last_occurrence [i] = pattern.Count;
                  
                  for (int i = 0; i < pattern.Count - 1; ++i)
                        last_occurrence [pattern [i]] =
                              pattern.Count - i - 1;
                  
                  for (int i = pattern.Count - 1 + offset;
                        i < this.data.Count;
                        i += last_occurrence [this.data [i]]) {
                        int iBuffer = i;
                        int iPattern = pattern.Count - 1;
                        
                        while(iPattern >= 0 && this.data [iBuffer] ==
                              pattern [iPattern]) {
                              --iBuffer;
                              --iPattern;
                        }
                        
                        if (-1 == iPattern && (iBuffer + 1 - offset) %
                              byteAlign == 0)
                              return iBuffer + 1;
                  }
                  
                  return -1;
            }
            
            /// <summary>
            ///    Finds the first occurance of a pattern in the current
            ///    instance, starting at a specified position.
            /// </summary>
            /// <param name="pattern">
            ///    A <see cref="ByteVector"/> object containing the pattern
            ///    to search for in the current instance.
            /// </param>
            /// <param name="offset">
            ///    A <see cref="int"/> value specifying the index in the
            ///    current instance at which to start searching.
            /// </param>
            /// <returns>
            ///    A <see cref="int"/> value containing the index at which
            ///    <paramref name="pattern" /> was found in the current
            ///    instance, or -1 if the pattern was not found.
            /// </returns>
            /// <exception cref="ArgumentNullException">
            ///    <paramref name="pattern" /> is <see langword="null" />.
            /// </exception>
            /// <exception cref="ArgumentOutOfRangeException">
            ///    <paramref name="offset" /> is less than zero.
            /// </exception>
00585             public int Find(ByteVector pattern, int offset)
            {
                  return Find(pattern, offset, 1);
            }
            
            /// <summary>
            ///    Finds the first occurance of a pattern in the current
            ///    instance.
            /// </summary>
            /// <param name="pattern">
            ///    A <see cref="ByteVector"/> object containing the pattern
            ///    to search for in the current instance.
            /// </param>
            /// <returns>
            ///    A <see cref="int"/> value containing the index at which
            ///    <paramref name="pattern" /> was found in the current
            ///    instance, or -1 if the pattern was not found.
            /// </returns>
            /// <exception cref="ArgumentNullException">
            ///    <paramref name="pattern" /> is <see langword="null" />.
            /// </exception>
00606             public int Find(ByteVector pattern)
            {
                  return Find(pattern, 0, 1);
            }
            
            /// <summary>
            ///    Finds the last byte-aligned occurance of a pattern in
            ///    the current instance, starting before a specified
            ///    position.
            /// </summary>
            /// <param name="pattern">
            ///    A <see cref="ByteVector"/> object containing the pattern
            ///    to search for in the current instance.
            /// </param>
            /// <param name="offset">
            ///    A <see cref="int"/> value specifying the index in the
            ///    current instance at which to start searching.
            /// </param>
            /// <param name="byteAlign">
            ///    A <see cref="int"/> value specifying the byte alignment
            ///    of the pattern to search for, relative to <paramref
            ///    name="offset" />.
            /// </param>
            /// <returns>
            ///    A <see cref="int"/> value containing the index at which
            ///    <paramref name="pattern" /> was found in the current
            ///    instance, or -1 if the pattern was not found. The
            ///    difference between the position and <paramref
            ///    name="offset" /> will be divisible by <paramref
            ///    name="byteAlign" />.
            /// </returns>
            /// <exception cref="ArgumentNullException">
            ///    <paramref name="pattern" /> is <see langword="null" />.
            /// </exception>
            /// <exception cref="ArgumentOutOfRangeException">
            ///    <paramref name="offset" /> is less than zero.
            /// </exception>
00643             public int RFind (ByteVector pattern, int offset, int byteAlign)
            {
                  if (pattern == null)
                        throw new ArgumentNullException ("pattern");
                  
                  if (offset < 0)
                        throw new ArgumentOutOfRangeException (
                              "offset");
                  
                  if (pattern.Count == 0 || pattern.Count > Count - offset)
                        return -1;
                  
                  // Let's go ahead and special case a pattern of size one
                  // since that's common and easy to make fast.
                  
                  if (pattern.Count == 1) {
                        byte p = pattern [0];
                        for (int i = Count - offset - 1; i >= 0;
                              i -= byteAlign)
                              if (this.data [i] == p)
                                    return i;
                        return -1;
                  }
                  
                  int [] first_occurrence = new int [256];
                  
                  for (int i = 0; i < 256; ++i)
                        first_occurrence [i] = pattern.Count;
                  
                  for (int i = pattern.Count - 1; i > 0; --i)
                        first_occurrence [pattern [i]] = i;
                  
                  for (int i = Count - offset - pattern.Count; i >= 0;
                        i -= first_occurrence [this.data [i]])
                        if ((offset - i) % byteAlign == 0 &&
                              ContainsAt (pattern, i))
                              return i;
                  
                  return -1;
            }
            
            /// <summary>
            ///    Finds the last occurance of a pattern in the current
            ///    instance, starting before a specified position.
            /// </summary>
            /// <param name="pattern">
            ///    A <see cref="ByteVector"/> object containing the pattern
            ///    to search for in the current instance.
            /// </param>
            /// <param name="offset">
            ///    A <see cref="int"/> value specifying the index in the
            ///    current instance at which to start searching.
            /// </param>
            /// <returns>
            ///    A <see cref="int"/> value containing the index at which
            ///    <paramref name="pattern" /> was found in the current
            ///    instance, or -1 if the pattern was not found.
            /// </returns>
            /// <exception cref="ArgumentNullException">
            ///    <paramref name="pattern" /> is <see langword="null" />.
            /// </exception>
            /// <exception cref="ArgumentOutOfRangeException">
            ///    <paramref name="offset" /> is less than zero.
            /// </exception>
00707             public int RFind(ByteVector pattern, int offset)
            {
                  return RFind (pattern, offset, 1);
            }
            
            /// <summary>
            ///    Finds the last occurance of a pattern in the current
            ///    instance.
            /// </summary>
            /// <param name="pattern">
            ///    A <see cref="ByteVector"/> object containing the pattern
            ///    to search for in the current instance.
            /// </param>
            /// <returns>
            ///    A <see cref="int"/> value containing the index at which
            ///    <paramref name="pattern" /> was found in the current
            ///    instance, or -1 if the pattern was not found.
            /// </returns>
            /// <exception cref="ArgumentNullException">
            ///    <paramref name="pattern" /> is <see langword="null" />.
            /// </exception>
00728             public int RFind(ByteVector pattern)
            {
                  return RFind(pattern, 0, 1);
            }
            
            /// <summary>
            ///    Checks whether or not a pattern appears at a specified
            ///    position in the current instance.
            /// </summary>
            /// <param name="pattern">
            ///    A <see cref="ByteVector"/> object containing the pattern
            ///    to check for in the current instance.
            /// </param>
            /// <param name="offset">
            ///    A <see cref="int"/> value specifying the offset in the
            ///    current instance at which to check for the pattern.
            /// </param>
            /// <param name="patternOffset">
            ///    A <see cref="int"/> value specifying the position in
            ///    <paramref name="pattern" /> at which to start checking.
            /// </param>
            /// <param name="patternLength">
            ///    A <see cref="int"/> value specifying the number of bytes
            ///    in <paramref name="pattern" /> to compare.
            /// </param>
            /// <returns>
            ///    <see langword="true"/> if the pattern was found at the
            ///    specified position. Otherwise, <see langword="false"/>.
            /// </returns>
            /// <exception cref="ArgumentNullException">
            ///    <paramref name="pattern" /> is <see langword="null" />.
            /// </exception>
00760             public bool ContainsAt (ByteVector pattern, int offset, 
                                    int patternOffset, int patternLength)
            {
                  if (pattern == null)
                        throw new ArgumentNullException ("pattern");
                  
                  if(pattern.Count < patternLength) {
                        patternLength = pattern.Count;
                  }
                  
                  // do some sanity checking -- all of these things are 
                  // needed for the search to be valid
                  if (patternLength > this.data.Count ||
                        offset >= this.data.Count ||
                        patternOffset >= pattern.Count ||
                        patternLength <= 0 || offset < 0)
                        return false;
                  
                  // loop through looking for a mismatch
                  for (int i = 0; i < patternLength - patternOffset; i++)
                        if (this.data[i + offset] !=
                              pattern [i + patternOffset])
                              return false;
                  
                  return true;
            }
            
            /// <summary>
            ///    Checks whether or not a pattern appears at a specified
            ///    position in the current instance.
            /// </summary>
            /// <param name="pattern">
            ///    A <see cref="ByteVector"/> object containing the pattern
            ///    to check for in the current instance.
            /// </param>
            /// <param name="offset">
            ///    A <see cref="int"/> value specifying the offset in the
            ///    current instance at which to check for the pattern.
            /// </param>
            /// <param name="patternOffset">
            ///    A <see cref="int"/> value specifying the position in
            ///    <paramref name="pattern" /> at which to start checking.
            /// </param>
            /// <returns>
            ///    <see langword="true"/> if the pattern was found at the
            ///    specified position. Otherwise, <see langword="false"/>.
            /// </returns>
            /// <exception cref="ArgumentNullException">
            ///    <paramref name="pattern" /> is <see langword="null" />.
            /// </exception>
00810             public bool ContainsAt (ByteVector pattern, int offset,
                                    int patternOffset)
            {
                  return ContainsAt (pattern, offset, patternOffset,
                        int.MaxValue);
            }
            
            /// <summary>
            ///    Checks whether or not a pattern appears at a specified
            ///    position in the current instance.
            /// </summary>
            /// <param name="pattern">
            ///    A <see cref="ByteVector"/> object containing the pattern
            ///    to check for in the current instance.
            /// </param>
            /// <param name="offset">
            ///    A <see cref="int"/> value specifying the offset in the
            ///    current instance at which to check for the pattern.
            /// </param>
            /// <returns>
            ///    <see langword="true"/> if the pattern was found at the
            ///    specified position. Otherwise, <see langword="false"/>.
            /// </returns>
            /// <exception cref="ArgumentNullException">
            ///    <paramref name="pattern" /> is <see langword="null" />.
            /// </exception>
00836             public bool ContainsAt (ByteVector pattern, int offset)
            {
                  return ContainsAt (pattern, offset, 0);
            }
            
            /// <summary>
            ///    Checks whether or not a pattern appears at the beginning
            ///    of the current instance.
            /// </summary>
            /// <param name="pattern">
            ///    A <see cref="ByteVector"/> object containing the pattern
            ///    to check for in the current instance.
            /// </param>
            /// <returns>
            ///    <see langword="true"/> if the pattern was found at the
            ///    beginning of the current instance. Otherwise, <see
            ///    langword="false"/>.
            /// </returns>
            /// <exception cref="ArgumentNullException">
            ///    <paramref name="pattern" /> is <see langword="null" />.
            /// </exception>
00857             public bool StartsWith (ByteVector pattern)
            {
                  return ContainsAt (pattern, 0);
            }
            
            /// <summary>
            ///    Checks whether or not a pattern appears at the end of the
            ///    current instance.
            /// </summary>
            /// <param name="pattern">
            ///    A <see cref="ByteVector"/> object containing the pattern
            ///    to check for in the current instance.
            /// </param>
            /// <returns>
            ///    <see langword="true"/> if the pattern was found at the
            ///    end of the current instance. Otherwise, <see
            ///    langword="false"/>.
            /// </returns>
            /// <exception cref="ArgumentNullException">
            ///    <paramref name="pattern" /> is <see langword="null" />.
            /// </exception>
00878             public bool EndsWith (ByteVector pattern)
            {
                  if (pattern == null)
                        throw new ArgumentNullException ("pattern");
                  
                  return ContainsAt (pattern,
                        this.data.Count - pattern.Count);
            }
            
            /// <summary>
            ///    Checks whether or not the current instance ends with part
            ///    of a pattern.
            /// </summary>
            /// <param name="pattern">
            ///    A <see cref="ByteVector"/> object containing the pattern
            ///    to search for in the current instance.
            /// </param>
            /// <returns>
            ///    A <see cref="int" /> value containing the index at which
            ///    a partial match was located, or -1 if no match was found.
            /// </returns>
            /// <remarks>
            ///    <para>This function is useful for checking for patterns
            ///    across multiple buffers.</para>
            /// </remarks>
00903             public int EndsWithPartialMatch (ByteVector pattern)
            {
                  if (pattern == null)
                        throw new ArgumentNullException ("pattern");
                  
                  if(pattern.Count > this.data.Count) {
                        return -1;
                  }
                  
                  int start_index = this.data.Count - pattern.Count;
                  
                  // try to match the last n-1 bytes from the vector
                  // (where n is the pattern size) -- continue trying to
                  // match n-2, n-3...1 bytes
                  
                  for(int i = 1; i < pattern.Count; i++) {
                        if (ContainsAt (pattern, start_index + i, 0,
                              pattern.Count - i)) {
                              return start_index + i;
                        }
                  }
                  
                  return -1;
            }
            
            /// <summary>
            ///    Adds the contents of another <see cref="ByteVector" />
            ///    object to the end of the current instance.
            /// </summary>
            /// <param name="data">
            ///    A <see cref="ByteVector"/> object containing data to add
            ///    to the end of the current instance.
            /// </param>
            /// <exception cref="NotSupportedException">
            ///    The current instance is read-only.
            /// </exception>
00939             public void Add (ByteVector data)
            {
                  if (IsReadOnly)
                        throw new NotSupportedException (
                              "Cannot edit readonly objects.");
                  
                  if(data != null) {
                        this.data.AddRange(data);
                  }
            }
            
            /// <summary>
            ///    Adds the contents of an array to the end of the current
            ///    instance.
            /// </summary>
            /// <param name="data">
            ///    A <see cref="byte[]"/> containing data to add to the end
            ///    of the current instance.
            /// </param>
            /// <exception cref="NotSupportedException">
            ///    The current instance is read-only.
            /// </exception>
00961             public void Add (byte [] data)
            {
                  if (IsReadOnly)
                        throw new NotSupportedException (
                              "Cannot edit readonly objects.");
                  
                  if(data != null)
                        this.data.AddRange(data);
            }
            
            /// <summary>
            ///    Inserts the contents of another <see cref="ByteVector" />
            ///    object into the current instance.
            /// </summary>
            /// <param name="index">
            ///    A <see cref="int"/> value specifying the index at which
            ///    to insert the data.
            /// </param>
            /// <param name="data">
            ///    A <see cref="ByteVector"/> object containing data to
            ///    insert into the current instance.
            /// </param>
            /// <exception cref="NotSupportedException">
            ///    The current instance is read-only.
            /// </exception>
00986             public void Insert (int index, ByteVector data)
            {
                  if (IsReadOnly)
                        throw new NotSupportedException (
                              "Cannot edit readonly objects.");
                  
                  if (data != null)
                        this.data.InsertRange (index, data);
            }
            
            /// <summary>
            ///    Inserts the contents of an array to insert into the
            ///    current instance.
            /// </summary>
            /// <param name="index">
            ///    A <see cref="int"/> value specifying the index at which
            ///    to insert the data.
            /// </param>
            /// <param name="data">
            ///    A <see cref="byte[]"/> containing data to insert into the
            ///    current instance.
            /// </param>
            /// <exception cref="NotSupportedException">
            ///    The current instance is read-only.
            /// </exception>
01011             public void Insert (int index, byte [] data)
            {
                  if (IsReadOnly)
                        throw new NotSupportedException (
                              "Cannot edit readonly objects.");
                  
                  if (data != null)
                        this.data.InsertRange (index, data);
            }
            
            /// <summary>
            ///    Resizes the current instance.
            /// </summary>
            /// <param name="size">
            ///    A <see cref="int"/> value specifying the new size of the
            ///    current instance.
            /// </param>
            /// <param name="padding">
            ///    A <see cref="byte"/> object containing the padding byte
            ///    to use if the current instance is growing.
            /// </param>
            /// <returns>
            ///    The current instance.
            /// </returns>
            /// <exception cref="NotSupportedException">
            ///    The current instance is read-only.
            /// </exception>
01038             public ByteVector Resize (int size, byte padding)
            {
                  if (IsReadOnly)
                        throw new NotSupportedException (
                              "Cannot edit readonly objects.");
                  
                  if (this.data.Count > size)
                        this.data.RemoveRange (size,
                              this.data.Count - size);
                  
                  while (this.data.Count < size)
                        this.data.Add (padding);
                  
                  return this;
            }
            
            /// <summary>
            ///    Resizes the current instance.
            /// </summary>
            /// <param name="size">
            ///    A <see cref="int"/> value specifying the new size of the
            ///    current instance.
            /// </param>
            /// <returns>
            ///    The current instance.
            /// </returns>
            /// <remarks>
            ///    If the current instance grows, the added bytes are filled
            ///    with '0'. Use <see cref="Resize(int,byte)" /> to specify
            ///    the padding byte.
            /// </remarks>
            /// <exception cref="NotSupportedException">
            ///    The current instance is read-only.
            /// </exception>
            /// <seealso cref="Resize(int,byte)" />
01073             public ByteVector Resize (int size)
            {
                  return Resize (size, 0);
            }
            
            /// <summary>
            ///    Removes a range of data from the current instance.
            /// </summary>
            /// <param name="index">
            ///    A <see cref="int" /> value specifying the index at which
            ///    to start removing data.
            /// </param>
            /// <param name="count">
            ///    A <see cref="int"/> value specifying the number of bytes
            ///    to remove.
            /// </param>
            /// <exception cref="NotSupportedException">
            ///    The current instance is read-only.
            /// </exception>
01092             public void RemoveRange (int index, int count)
            {
                  if (IsReadOnly)
                        throw new NotSupportedException (
                              "Cannot edit readonly objects.");
                  
                  this.data.RemoveRange (index, count);
            }
            
#endregion
            
            
            
#region Conversions
            
            /// <summary>
            ///    Converts an first four bytes of the current instance to
            ///    a <see cref="int" /> value.
            /// </summary>
            /// <param name="mostSignificantByteFirst">
            ///    <see langword="true" /> if the most significant byte
            ///    appears first (big endian format), or <see
            ///    langword="false" /> if the least significant byte appears
            ///    first (little endian format).
            /// </param>
            /// <returns>
            ///    A <see cref="int"/> value containing the value read from
            ///    the current instance.
            /// </returns>
01121             public int ToInt (bool mostSignificantByteFirst)
            {
                  int ret = 0;
                  int last = Count > 4 ? 3 : Count - 1;

                  for (int i = 0; i <= last; i++) {
                        int offset = mostSignificantByteFirst ? last-i : i;
                        ret |= (int) this[i] << (offset * 8);
                  }

                  return ret;
            }

            /// <summary>
            ///    Converts an first four bytes of the current instance to
            ///    a <see cref="int" /> value using big-endian format.
            /// </summary>
            /// <returns>
            ///    A <see cref="int"/> value containing the value read from
            ///    the current instance.
            /// </returns>
01142             public int ToInt ()
            {
                  return ToInt (true);
            }

            /// <summary>
            ///    Converts an first four bytes of the current instance to
            ///    a <see cref="uint" /> value.
            /// </summary>
            /// <param name="mostSignificantByteFirst">
            ///    <see langword="true" /> if the most significant byte
            ///    appears first (big endian format), or <see
            ///    langword="false" /> if the least significant byte appears
            ///    first (little endian format).
            /// </param>
            /// <returns>
            ///    A <see cref="uint"/> value containing the value read from
            ///    the current instance.
            /// </returns>
01161             public uint ToUInt (bool mostSignificantByteFirst)
            {
                  uint sum = 0;
                  int last = Count > 4 ? 3 : Count - 1;
                  
                  for (int i = 0; i <= last; i++) {
                        int offset = mostSignificantByteFirst ? last-i : i;
                        sum |= (uint) this[i] << (offset * 8);
                  }
                  
                  return sum;
            }
            
            /// <summary>
            ///    Converts an first four bytes of the current instance to
            ///    a <see cref="uint" /> value using big-endian format.
            /// </summary>
            /// <returns>
            ///    A <see cref="uint"/> value containing the value read from
            ///    the current instance.
            /// </returns>
01182             public uint ToUInt ()
            {
                  return ToUInt (true);
            }
            
            /// <summary>
            ///    Converts an first two bytes of the current instance to a
            ///    <see cref="ushort" /> value.
            /// </summary>
            /// <param name="mostSignificantByteFirst">
            ///    <see langword="true" /> if the most significant byte
            ///    appears first (big endian format), or <see
            ///    langword="false" /> if the least significant byte appears
            ///    first (little endian format).
            /// </param>
            /// <returns>
            ///    A <see cref="ushort"/> value containing the value read
            ///    from the current instance.
            /// </returns>
01201             public ushort ToUShort (bool mostSignificantByteFirst)
            {
                  ushort sum = 0;
                  int last = Count > 2 ? 1 : Count - 1;
                  for (int i = 0; i <= last; i++) {
                        int offset = mostSignificantByteFirst ? last-i : i;
                        sum |= (ushort)(this[i] << (offset * 8));
                  }
                  
                  return sum;
            }
            
            /// <summary>
            ///    Converts an first two bytes of the current instance to
            ///    a <see cref="ushort" /> value using big-endian format.
            /// </summary>
            /// <returns>
            ///    A <see cref="ushort"/> value containing the value read
            ///    from the current instance.
            /// </returns>
01221             public ushort ToUShort ()
            {
                  return ToUShort (true);
            }
            
            /// <summary>
            ///    Converts an first eight bytes of the current instance to
            ///    a <see cref="ulong" /> value.
            /// </summary>
            /// <param name="mostSignificantByteFirst">
            ///    <see langword="true" /> if the most significant byte
            ///    appears first (big endian format), or <see
            ///    langword="false" /> if the least significant byte appears
            ///    first (little endian format).
            /// </param>
            /// <returns>
            ///    A <see cref="ulong"/> value containing the value read
            ///    from the current instance.
            /// </returns>
01240             public ulong ToULong (bool mostSignificantByteFirst)
            {
                  ulong sum = 0;
                  int last = Count > 8 ? 7 : Count - 1;
                  for(int i = 0; i <= last; i++) {
                        int offset = mostSignificantByteFirst ? last-i : i;
                        sum |= (ulong) this[i] << (offset * 8);
                  }
                  return sum;
            }
            
            /// <summary>
            ///    Converts an first eight bytes of the current instance to
            ///    a <see cref="ulong" /> value using big-endian format.
            /// </summary>
            /// <returns>
            ///    A <see cref="ulong"/> value containing the value read
            ///    from the current instance.
            /// </returns>
01259             public ulong ToULong ()
            {
                  return ToULong (true);
            }
            
            /// <summary>
            ///    Converts a portion of the current instance to a <see
            ///    cref="string"/> object using a specified encoding.
            /// </summary>
            /// <param name="type">
            ///    A <see cref="StringType"/> value indicating the encoding
            ///    to use when converting to a <see cref="string"/> object.
            /// </param>
            /// <param name="offset">
            ///    A <see cref="int"/> value specify the index in the
            ///    current instance at which to start converting.
            /// </param>
            /// <param name="count">
            ///    A <see cref="int"/> value specify the number of bytes to
            ///    convert.
            /// </param>
            /// <returns>
            ///    A <see cref="string"/> object containing the converted
            ///    text.
            /// </returns>
            /// <exception cref="ArgumentOutOfRangeException">
            ///    <paramref name="offset" /> is less than zero or greater
            ///    than the total number of bytes, or <paramref name="count"
            ///    /> is less than zero or greater than the number of bytes
            ///    after <paramref name="offset" />.
            /// </exception>
01290             public string ToString (StringType type, int offset, int count)
            {
                  if (offset < 0 || offset > Count)
                        throw new ArgumentOutOfRangeException ("offset");
                  
                  if (count < 0 || count + offset > Count)
                        throw new ArgumentOutOfRangeException ("count");
                  
                  ByteVector bom = type == StringType.UTF16 &&
                        this.data.Count - offset > 1 ? Mid (offset, 2) : null;
                  
                  string s = StringTypeToEncoding (type, bom)
                        .GetString (Data, offset, count);
                  
                  // UTF16 BOM
                  if(s.Length != 0 && (s[0] == 0xfffe || s[0] == 0xfeff)) 
                        return s.Substring (1);
                  
                  return s;
            }
            
            /// <summary>
            ///    Converts all data after a specified index in the current
            ///    instance to a <see cref="string"/> object using a
            ///    specified encoding.
            /// </summary>
            /// <param name="type">
            ///    A <see cref="StringType"/> value indicating the encoding
            ///    to use when converting to a <see cref="string"/> object.
            /// </param>
            /// <param name="offset">
            ///    A <see cref="int"/> value specify the index in the
            ///    current instance at which to start converting.
            /// </param>
            /// <returns>
            ///    A <see cref="string"/> object containing the converted
            ///    text.
            /// </returns>
            /// <exception cref="ArgumentOutOfRangeException">
            ///    <paramref name="offset" /> is less than zero or greater
            ///    than the total number of bytes.
            /// </exception>
            [Obsolete ("Use ToString(StringType,int,int)")]
01333             public string ToString (StringType type, int offset)
            {
                  return ToString (type, offset, Count - offset);
            }
            
            /// <summary>
            ///    Converts the current instance into a <see cref="string"/>
            ///    object using a specified encoding.
            /// </summary>
            /// <returns>
            ///    A <see cref="string"/> object containing the converted
            ///    text.
            /// </returns>
01346             public string ToString (StringType type)
            {
                  return ToString (type, 0, Count);
            }
            
            /// <summary>
            ///    Converts the current instance into a <see cref="string"/>
            ///    object using a UTF-8 encoding.
            /// </summary>
            /// <returns>
            ///    A <see cref="string"/> object containing the converted
            ///    text.
            /// </returns>
01359             public override string ToString ()
            {
                  return ToString (StringType.UTF8);
            }
            
            /// <summary>
            ///    Converts the current instance into a <see cref="string[]"
            ///    /> starting at a specified offset and using a specified
            ///    encoding, assuming the values are nil separated.
            /// </summary>
            /// <param name="type">
            ///    A <see cref="StringType"/> value indicating the encoding
            ///    to use when converting to a <see cref="string"/> object.
            /// </param>
            /// <param name="offset">
            ///    A <see cref="int"/> value specify the index in the
            ///    current instance at which to start converting.
            /// </param>
            /// <returns>
            ///    A <see cref="string[]" /> containing the converted text.
            /// </returns>
01380             public string[] ToStrings (StringType type, int offset)
            {
                  return ToStrings (type, offset, int.MaxValue);
            }
            
            /// <summary>
            ///    Converts the current instance into a <see cref="string[]"
            ///    /> starting at a specified offset and using a specified
            ///    encoding, assuming the values are nil separated and
            ///    limiting it to a specified number of items.
            /// </summary>
            /// <param name="type">
            ///    A <see cref="StringType"/> value indicating the encoding
            ///    to use when converting to a <see cref="string"/> object.
            /// </param>
            /// <param name="offset">
            ///    A <see cref="int"/> value specify the index in the
            ///    current instance at which to start converting.
            /// </param>
            /// <param name="count">
            ///    A <see cref="int"/> value specifying a limit to the
            ///    number of strings to create. Once the limit has been
            ///    reached, the last string will be filled by the remainder
            ///    of the data.
            /// </param>
            /// <returns>
            ///    A <see cref="string[]" /> containing the converted text.
            /// </returns>
01408             public string[] ToStrings (StringType type, int offset,
                                       int count)
            {
                  int chunk = 0;
                  int position = offset;
                  
                  List<string> list = new List<string> ();
                  ByteVector separator = TextDelimiter (type);
                  int align = separator.Count;
                  
                  while (chunk < count && position < Count) {
                        int start = position;
                        
                        if (chunk + 1 == count) {
                              position = offset + count;
                        } else {
                              position = Find (separator, start,
                                    align);
                              
                              if (position < 0)
                                    position = Count;
                        }
                        
                        int length = position - start;
                        
                        if (length == 0) {
                              list.Add (string.Empty);
                        } else {
                              string s = ToString (type, start,
                                    length);
                              if (s.Length != 0 && (s[0] == 0xfffe ||
                                    s[0] == 0xfeff)) { // UTF16 BOM
                                    s = s.Substring (1);
                              }
                              
                              list.Add (s);
                        }
                        
                        position += align;
                  }
                  
                  return list.ToArray ();
            }
            
#endregion
            
            
            
#region Operators
            
            /// <summary>
            ///    Determines whether two specified <see cref="ByteVector"
            ///    /> objects are equal.
            /// </summary>
            /// <param name="first">
            ///    A <see cref="ByteVector"/> to compare.
            /// </param>
            /// <param name="second">
            ///    A <see cref="ByteVector"/> to compare.
            /// </param>
            /// <returns>
            ///    <para><see langword="true" /> if <paramref name="first"
            ///    /> and <paramref name="second" /> contain the same
            ///    data; otherwise, <see langword="false" />.</para>
            /// </returns>
01473             public static bool operator== (ByteVector first,
                                           ByteVector second)
            {
                  bool fnull = (object) first == null;
                  bool snull = (object) second == null;
                  if (fnull && snull)
                        return true;
                  else if (fnull || snull)
                        return false;
                  
                  return first.Equals (second);
            }

            /// <summary>
            ///    Determines whether two specified <see cref="ByteVector"
            ///    /> objects differ.
            /// </summary>
            /// <param name="first">
            ///    A <see cref="ByteVector"/> to compare.
            /// </param>
            /// <param name="second">
            ///    A <see cref="ByteVector"/> to compare.
            /// </param>
            /// <returns>
            ///    <para><see langword="true" /> if <paramref name="first"
            ///    /> and <paramref name="second" /> contain different
            ///    data; otherwise, <see langword="false" />.</para>
            /// </returns>
01501             public static bool operator!= (ByteVector first,
                                           ByteVector second)
            {
                  return !(first == second);
            }

            /// <summary>
            ///    Determines whether or not one <see cref="ByteVector" />
            ///    is less than another.
            /// </summary>
            /// <param name="first">
            ///    A <see cref="ByteVector"/> to compare.
            /// </param>
            /// <param name="second">
            ///    A <see cref="ByteVector"/> to compare.
            /// </param>
            /// <returns>
            ///    <para><see langword="true" /> if <paramref name="first"
            ///    /> is less than <paramref name="second" />; otherwise,
            ///    <see langword="false" />.</para>
            /// </returns>
            /// <exception cref="ArgumentNullException">
            ///    <paramref name="first" /> or <paramref name="second" />
            ///    is <see langword="null" />.
            /// </exception>
01526             public static bool operator< (ByteVector first,
                                          ByteVector second)
            {
                  if (first == null)
                        throw new ArgumentNullException ("first");

                  if (second == null)
                        throw new ArgumentNullException ("second");
                  
                  return first.CompareTo (second) < 0;
            }

            /// <summary>
            ///    Determines whether or not one <see cref="ByteVector" />
            ///    is less than or equal to another.
            /// </summary>
            /// <param name="first">
            ///    A <see cref="ByteVector"/> to compare.
            /// </param>
            /// <param name="second">
            ///    A <see cref="ByteVector"/> to compare.
            /// </param>
            /// <returns>
            ///    <para><see langword="true" /> if <paramref name="first"
            ///    /> is less than or equal to <paramref name="second" />;
            ///    otherwise, <see langword="false" />.</para>
            /// </returns>
            /// <exception cref="ArgumentNullException">
            ///    <paramref name="first" /> or <paramref name="second" />
            ///    is <see langword="null" />.
            /// </exception>
01557             public static bool operator<= (ByteVector first,
                                           ByteVector second)
            {
                  if (first == null)
                        throw new ArgumentNullException ("first");
                  
                  if (second == null)
                        throw new ArgumentNullException ("second");
                  
                  return first.CompareTo (second) <= 0;
            }

            /// <summary>
            ///    Determines whether or not one <see cref="ByteVector" />
            ///    is greater than another.
            /// </summary>
            /// <param name="first">
            ///    A <see cref="ByteVector"/> to compare.
            /// </param>
            /// <param name="second">
            ///    A <see cref="ByteVector"/> to compare.
            /// </param>
            /// <returns>
            ///    <para><see langword="true" /> if <paramref name="first"
            ///    /> is greater than <paramref name="second" />; otherwise,
            ///    <see langword="false" />.</para>
            /// </returns>
            /// <exception cref="ArgumentNullException">
            ///    <paramref name="first" /> or <paramref name="second" />
            ///    is <see langword="null" />.
            /// </exception>
01588             public static bool operator> (ByteVector first,
                                          ByteVector second)
            {
                  if (first == null)
                        throw new ArgumentNullException ("first");

                  if (second == null)
                        throw new ArgumentNullException ("second");

                  return first.CompareTo (second) > 0;
            }

            /// <summary>
            ///    Determines whether or not one <see cref="ByteVector" />
            ///    is greater than or equal to another.
            /// </summary>
            /// <param name="first">
            ///    A <see cref="ByteVector"/> to compare.
            /// </param>
            /// <param name="second">
            ///    A <see cref="ByteVector"/> to compare.
            /// </param>
            /// <returns>
            ///    <para><see langword="true" /> if <paramref name="first"
            ///    /> is greater than or equal to <paramref name="second"
            ///    />; otherwise, <see langword="false" />.</para>
            /// </returns>
            /// <exception cref="ArgumentNullException">
            ///    <paramref name="first" /> or <paramref name="second" />
            ///    is <see langword="null" />.
            /// </exception>
01619             public static bool operator>= (ByteVector first,
                                           ByteVector second)
            {
                  if (first == null)
                        throw new ArgumentNullException ("first");

                  if (second == null)
                        throw new ArgumentNullException ("second");

                  return first.CompareTo (second) >= 0;
            }
            
            /// <summary>
            ///    Creates a new <see cref="ByteVector"/> object by adding
            ///    two objects together.
            /// </summary>
            /// <param name="first">
            ///    A <see cref="ByteVector"/> to combine.
            /// </param>
            /// <param name="second">
            ///    A <see cref="ByteVector"/> to combine.
            /// </param>
            /// <returns>
            ///    A new instance of <see cref="ByteVector" /> with the
            ///    contents of <paramref name="first" /> followed by the
            ///    contents of <paramref name="second" />.
            /// </returns>
01646             public static ByteVector operator+ (ByteVector first,
                                                ByteVector second)
            {
                  ByteVector sum = new ByteVector(first);
                  sum.Add(second);
                  return sum;
            }
            
            /// <summary>
            ///    Converts a <see cref="byte" /> to a new <see
            ///    cref="ByteVector" /> object.
            /// </summary>
            /// <param name="value">
            ///    A <see cref="byte" /> to convert.
            /// </param>
            /// <returns>
            ///    A new instance of <see cref="ByteVector" /> containing
            ///    <paramref name="value" />.
            /// </returns>
01665             public static implicit operator ByteVector (byte value)
            {
                  return new ByteVector (value);
            }

            /// <summary>
            ///    Converts a <see cref="byte[]" /> to a new <see
            ///    cref="ByteVector" /> object.
            /// </summary>
            /// <param name="value">
            ///    A <see cref="byte[]" /> to convert.
            /// </param>
            /// <returns>
            ///    A new instance of <see cref="ByteVector" /> containing
            ///    the contents of <paramref name="value" />.
            /// </returns>
01681             public static implicit operator ByteVector (byte [] value)
            {
                  return new ByteVector (value);
            }

            /// <summary>
            ///    Converts a <see cref="string" /> to a new <see
            ///    cref="ByteVector" /> object.
            /// </summary>
            /// <param name="value">
            ///    A <see cref="string" /> to convert.
            /// </param>
            /// <returns>
            ///    A new instance of <see cref="ByteVector" /> containing
            ///    the UTF-8 encoded contents of <paramref name="value" />.
            /// </returns>
01697             public static implicit operator ByteVector (string value)
            {
                  return ByteVector.FromString (value, StringType.UTF8);
            }
        
#endregion
            
            
            
#region Static Conversions
            
            /// <summary>
            ///    Converts a value into a data representation.
            /// </summary>
            /// <param name="value">
            ///    A <see cref="int"/> value to convert into bytes.
            /// </param>
            /// <param name="mostSignificantByteFirst">
            ///    <see langword="true" /> if the most significant byte is
            ///    to appear first (big endian format), or <see
            ///    langword="false" /> if the least significant byte is to
            ///    appear first (little endian format).
            /// </param>
            /// <returns>
            ///    A <see cref="ByteVector"/> object containing the encoded
            ///    representation of <paramref name="value" />.
            /// </returns>
01724             public static ByteVector FromInt (int value,
                                               bool mostSignificantByteFirst)
            {
                  ByteVector vector = new ByteVector();
                  for(int i = 0; i < 4; i++) {
                        int offset = mostSignificantByteFirst ? 3-i : i;
                        vector.Add ((byte)(value >> (offset * 8) & 0xFF));
                  }

                  return vector;
            }

            /// <summary>
            ///    Converts an value into a big-endian data representation.
            /// </summary>
            /// <param name="value">
            ///    A <see cref="int"/> value to convert into bytes.
            /// </param>
            /// <returns>
            ///    A <see cref="ByteVector"/> object containing the encoded
            ///    representation of <paramref name="value" />.
            /// </returns>
01746             public static ByteVector FromInt (int value)
            {
                  return FromInt (value, true);
            }

            /// <summary>
            ///    Converts an unsigned value into a data representation.
            /// </summary>
            /// <param name="value">
            ///    A <see cref="uint"/> value to convert into bytes.
            /// </param>
            /// <param name="mostSignificantByteFirst">
            ///    <see langword="true" /> if the most significant byte is
            ///    to appear first (big endian format), or <see
            ///    langword="false" /> if the least significant byte is to
            ///    appear first (little endian format).
            /// </param>
            /// <returns>
            ///    A <see cref="ByteVector"/> object containing the encoded
            ///    representation of <paramref name="value" />.
            /// </returns>
01767             public static ByteVector FromUInt (uint value,
                                               bool mostSignificantByteFirst)
            {
                  ByteVector vector = new ByteVector();
                  for(int i = 0; i < 4; i++) {
                        int offset = mostSignificantByteFirst ? 3-i : i;
                        vector.Add ((byte)(value >> (offset * 8) & 0xFF));
                  }
                  
                  return vector;
            }
            
            /// <summary>
            ///    Converts an unsigned value into a big-endian data
            ///    representation.
            /// </summary>
            /// <param name="value">
            ///    A <see cref="uint"/> value to convert into bytes.
            /// </param>
            /// <returns>
            ///    A <see cref="ByteVector"/> object containing the encoded
            ///    representation of <paramref name="value" />.
            /// </returns>
01790             public static ByteVector FromUInt (uint value)
            {
                  return FromUInt(value, true);
            }
            
            /// <summary>
            ///    Converts an unsigned value into a data representation.
            /// </summary>
            /// <param name="value">
            ///    A <see cref="ushort"/> value to convert into bytes.
            /// </param>
            /// <param name="mostSignificantByteFirst">
            ///    <see langword="true" /> if the most significant byte is
            ///    to appear first (big endian format), or <see
            ///    langword="false" /> if the least significant byte is to
            ///    appear first (little endian format).
            /// </param>
            /// <returns>
            ///    A <see cref="ByteVector"/> object containing the encoded
            ///    representation of <paramref name="value" />.
            /// </returns>
01811             public static ByteVector FromUShort (ushort value,
                                                 bool mostSignificantByteFirst)
            {
                  ByteVector vector = new ByteVector();
                  for(int i = 0; i < 2; i++) {
                        int offset = mostSignificantByteFirst ? 1-i : i;
                        vector.Add ((byte)(value >> (offset * 8) & 0xFF));
                  }
                  
                  return vector;
            }
            
            /// <summary>
            ///    Converts an unsigned value into a big-endian data
            ///    representation.
            /// </summary>
            /// <param name="value">
            ///    A <see cref="ushort"/> value to convert into bytes.
            /// </param>
            /// <returns>
            ///    A <see cref="ByteVector"/> object containing the encoded
            ///    representation of <paramref name="value" />.
            /// </returns>
01834             public static ByteVector FromUShort(ushort value)
            {
                  return FromUShort (value, true);
            }
            
            /// <summary>
            ///    Converts an unsigned value into a data representation.
            /// </summary>
            /// <param name="value">
            ///    A <see cref="ulong"/> value to convert into bytes.
            /// </param>
            /// <param name="mostSignificantByteFirst">
            ///    <see langword="true" /> if the most significant byte is
            ///    to appear first (big endian format), or <see
            ///    langword="false" /> if the least significant byte is to
            ///    appear first (little endian format).
            /// </param>
            /// <returns>
            ///    A <see cref="ByteVector"/> object containing the encoded
            ///    representation of <paramref name="value" />.
            /// </returns>
01855             public static ByteVector FromULong (ulong value,
                                                bool mostSignificantByteFirst)
            {
                  ByteVector vector = new ByteVector();
                  for(int i = 0; i < 8; i++) {
                        int offset = mostSignificantByteFirst ? 7-i : i;
                        vector.Add ((byte)(value >> (offset * 8) & 0xFF));
                  }
                  return vector;
            }
            
            /// <summary>
            ///    Converts an unsigned value into a big-endian data
            ///    representation.
            /// </summary>
            /// <param name="value">
            ///    A <see cref="ulong"/> value to convert into bytes.
            /// </param>
            /// <returns>
            ///    A <see cref="ByteVector"/> object containing the encoded
            ///    representation of <paramref name="value" />.
            /// </returns>
01877             public static ByteVector FromULong(ulong value)
            {
                  return FromULong(value, true);
            }
            
            /// <summary>
            ///    Converts an string into a encoded data representation.
            /// </summary>
            /// <param name="text">
            ///    A <see cref="string"/> object containing the text to
            ///    convert.
            /// </param>
            /// <param name="type">
            ///    A <see cref="StringType"/> value specifying the encoding
            ///    to use when converting the text.
            /// </param>
            /// <param name="length">
            ///    A <see cref="int"/> value specifying the number of
            ///    characters in <paramref name="text" /> to encoded.
            /// </param>
            /// <returns>
            ///    A <see cref="ByteVector"/> object containing the encoded
            ///    representation of <paramref name="text" />.
            /// </returns>
01901             public static ByteVector FromString (string text,
                                                 StringType type,
                                                 int length)
            {
                  ByteVector data = new ByteVector ();
                  
                  if (type == StringType.UTF16)
                        data.Add (new byte [] {0xff, 0xfe});
                  
                  if (text == null || text.Length == 0)
                        return data;
                  
                  if (text.Length > length)
                        text = text.Substring (0, length);
                  
                  data.Add (StringTypeToEncoding (type, data)
                        .GetBytes (text));
                  
                  return data;
            }
            
            /// <summary>
            ///    Converts an string into a encoded data representation.
            /// </summary>
            /// <param name="text">
            ///    A <see cref="string"/> object containing the text to
            ///    convert.
            /// </param>
            /// <param name="type">
            ///    A <see cref="StringType"/> value specifying the encoding
            ///    to use when converting the text.
            /// </param>
            /// <returns>
            ///    A <see cref="ByteVector"/> object containing the encoded
            ///    representation of <paramref name="text" />.
            /// </returns>
01937             public static ByteVector FromString(string text,
                                                StringType type)
            {
                  return FromString(text, type, Int32.MaxValue);
            }
            
            /// <summary>
            ///    Converts an string into a encoded data representation.
            /// </summary>
            /// <param name="text">
            ///    A <see cref="string"/> object containing the text to
            ///    convert.
            /// </param>
            /// <param name="length">
            ///    A <see cref="int"/> value specifying the number of
            ///    characters in <paramref name="text" /> to encoded.
            /// </param>
            /// <returns>
            ///    A <see cref="ByteVector"/> object containing the encoded
            ///    representation of <paramref name="text" />.
            /// </returns>
01958             public static ByteVector FromString(string text, int length)
            {
                  return FromString(text, StringType.UTF8, length);
            }
            
            /// <summary>
            ///    Converts an string into a encoded data representation.
            /// </summary>
            /// <param name="text">
            ///    A <see cref="string"/> object containing the text to
            ///    convert.
            /// </param>
            /// <returns>
            ///    A <see cref="ByteVector"/> object containing the encoded
            ///    representation of <paramref name="text" />.
            /// </returns>
            [Obsolete("Use FromString(string,StringType)")]
01975             public static ByteVector FromString(string text)
            {
                  return FromString (text, StringType.UTF8);
            }
            
            /// <summary>
            ///    Creates a new instance of <see cref="ByteVector" /> by
            ///    reading in the contents of a specified file.
            /// </summary>
            /// <param name="path">
            ///    A <see cref="string"/> object containing the path of the
            ///    file to read.
            /// </param>
            /// <returns>
            ///    A <see cref="ByteVector"/> object containing the contents
            ///    of the specified file.
            /// </returns>
            /// <exception cref="ArgumentNullException">
            ///    <paramref name="path" /> is <see langword="null" />.
            /// </exception>
01995             public static ByteVector FromPath (string path)
            {
                  byte [] tmp_out;
                  return FromPath (path, out tmp_out, false);
            }
            
            /// <summary>
            ///    Creates a new instance of <see cref="ByteVector" /> by
            ///    reading in the contents of a specified file.
            /// </summary>
            /// <param name="path">
            ///    A <see cref="string"/> object containing the path of the
            ///    file to read.
            /// </param>
            /// <param name="firstChunk">
            ///    A <see cref="byte[]"/> reference to be filled with the
            ///    first data chunk from the read file.
            /// </param>
            /// <param name="copyFirstChunk">
            ///    A <see cref="bool"/> value specifying whether or not to
            ///    copy the first chunk of the file into <paramref
            ///    name="firstChunk" />.
            /// </param>
            /// <returns>
            ///    A <see cref="ByteVector"/> object containing the contents
            ///    of the specified file.
            /// </returns>
            /// <exception cref="ArgumentNullException">
            ///    <paramref name="path" /> is <see langword="null" />.
            /// </exception>
02025             internal static ByteVector FromPath (string path,
                                                 out byte [] firstChunk,
                                                 bool copyFirstChunk)
            {
                  if (path == null)
                        throw new ArgumentNullException ("path");
                  
                  return FromFile (new File.LocalFileAbstraction (path),
                        out firstChunk, copyFirstChunk);
            }
            
            /// <summary>
            ///    Creates a new instance of <see cref="ByteVector" /> by
            ///    reading in the contents of a specified file abstraction.
            /// </summary>
            /// <param name="abstraction">
            ///    A <see cref="File.IFileAbstraction"/> object containing
            ///    abstraction of the file to read.
            /// </param>
            /// <returns>
            ///    A <see cref="ByteVector"/> object containing the contents
            ///    of the specified file.
            /// </returns>
            /// <exception cref="ArgumentNullException">
            ///    <paramref name="abstraction" /> is <see langword="null"
            ///    />.
            /// </exception>
02052             public static ByteVector FromFile (File.IFileAbstraction
                                               abstraction)
            {
                  byte [] tmp_out;
                  return FromFile (abstraction, out tmp_out, false);
            }
            
            /// <summary>
            ///    Creates a new instance of <see cref="ByteVector" /> by
            ///    reading in the contents of a specified file abstraction.
            /// </summary>
            /// <param name="abstraction">
            ///    A <see cref="File.IFileAbstraction"/> object containing
            ///    abstraction of the file to read.
            /// </param>
            /// <param name="firstChunk">
            ///    A <see cref="byte[]"/> reference to be filled with the
            ///    first data chunk from the read file.
            /// </param>
            /// <param name="copyFirstChunk">
            ///    A <see cref="bool"/> value specifying whether or not to
            ///    copy the first chunk of the file into <paramref
            ///    name="firstChunk" />.
            /// </param>
            /// <returns>
            ///    A <see cref="ByteVector"/> object containing the contents
            ///    of the specified file.
            /// </returns>
            /// <exception cref="ArgumentNullException">
            ///    <paramref name="abstraction" /> is <see langword="null"
            ///    />.
            /// </exception>
02084             internal static ByteVector FromFile (File.IFileAbstraction
                                                 abstraction,
                                                 out byte [] firstChunk,
                                                 bool copyFirstChunk)
            {
                  if (abstraction == null)
                        throw new ArgumentNullException ("abstraction");
                  
                  System.IO.Stream stream = abstraction.ReadStream;
                  ByteVector output = FromStream (stream, out firstChunk,
                        copyFirstChunk);
                  abstraction.CloseStream (stream);
                  return output;
            }
            
            /// <summary>
            ///    Creates a new instance of <see cref="ByteVector" /> by
            ///    reading in the contents of a specified stream.
            /// </summary>
            /// <param name="stream">
            ///    A <see cref="System.IO.Stream"/> object containing
            ///    the stream to read.
            /// </param>
            /// <returns>
            ///    A <see cref="ByteVector"/> object containing the contents
            ///    of the specified stream.
            /// </returns>
            /// <exception cref="ArgumentNullException">
            ///    <paramref name="stream" /> is <see langword="null" />.
            /// </exception>
02114             public static ByteVector FromStream (System.IO.Stream stream)
            {
                  byte [] tmp_out;
                  return FromStream (stream, out tmp_out, false);
            }
            
            /// <summary>
            ///    Creates a new instance of <see cref="ByteVector" /> by
            ///    reading in the contents of a specified stream.
            /// </summary>
            /// <param name="stream">
            ///    A <see cref="System.IO.Stream"/> object containing
            ///    the stream to read.
            /// </param>
            /// <param name="firstChunk">
            ///    A <see cref="byte[]"/> reference to be filled with the
            ///    first data chunk from the read stream.
            /// </param>
            /// <param name="copyFirstChunk">
            ///    A <see cref="bool"/> value specifying whether or not to
            ///    copy the first chunk of the stream into <paramref
            ///    name="firstChunk" />.
            /// </param>
            /// <returns>
            ///    A <see cref="ByteVector"/> object containing the contents
            ///    of the specified stream.
            /// </returns>
            /// <exception cref="ArgumentNullException">
            ///    <paramref name="stream" /> is <see langword="null" />.
            /// </exception>
02144             internal static ByteVector FromStream (System.IO.Stream stream,
                                                   out byte [] firstChunk,
                                                   bool copyFirstChunk)
            {
                  ByteVector vector = new ByteVector();
                  byte [] bytes = new byte[4096];
                  int read_size = bytes.Length;
                  int bytes_read = 0;
                  bool set_first_chunk = false;
                  
                  firstChunk = null;
                  
                  while (true) {
                        Array.Clear(bytes, 0, bytes.Length);
                        int n = stream.Read(bytes, 0, read_size);
                        vector.Add(bytes);
                        bytes_read += n;
                        
                        if (!set_first_chunk) {
                              if (copyFirstChunk) {
                                    if(firstChunk == null ||
                                          firstChunk.Length != read_size) {
                                          firstChunk = new byte [read_size];
                                    }
                                    
                                    Array.Copy (bytes, 0, firstChunk, 0, n);
                              }
                              set_first_chunk = true;
                        }
                        
                        if ((bytes_read == stream.Length && stream.Length > 0) || 
                              (n < read_size && stream.Length <= 0)) {
                              break;
                        }
                  }
                  
                  if (stream.Length > 0 && vector.Count != stream.Length) {
                        vector.Resize ((int)stream.Length);
                  }
                  
                  return vector;
            }
            
#endregion
            
            
            
#region Utilities
            
            /// <summary>
            ///    Gets the text delimiter for nil separated string lists of
            ///    a specified encoding.
            /// </summary>
            /// <param name="type">
            ///    A <see cref="StringType"/> value specifying the encoding
            ///    to use.
            /// </param>
            /// <returns>
            ///    A <see cref="ByteVector"/> object containing the text
            ///    delimiter.
            /// </returns>
02205             public static ByteVector TextDelimiter (StringType type)
            {
                  return type == StringType.UTF16 ||
                        type == StringType.UTF16BE ||
                        type == StringType.UTF16LE ? td2 : td1;
            }
            
            /// <summary>
            ///    Gets the <see cref="Encoding" /> to use for a specified
            ///    encoding.
            /// </summary>
            /// <param name="type">
            ///    A <see cref="StringType"/> value specifying encoding to
            ///    use.
            /// </param>
            /// <param name="bom">
            ///    A <see cref="ByteVector"/> object containing the first
            ///    two bytes of the data to convert if <paramref
            ///    name="type" /> equals <see cref="StringType.UTF16" />.
            /// </param>
            /// <returns>
            ///    A <see cref="Encoding" /> object capable of encoding
            ///    and decoding text with the specified type.
            /// </returns>
            /// <remarks>
            ///    <paramref name="bom" /> is used to determine whether the
            ///    encoding is big or little endian. If it does not contain
            ///    BOM data, the previously used endian format is used.
            /// </remarks>
02234             private static Encoding StringTypeToEncoding (StringType type,
                                                          ByteVector bom)
            {
                  switch(type) {
                  case StringType.UTF16:
                        // If we have a BOM, return the appropriate
                        // encoding. Otherwise, assume we're reading
                        // from a string that was already identified. In
                        // that case, the encoding will be stored as
                        // last_utf16_encoding.
                        
                        if (bom == null)
                              return last_utf16_encoding;
                        
                        if (bom [0] == 0xFF && bom [1] == 0xFE)
                              return last_utf16_encoding =
                                    Encoding.Unicode;
                        
                        if (bom [1] == 0xFF && bom [0] == 0xFE)
                              return last_utf16_encoding =
                                    Encoding.BigEndianUnicode;
                        
                        return last_utf16_encoding;
                        
                  case StringType.UTF16BE:
                        return Encoding.BigEndianUnicode;
                        
                  case StringType.UTF8:
                        return Encoding.UTF8;
                        
                  case StringType.UTF16LE:
                        return Encoding.Unicode;
                  }
                  
                  if (use_broken_latin1)
                        return Encoding.Default;
                  
                  try {
                        return Encoding.GetEncoding ("latin1");
                  } catch (ArgumentException) {
                        return Encoding.UTF8;
                  }
            }
            
#endregion
            
            
            
#region System.Object
            
            /// <summary>
            ///    Determines whether another object is equal to the current
            ///    instance.
            /// </summary>
            /// <param name="other">
            ///    A <see cref="object"/> to compare to the current
            ///    instance.
            /// </param>
            /// <returns>
            ///    <see langword="true" /> if <paramref name="other"/> is not
            ///    <see langword="null" />, is of type <see
            ///    cref="ByteVector" />, and is equal to the current
            ///    instance; otherwise <see langword="false" />.
            /// </returns>
02298             public override bool Equals (object other)
            {
                  if (!(other is ByteVector))
                        return false;
                  
                  return Equals ((ByteVector) other);
            }
            
            /// <summary>
            ///    Determines whether another <see cref="ByteVector"/>
            ///    object is equal to the current instance.
            /// </summary>
            /// <param name="other">
            ///    A <see cref="ByteVector"/> object to compare to the
            ///    current instance.
            /// </param>
            /// <returns>
            ///    <see langword="true" /> if <paramref name="other"/> is not
            ///    <see langword="null" /> and equal to the current instance;
            ///    otherwise <see langword="false" />.
            /// </returns>
02319             public bool Equals (ByteVector other)
            {
                  return CompareTo (other) == 0;
            }
            
            /// <summary>
            ///    Gets the hash value for the current instance.
            /// </summary>
            /// <returns>
            ///    A <see cref="int" /> value equal to the CRC checksum of
            ///    the current instance.
            /// </returns>
02331             public override int GetHashCode ()
            {
                  unchecked {return (int) Checksum;}
            }
            
#endregion
            
            
            
#region IComparable<T>
            
            /// <summary>
            ///    Compares the current instance to another to determine if
            ///    their order.
            /// </summary>
            /// <param name="other">
            ///    A <see cref="ByteVector" /> object to compare to the
            ///    current instance.
            /// </param>
            /// <returns>
            ///    A <see cref="int" /> which is less than zero if the
            ///    current instance is less than <paramref name="other" />,
            ///    zero if it is equal to <paramref name="other" />, and
            ///    greater than zero if the current instance is greater than
            ///    <paramref name="other" />.
            /// </returns>
02357             public int CompareTo (ByteVector other)
            {
                  if ((object) other == null)
                        throw new ArgumentNullException ("other");
            
                  int diff = Count - other.Count;
            
                  for(int i = 0; diff == 0 && i < Count; i ++)
                        diff = this [i] - other [i];
            
                  return diff;
            }
            
#endregion
            
            
            
#region IEnumerable<T>

            /// <summary>
            ///    Gets an enumerator for enumerating through the the bytes
            ///    in the current instance.
            /// </summary>
            /// <returns>
            ///    A <see cref="T:System.Collections.IEnumerator`1" /> for
            ///    enumerating through the contents of the current instance.
            /// </returns>
02384             public IEnumerator<byte> GetEnumerator()
            {
                  return this.data.GetEnumerator();
            }

            IEnumerator IEnumerable.GetEnumerator()
            {
                  return this.data.GetEnumerator();
            }
            
#endregion
            
            
            
#region ICollection<T>
            
            /// <summary>
            ///    Clears the current instance.
            /// </summary>
            /// <exception cref="NotSupportedException">
            ///    The current instance is read-only.
            /// </exception>
02406             public void Clear()
            {
                  if (IsReadOnly)
                        throw new NotSupportedException ("Cannot edit readonly objects.");
            
                  this.data.Clear();
            }
            
            /// <summary>
            ///    Adds a single byte to the end of the current instance.
            /// </summary>
            /// <param name="item">
            ///    A <see cref="byte" /> to add to the current instance.
            /// </param>
            /// <exception cref="NotSupportedException">
            ///    The current instance is read-only.
            /// </exception>
02423             public void Add (byte item)
            {
                  if (IsReadOnly)
                        throw new NotSupportedException (
                              "Cannot edit readonly objects.");
            
                  this.data.Add(item);
            }
            
            /// <summary>
            ///    Removes the first occurance of a <see cref="byte" /> from
            ///    the current instance.
            /// </summary>
            /// <param name="item">
            ///    A <see cref="byte"/> to remove from the current instance.
            /// </param>
            /// <returns>
            ///    <see langword="true" /> if the value was removed;
            ///    otherwise the value did not appear in the current
            ///    instance and <see langword="false" /> is returned.
            /// </returns>
            /// <exception cref="NotSupportedException">
            ///    The current instance is read-only.
            /// </exception>
02447             public bool Remove (byte item)
            {
                  if (IsReadOnly)
                        throw new NotSupportedException (
                              "Cannot edit readonly objects.");
                  
                  return this.data.Remove(item);
            }
            
            /// <summary>
            ///    Copies the current instance to a <see cref="byte[]"/>
            ///    starting at a specified index.
            /// </summary>
            /// <param name="array">
            ///    A <see cref="byte[]" /> to copy to.
            /// </param>
            /// <param name="arrayIndex">
            ///    A <see cref="int" /> value indicating the index in
            ///    <paramref name="array" /> at which to start copying.
            /// </param>
02467             public void CopyTo (byte [] array, int arrayIndex)
            {
                  this.data.CopyTo (array, arrayIndex);
            }
            
            /// <summary>
            ///    Gets whether or not the current instance contains a
            ///    specified byte.
            /// </summary>
            /// <param name="item">
            ///    A <see cref="byte" /> value to look for in the current
            ///    instance.
            /// </param>
            /// <returns>
            ///    <see langword="true" /> if the value could be found;
            ///    otherwise <see langword="false" />.
            /// </returns>
02484             public bool Contains (byte item)
            {
                  return this.data.Contains (item);
            }
            
            /// <summary>
            ///    Gets the number of elements in the current instance.
            /// </summary>
            /// <value>
            ///    A <see cref="int" /> value containing the number of bytes
            ///    in the current instance.
            /// </value>
02496             public int Count {
                  get {return this.data.Count;}
            }
            
            /// <summary>
            ///    Gets whether or not the current instance is synchronized.
            /// </summary>
            /// <value>
            ///    Always <see langword="false" />.
            /// </value>
02506             public bool IsSynchronized {
                  get {return false;}
            }
            
            /// <summary>
            ///    Gets the object that can be used to synchronize the
            ///    current instance.
            /// </summary>
            /// <value>
            ///    A <see cref="object" /> that can be used to synchronize
            ///    the current instance.
            /// </value>
02518             public object SyncRoot {
                  get {return this;}
            }
            
#endregion
            
            
            
#region IList<T>
            
            /// <summary>
            ///    Removes the byte at the specified index.
            /// </summary>
            /// <param name="index">
            ///    A <see cref="int" /> value specifying the position at
            ///    which to remove a byte.
            /// </param>
            /// <exception cref="NotSupportedException">
            ///    The current instance is read-only.
            /// </exception>
02538             public void RemoveAt (int index)
            {
                  if (IsReadOnly)
                        throw new NotSupportedException (
                              "Cannot edit readonly objects.");
                  
                  this.data.RemoveAt(index);
            }
            
            /// <summary>
            ///    Inserts a single byte into the current instance at a
            //     specified index.
            /// </summary>
            /// <param name="index">
            ///    A <see cref="int" /> value specifying the position at
            ///    which to insert the value.
            /// </param>
            /// <param name="item">
            ///    A <see cref="byte"/> value to insert into the current
            ///    instance.
            /// </param>
            /// <exception cref="NotSupportedException">
            ///    The current instance is read-only.
            /// </exception>
02562             public void Insert (int index, byte item)
            {
                  if (IsReadOnly)
                        throw new NotSupportedException (
                              "Cannot edit readonly objects.");
                  
                  this.data.Insert(index, item);
            }
            
            /// <summary>
            ///    Gets the index of the first occurance of a value.
            /// </summary>
            /// <param name="item">
            ///    A <see cref="byte" /> to find in the current instance.
            /// </param>
            /// <returns>
            ///    A <see cref="int" /> value containing the first index
            ///    at which the value was found, or -1 if it was not found.
            /// </returns>
02581             public int IndexOf (byte item)
            {
                  return this.data.IndexOf (item);
            }
            
            /// <summary>
            ///    Gets whether or not the current instance is read-only.
            /// </summary>
            /// <value>
            ///    <see langword="true" /> if the current instance is
            ///    read-only; otherwise <see langword="false" />.
            /// </value>
02593             public virtual bool IsReadOnly {
                  get {return false;}
            }
            
            /// <summary>
            ///    Gets whether or not the current instance has a fixed
            ///    size.
            /// </summary>
            /// <value>
            ///    <see langword="true" /> if the current instance has a
            ///    fixed size; otherwise <see langword="false" />.
            /// </value>
02605             public virtual bool IsFixedSize {
                  get {return false;}
            }
            
            /// <summary>
            ///    Gets and sets the value as a specified index.
            /// </summary>
            /// <exception cref="NotSupportedException">
            ///    The current instance is read-only.
            /// </exception>
02615             public byte this[int index] {
                  get {return this.data[index]; }
                  set {
                        if (IsReadOnly)
                              throw new NotSupportedException (
                                    "Cannot edit readonly objects.");
                        
                        data[index] = value;
                  }
            }
            
#endregion
      }
}

Generated by  Doxygen 1.6.0   Back to index