1 /* 2 * Copyright 2016 Google Inc. All rights reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 module flatbuffers.bytebuffer; 18 19 import std.exception; 20 import std.bitmanip; 21 import std.exception; 22 import core.exception; 23 24 /** 25 Class warp a ubyte[] to provide byte handle. 26 */ 27 28 final class ByteBuffer 29 { 30 public: 31 this(){} 32 33 /// init ByteBuffer obj with buffer data 34 this(ubyte[] buffer) 35 { 36 restData(buffer,0); 37 } 38 39 /// Returns buffer length 40 @property size_t length() 41 { 42 return _buffer.length; 43 } 44 45 /// Returns buffer data 46 @property ubyte[] data() 47 { 48 return _buffer; 49 } 50 51 /// Returns buffer position 52 @property size_t position() 53 { 54 return _pos; 55 } 56 /// put boolen value into buffer 57 void put(T)(size_t offset, T value) if (is(T == bool)) 58 { 59 put!ubyte(offset, (value ? 0x01 : 0x00)); 60 } 61 62 /// put byte value into buffer 63 void put(T)(size_t offset, T value) if (isByte!T) 64 { 65 mixin(verifyOffset!1); 66 _buffer[offset] = value; 67 _pos = offset; 68 } 69 70 /// put numbirc value into buffer 71 void put(T)(size_t offset, T value) if (isNum!T) 72 { 73 mixin(verifyOffset!(T.sizeof)); 74 version (FLATBUFFER_BIGENDIAN) 75 { 76 auto array = nativeToBigEndian!T(value); 77 _buffer[offset .. (offset + T.sizeof)] = array[]; 78 } 79 else 80 { 81 auto array = nativeToLittleEndian!T(value); 82 _buffer[offset .. (offset + T.sizeof)] = array[]; 83 } 84 _pos = offset; 85 } 86 87 ///get Byte value in buffer from index 88 T get(T)(size_t index) if (isByte!T) 89 { 90 return cast(T) _buffer[index]; 91 } 92 93 T get(T)(size_t index) if(is(T == bool)) 94 { 95 ubyte value = get!ubyte(index); 96 return (value ==0x01 ? true : false); 97 } 98 99 T get(T)(size_t index) if (isNum!T) 100 { 101 ubyte[T.sizeof] buf = _buffer[index .. (index + T.sizeof)]; 102 version (FLATBUFFER_BIGENDIAN) 103 return bigEndianToNative!(T, T.sizeof)(buf); 104 else 105 return littleEndianToNative!(T, T.sizeof)(buf); 106 } 107 108 void restData(ubyte[] buffer,size_t pos){ 109 _buffer = buffer; 110 _pos = pos; 111 } 112 113 private: /// Variables. 114 ubyte[] _buffer; 115 size_t _pos; /// Must track start of the buffer. 116 } 117 118 unittest 119 { 120 ByteBuffer buf = new ByteBuffer(new ubyte[50]); 121 int a = 10; 122 buf.put(5, a); 123 short t = 4; 124 buf.put(9, t); 125 126 assert(buf.get!int(5) == 10); 127 assert(buf.get!short(9) == 4); 128 129 } 130 /*********************************** 131 * test for boolen value 132 */ 133 unittest 134 { 135 ByteBuffer buf = new ByteBuffer(new ubyte[50]); 136 bool a = true; 137 buf.put(5, a); 138 bool b = false; 139 buf.put(9, b); 140 assert(buf.get!bool(5) == true); 141 assert(buf.get!bool(9) == false); 142 143 } 144 private: 145 template verifyOffset(size_t length) 146 { 147 enum verifyOffset = "if(offset < 0 || offset >= _buffer.length || (offset + " ~ length.stringof ~ ") > _buffer.length) throw new RangeError();"; 148 } 149 150 template isNum(T) 151 { 152 static if (is(T == short) || is(T == ushort) || is(T == int) || is(T == uint) 153 || is(T == long) || is(T == ulong) || is(T == float) || is(T == double)) 154 enum isNum = true; 155 else 156 enum isNum = false; 157 } 158 159 template isByte(T) 160 { 161 static if (is(T == byte) || is(T == ubyte)) 162 enum isByte = true; 163 else 164 enum isByte = false; 165 }