1 /* 2 Copyright (c) 2013 Andrey Penechko 3 4 Boost Software License - Version 1.0 - August 17th, 2003 5 6 Permission is hereby granted, free of charge, to any person or organization 7 obtaining a copy of the software and accompanying documentation covered by 8 this license the "Software" to use, reproduce, display, distribute, 9 execute, and transmit the Software, and to prepare derivative works of the 10 Software, and to permit third-parties to whom the Software is furnished to 11 do so, all subject to the following: 12 13 The copyright notices in the Software and this entire statement, including 14 the above license grant, this restriction and the following disclaimer, 15 must be included in all copies of the Software, in whole or in part, and 16 all derivative works of the Software, unless such copies or derivative 17 works are solely in the form of machine-executable object code generated by 18 a source language processor. 19 20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 23 SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 24 FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 25 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 26 DEALINGS IN THE SOFTWARE. 27 */ 28 29 module anchovy.utils.streamutils; 30 31 version=TestPrint; 32 33 private import std.bitmanip; 34 import std.stdio; 35 import std..string; 36 37 38 class StreamUtilsException:Exception{ 39 this(string msg){super(msg);} 40 } 41 /// 42 pure T Peek(T)(ref ubyte[] inData){ 43 Check!T(inData); 44 ubyte[T.sizeof] staticValue= inData[0..T.sizeof]; 45 return bigEndianToNative!T(staticValue); 46 } 47 48 ///Peeks the value from the begining of the stream and Crops it 49 T Read(T)(ref ubyte[] inData){ 50 Check!T(inData); 51 ubyte[T.sizeof] staticValue= inData[0..T.sizeof]; 52 Crop!(T,false)(inData); 53 54 return bigEndianToNative!T(staticValue); 55 } 56 57 ///Crops the value from the begining of the stream. If chek is true it will check if cropping is possible 58 void Crop(T, bool check = true)(ref ubyte[] inData){ 59 static if(check){ 60 Check!T(inData); 61 inData = inData[T.sizeof..$]; 62 }else 63 inData = inData[T.sizeof..$]; 64 } 65 66 void Check(T)(ref ubyte[] inData){ 67 if(inData.length<T.sizeof) 68 throw new StreamUtilsException(format("Not enough data to read: need %s, got %s",T.sizeof,inData.length)); 69 } 70 71 // 72 unittest{ 73 ubyte[] inData=[1,1,1]; 74 75 } 76 77 nothrow void Write(T)(ref ubyte[] outData, T var){ 78 outData~= nativeToBigEndian!T(var); 79 } 80 81 //Write and Read unittest 82 unittest{ 83 ubyte[] outStream; 84 Write!(bool)(outStream, true); 85 Write!(bool)(outStream, false); 86 Write!(byte)(outStream, -69); 87 Write!(ubyte)(outStream, 69); 88 Write!(short)(outStream, -20000); 89 Write!(ushort)(outStream, 65000); 90 Write!(int)(outStream, -1234567); 91 Write!(uint)(outStream, 12345678); 92 Write!(float)(outStream, 3.14159); 93 Write!(double)(outStream, 3.141592); 94 Write!(long)(outStream, 12345679); 95 Write!(ulong)(outStream, 123456790); 96 97 size_t dataLength = bool.sizeof*2 + byte.sizeof*2 + short.sizeof*2 + int.sizeof*2 + float.sizeof + double.sizeof + 98 long.sizeof*2; 99 100 assert(outStream.length==dataLength); 101 assert(Read!(bool)(outStream)==true); 102 assert(Read!(bool)(outStream)==false); 103 assert(Read!(byte)(outStream)==-69); 104 assert(Read!(ubyte)(outStream)==69); 105 assert(Read!(short)(outStream)==-20000); 106 assert(Read!(ushort)(outStream)==65000); 107 assert(Read!(int)(outStream)==-1234567); 108 assert(Read!(uint)(outStream)==12345678); 109 assert(Read!(float)(outStream)==3.14159f); 110 assert(Read!(double)(outStream)==3.141592f); 111 assert(Read!(long)(outStream)==12345679); 112 assert(Read!(ulong)(outStream)==123456790); 113 version(TestPrint){writeln("SUCCESS: Write(T)(T var, ref ubyte[] outData)");} 114 } 115 116 /** 117 * Reads array of elements of type T from byte array data and changes data to point to slice after this array. 118 * The elements in stream are stored in Big Endian. 119 * If length of stream in less then length of inquired data then empty array is returned. 120 * 121 * Returns: array of type T 122 */ 123 T[] ReadArray(T)(ref ubyte[] inData, uint length){ 124 T[] returnValue; 125 126 if(inData.length<T.sizeof*length) 127 throw new StreamUtilsException(format("Not enough data to read: need %s, got %s",(T.sizeof)*length,inData.length)); 128 129 for(size_t i=0;i<length;++i){ 130 131 ubyte[T.sizeof] staticValue= inData[0..T.sizeof]; 132 returnValue ~= bigEndianToNative!T(staticValue); 133 inData=inData[T.sizeof..$];//pop the data from begining. 134 } 135 136 return returnValue; 137 } 138 139 140 //ReadArray unittest 141 unittest{ 142 ubyte[] inData=[0,0,0,10,0,0,1,1,0,1,1,1]; 143 144 ubyte[] tempData=inData; 145 uint[] outData1=ReadArray!(uint)(tempData,3); 146 147 assert(outData1==[10,257,65793]); 148 assert(tempData.length==0); 149 150 ///////// 151 tempData=inData; 152 float[] outData2=ReadArray!(float)(tempData,2); 153 assert(tempData.length==4); 154 writeln(outData2); 155 assert(tempData.length==float.sizeof); 156 157 158 writeln("SUCCESS: ReadArray(T)(ref ubyte[] data, uint num)"); 159 }