1 // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors 2 // Licensed under the MIT License: 3 // 4 // Permission is hereby granted, free of charge, to any person obtaining a copy 5 // of this software and associated documentation files (the "Software"), to deal 6 // in the Software without restriction, including without limitation the rights 7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 // copies of the Software, and to permit persons to whom the Software is 9 // furnished to do so, subject to the following conditions: 10 // 11 // The above copyright notice and this permission notice shall be included in 12 // all copies or substantial portions of the Software. 13 // 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 // THE SOFTWARE. 21 22 module capnproto.ListReader; 23 24 import java.nio.ByteBuffer; 25 26 import capnproto.Constants; 27 import capnproto.Data; 28 import capnproto.ElementSize; 29 import capnproto.SegmentReader; 30 import capnproto.StructReader; 31 import capnproto.Text; 32 import capnproto.WireHelpers; 33 34 struct ListReader 35 { 36 public: //Methods. 37 this(SegmentReader* segment, int ptr, int elementCount, int step, int structDataSize, short structPointerCount, int nestingLimit) 38 { 39 this.segment = segment; 40 this.ptr = ptr; 41 this.elementCount = elementCount; 42 this.step = step; 43 this.structDataSize = structDataSize; 44 this.structPointerCount = structPointerCount; 45 this.nestingLimit = nestingLimit; 46 } 47 48 size_t length() const 49 { 50 return this.elementCount; 51 } 52 53 bool _getBooleanElement(size_t index) 54 { 55 long bindex = cast(long)index * this.step; 56 byte b = this.segment.buffer.get!byte(this.ptr + cast(int)(bindex / Constants.BITS_PER_BYTE)); 57 return (b & (1 << (bindex % 8))) != 0; 58 } 59 60 byte _getByteElement(size_t index) 61 { 62 return this.segment.buffer.get!byte(this.ptr + cast(int)(cast(long)index * this.step / Constants.BITS_PER_BYTE)); 63 } 64 65 short _getShortElement(size_t index) 66 { 67 return this.segment.buffer.get!short(this.ptr + cast(int)(cast(long)index * this.step / Constants.BITS_PER_BYTE)); 68 } 69 70 int _getIntElement(size_t index) 71 { 72 return this.segment.buffer.get!int(this.ptr + cast(int)(cast(long)index * this.step / Constants.BITS_PER_BYTE)); 73 } 74 75 long _getLongElement(size_t index) 76 { 77 return this.segment.buffer.get!long(this.ptr + cast(int)(cast(long)index * this.step / Constants.BITS_PER_BYTE)); 78 } 79 80 float _getFloatElement(size_t index) 81 { 82 return this.segment.buffer.get!float(this.ptr + cast(int)(cast(long)index * this.step / Constants.BITS_PER_BYTE)); 83 } 84 85 double _getDoubleElement(size_t index) 86 { 87 return this.segment.buffer.get!double(this.ptr + cast(int)(cast(long)index * this.step / Constants.BITS_PER_BYTE)); 88 } 89 90 T.Reader _getStructElement(T)(size_t index) 91 { 92 //TODO: Check nesting limit. 93 long indexBit = cast(long)index * this.step; 94 int structData = this.ptr + cast(int)(indexBit / Constants.BITS_PER_BYTE); 95 int structPointers = structData + (this.structDataSize / Constants.BITS_PER_BYTE); 96 return T.Reader(this.segment, structData, structPointers / 8, this.structDataSize, this.structPointerCount, this.nestingLimit - 1); 97 } 98 99 T.Reader _getPointerElement(T)(size_t index) 100 { 101 import std..string : startsWith; 102 import std.traits; 103 alias name = fullyQualifiedName!T; 104 105 int pointer = (this.ptr + cast(int)(cast(long)index * this.step / Constants.BITS_PER_BYTE)) / Constants.BYTES_PER_WORD; 106 static if(is(T : Data)) 107 return WireHelpers.readDataPointer(segment, pointer, null, 0, 0); 108 else static if(is(T : Text)) 109 return WireHelpers.readTextPointer(segment, pointer, null, 0, 0); 110 else static if(name.startsWith("capnproto.DataList") || name.startsWith("capnproto.EnumList") || name.startsWith("capnproto.PrimitiveList") || name.startsWith("capnproto.ListList") || name.startsWith("capnproto.StructList") || name.startsWith("capnproto.TextList")) 111 return WireHelpers.readListPointer!(T.Reader)(this.segment, pointer, null, 0, T.elementSize, this.nestingLimit); 112 else 113 return WireHelpers.readStructPointer!(T.Reader)(this.segment, pointer, null, 0, ElementSize.INLINE_COMPOSITE, this.nestingLimit); 114 } 115 116 T.Reader _getPointerElement(T)(size_t index, ref ByteBuffer defaultBuffer, int defaultOffset, int defaultSize) 117 { 118 static if(is(T : Data)) 119 return WireHelpers.readDataPointer(this.segment, (this.ptr + cast(int)(cast(long)index * this.step / Constants.BITS_PER_BYTE)) / Constants.BYTES_PER_WORD, defaultBuffer, defaultOffset, defaultSize); 120 static if(is(T : Text)) 121 return WireHelpers.readTextPointer(this.segment, (this.ptr + cast(int)(cast(long)index * this.step / Constants.BITS_PER_BYTE)) / Constants.BYTES_PER_WORD, defaultBuffer, defaultOffset, defaultSize); 122 else 123 return WireHelpers.readDataPointer(this.segment, (this.ptr + cast(int)(cast(long)index * this.step / Constants.BITS_PER_BYTE)) / Constants.BYTES_PER_WORD, defaultBuffer, defaultOffset, defaultSize); 124 } 125 126 package: 127 SegmentReader* segment; 128 int ptr; //Byte offset to front of list. 129 int elementCount; 130 int step; //In bits. 131 int structDataSize; //In bits. 132 short structPointerCount; 133 int nestingLimit; 134 }