Skip to content

Instantly share code, notes, and snippets.

@txdv
Created August 6, 2011 21:54
Show Gist options
  • Save txdv/1129790 to your computer and use it in GitHub Desktop.
Save txdv/1129790 to your computer and use it in GitHub Desktop.
ByteBufferCollection
using System.Reflection;
using System.Runtime.CompilerServices;
// Information about this assembly is defined by the following attributes.
// Change them to the values specific to your project.
[assembly: AssemblyTitle("Test")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("")]
[assembly: AssemblyCopyright("bentkus")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
[assembly: AssemblyVersion("1.0.*")]
// The following attributes are used to specify the signing key for the assembly,
// if desired. See the Mono documentation for more information about signing.
//[assembly: AssemblyDelaySign(false)]
//[assembly: AssemblyKeyFile("")]
using System;
using System.Collections.Generic;
using System.Linq;
using Manos.IO;
namespace Manos.IO
{
public class ByteBufferCollection
{
private LinkedList<ByteBuffer> buffers = new LinkedList<ByteBuffer>();
public ByteBufferCollection()
{
}
public void AddCopy(byte[] bytes)
{
Add(bytes.Clone() as byte[]);
}
public void AddCopy(ByteBuffer buffer)
{
byte[] bytes = new byte[buffer.Length];
Buffer.BlockCopy(buffer.Bytes, buffer.Position, bytes, 0, bytes.Length);
Add(new ByteBuffer(bytes, 0, bytes.Length));
}
public void Add(byte[] bytes)
{
Add(new ByteBuffer(bytes));
}
public void Add(ByteBuffer buffer)
{
buffers.AddLast(buffer);
}
private IEnumerable<ByteBuffer> Enumerate()
{
for (var current = buffers.First; current != null; current = current.Next) {
yield return current.Value;
}
yield break;
}
private IEnumerable<byte> EnumerateBytes()
{
return EnumerateBytes(0);
}
private IEnumerable<byte> EnumerateBytes(int skip)
{
bool skiped = skip == 0;
foreach (var buffer in Enumerate()) {
int i = 0;
int pos = buffer.Position;
if (!skiped) {
if (skip < buffer.Length) {
i = skip;
skiped = true;
yield return buffer.Bytes[i + pos];
} else {
skip -= buffer.Length;
}
} else {
for (; i < buffer.Length; i++) {
yield return buffer.Bytes[i + pos];
}
}
}
yield break;
}
public void Skip(int restLength)
{
foreach (var buffer in Enumerate()) {
int r = restLength - buffer.Length;
if (r >= 0) {
buffer.Skip(buffer.Length);
buffers.Remove(buffer);
restLength = r;
} else {
// it is the last buffer we need to skip
// break afterwards
buffer.Skip(restLength);
return;
}
}
}
public bool HasLength(int length)
{
foreach (var buffer in buffers) {
if (length < buffer.Length) {
return true;
}
length -= buffer.Length;
}
return false;
}
public int Length {
get {
int length = 0;
foreach (var buffer in buffers) {
length += buffer.Length;
}
return length;
}
}
public byte this[int index] {
get {
int position = index;
foreach (var buffer in buffers) {
if (position < buffer.Length) {
return buffer.Bytes[buffer.Position + position];
} else {
position -= buffer.Length;
}
}
throw new Exception();
}
}
public void CopyTo(byte[] destination, int length)
{
int startPos = 0;
foreach (var buffer in buffers) {
int rest = length - buffer.Length;
if (rest <= 0) {
Buffer.BlockCopy(buffer.Bytes, buffer.Position, destination, startPos, length);
break;
} else {
Buffer.BlockCopy(buffer.Bytes, buffer.Position, destination, startPos, buffer.Length);
startPos += buffer.Length;
length = rest;
}
}
}
public int FirstByte(byte val)
{
int pos = 0;
foreach (var buffer in buffers) {
for (int i = 0; i < buffer.Length; i++) {
if (buffer.Bytes[i + buffer.Position] == val) {
return pos;
} else {
pos++;
}
}
}
return -1;
}
public int FirstBytes(byte[] bytes)
{
return FirstBytes(bytes, 0);
}
public int FirstBytes(byte[] bytes, int start)
{
if ((bytes == null) || (bytes.Length == 0)) {
throw new ArgumentException("bytes cannot be equal null or have the length of 0");
}
int endPosition = bytes.Length - 1;
if (endPosition == 0) {
return FirstByte(bytes[0]);
}
bool started = false;
int bytesPos = 0;
int startPos = -1;
int i = start;
foreach (byte b in EnumerateBytes(start)) {
if (started) {
if (bytesPos == endPosition) {
if (b == bytes[bytesPos]) {
return startPos;
} else {
return FirstBytes(bytes, startPos + 1);
}
} else {
if (b == bytes[bytesPos]) {
bytesPos++;
} else {
return FirstBytes(bytes, startPos + 1);
}
}
} else {
if (b == bytes[0]) {
startPos = i;
bytesPos++;
started = true;
}
}
i++;
}
return -1;
}
public byte CurrentByte {
get {
var buffer = buffers.First();
return buffer.CurrentByte;
}
}
public bool ReadLong(int size, out long result)
{
if (size > sizeof(long) || !HasLength(size)) {
result = 0;
return false;
}
result = this[size - 1];
for (int i = size - 2;i >= 0; i--) {
result <<= 8;
result |= this[i];
}
return true;
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>10.0.0</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{34F9CC9C-7FA8-4C7C-B21B-139A0C1B56FD}</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>ByteBufferCollection</RootNamespace>
<AssemblyName>ByteBufferCollection</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>x86</PlatformTarget>
<ConsolePause>false</ConsolePause>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<DebugType>none</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>x86</PlatformTarget>
<ConsolePause>false</ConsolePause>
</PropertyGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
</Project>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>10.0.0</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{F92A1224-1B63-4BF1-A6E2-7687D5D0A1DA}</ProjectGuid>
<OutputType>Library</OutputType>
<RootNamespace>ByteBufferCollection</RootNamespace>
<AssemblyName>ByteBufferCollection</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\bin\</OutputPath>
<DefineConstants>DEBUG</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>x86</PlatformTarget>
<ConsolePause>false</ConsolePause>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<DebugType>none</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\bin\</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>x86</PlatformTarget>
<ConsolePause>false</ConsolePause>
</PropertyGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
<Compile Include="ByteBufferCollection.cs" />
</ItemGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="Manos.IO, Version=0.1.3.0, Culture=neutral, PublicKeyToken=null">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\libs\Manos.IO.dll</HintPath>
</Reference>
</ItemGroup>
</Project>
using System;
using Manos.IO;
namespace Test
{
class MainClass
{
public static void Main(string[] args)
{
var crlf = new byte[] { (byte)'\r', (byte)'\n' };
ByteBufferCollection buffers = new ByteBufferCollection();
buffers.Add(new byte[] { 1, 2, (byte)'\r', 3, 4 });
buffers.Add(new byte[] { 5, 6, (byte)'\r', (byte)'\n' });
int length = buffers.FirstBytes(crlf, 3);
byte[] bytes = new byte[length];
buffers.CopyTo(bytes, length);
buffers.Skip(length + crlf.Length);
foreach (var b in bytes) {
Console.WriteLine(b);
}
Console.WriteLine("end");
Console.WriteLine();
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>10.0.0</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{B4BDDEBC-9E16-4EFE-AF6B-68655162DF8E}</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>Test</RootNamespace>
<AssemblyName>Test</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>x86</PlatformTarget>
<Externalconsole>true</Externalconsole>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<DebugType>none</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>x86</PlatformTarget>
<Externalconsole>true</Externalconsole>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
</ItemGroup>
<ItemGroup>
<Compile Include="Main.cs" />
<Compile Include="AssemblyInfo.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
<ProjectReference Include="..\ByteBufferCollection\ByteBufferCollection.csproj">
<Project>{F92A1224-1B63-4BF1-A6E2-7687D5D0A1DA}</Project>
<Name>ByteBufferCollection</Name>
</ProjectReference>
</ItemGroup>
</Project>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment