Click here to Skip to main content
15,896,063 members
Articles / Programming Languages / C#

Buffer with overwrite protection and memory allocation on demand

Rate me:
Please Sign up or sign in to vote.
4.57/5 (7 votes)
10 Mar 2008CPOL7 min read 28.2K   244   22  
Implementation of a large memory buffer, with memory allocation on demand and overwrite protection.
using System;
using System.Collections.Generic;
using System.Text;
using System.Globalization;

namespace Buffers
{
	[Serializable]
	class WordBuffer : IEquatable<WordBuffer>
	{
		#region Constants

		const int cntMinNumBytesPerWord = 1;
		const int cntMaxNumBytesPerWord = 8;

		#endregion

		#region Private members

		bool locked;
		int numWords;
		int numBytesPerWord;
		long defaultValue;
		byte[] defaultValueInBytes;
		byte[] buffer;

		#endregion

		#region Constructor

		public WordBuffer(int numWords, int numBytesPerWord, long defaultValue)
		{
			if(numBytesPerWord<cntMinNumBytesPerWord || numBytesPerWord>cntMaxNumBytesPerWord)
				throw new ArgumentOutOfRangeException("numBytesPerWord",
					string.Format(CultureInfo.InvariantCulture, StringResources.ArgumentOutOfRangeMessage, "numBytesPerWord", 
					numBytesPerWord, cntMinNumBytesPerWord, cntMaxNumBytesPerWord));

			this.numWords = numWords;
			this.numBytesPerWord = numBytesPerWord;

			// Default value as a byte array
			long bwValue = defaultValue;
			defaultValueInBytes = new byte[numBytesPerWord];
			for(int i=0; i<numBytesPerWord; i++)
			{
				defaultValueInBytes[i] = (byte)bwValue;
				bwValue>>=8;
			}
			// Default value casted to the number of bytes
			for(int i=numBytesPerWord-1; i>=0; i--)
				this.defaultValue = (this.defaultValue<<8) + defaultValueInBytes[i];
		}

		#endregion

		#region Properties

		/// <summary>
		/// Returns true if no data has been written in the buffer (so the buffer is not allocated)
		/// </summary>
		public bool IsEmpty
		{
			get { return buffer==null; }
		}

		/// <summary>
		/// Returns true if the buffer is locked (readonly)
		/// </summary>
		public bool IsLocked
		{
			get { return locked; }
		}

		#endregion

		#region Public Methods

		/// <summary>
		/// Gets the byte[] as an integer value depending on the numBytesPerWord
		/// </summary>
		public long GetIntegerData(int byteOffset)
		{
			if(buffer==null)
			{
				return defaultValue;
			}
			else
			{
				switch(numBytesPerWord)
				{
					case 1:
						return (long)buffer[byteOffset];
					case 2:
						return (long)BitConverter.ToUInt16(buffer, byteOffset);
					case 4:
						return (long)BitConverter.ToUInt32(buffer, byteOffset);
					default:
						long data = 0;
						for(int i=numBytesPerWord-1; i>=0; i--)
							data = (data<<8) + buffer[byteOffset+i];
						return data;
				}
			}
		}

		/// <summary>
		/// Sets the byte[] as an integer value depending on the numBytesPerWord
		/// </summary>
		public void SetIntegerData(int byteOffset, long value)
		{
			if(IsLocked)
				throw new BufferIsReadOnlyException();
			
			if(buffer==null)
				AllocateBuffer();

			Buffer.BlockCopy(BitConverter.GetBytes(value), 0, buffer, byteOffset, numBytesPerWord);
		}

		/// <summary>
		/// Locks the buffer so it'll be read only
		/// </summary>
		public void Lock()
		{
			locked = true;
		}

		/// <summary>
		/// Frees the memory used by the buffer (all data is lost)
		/// </summary>
		public void Free()
		{
			buffer = null;
		}
		#endregion

		#region Private methods

		private void AllocateBuffer()
		{
			buffer = new byte[numWords*numBytesPerWord];

			// Initialize them with the default word value
			int offset = 0;
			for(int i=0; i<numWords; i++)
			{
				Buffer.BlockCopy(defaultValueInBytes, 0, buffer, offset, numBytesPerWord);
				offset+=numBytesPerWord;
			}
		}

		#endregion
		
		#region IEquatable<ByteBuffer> Members

		public bool Equals(WordBuffer other)
		{
			if(this.numWords!=other.numWords || this.numBytesPerWord!=other.numBytesPerWord)
				return false;

			if(buffer==null)
				return (other.buffer==null);

			for(int i = 0; i < buffer.Length; i++)
			{
				if(buffer[i] != other.buffer[i])
					return false;
			}
			return true;
		}

		// override object.Equals
		public override bool Equals(object obj)
		{

			if(obj == null || GetType() != obj.GetType())
			{
				return false;
			}

			return this.Equals((WordBuffer)obj);
		}

		// override object.GetHashCode
		public override int GetHashCode()
		{
			return base.GetHashCode();
		}

		#endregion
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) DGT Experts
Spain Spain
I finished my Degree in Industrial Electronics in the year 2000. I worked for 6 years as a Hardware and Software development engineer in Barcelona. On January 2007 I moved to Dublin to work as Software Engineer and I specialised in .NET technologies. Currently I'm consulting for other companies and running my own start up project Trainer Inside (www.trainerinside.com)

Comments and Discussions