table.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. # Copyright 2014 Google Inc. All rights reserved.
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. from . import encode
  15. from . import number_types as N
  16. class Table(object):
  17. """Table wraps a byte slice and provides read access to its data.
  18. The variable `Pos` indicates the root of the FlatBuffers object therein.
  19. """
  20. __slots__ = ("Bytes", "Pos")
  21. def __init__(self, buf, pos):
  22. N.enforce_number(pos, N.UOffsetTFlags)
  23. self.Bytes = buf
  24. self.Pos = pos
  25. def Offset(self, vtableOffset):
  26. """Offset provides access into the Table's vtable.
  27. Deprecated fields are ignored by checking the vtable's length.
  28. """
  29. vtable = self.Pos - self.Get(N.SOffsetTFlags, self.Pos)
  30. vtableEnd = self.Get(N.VOffsetTFlags, vtable)
  31. if vtableOffset < vtableEnd:
  32. return self.Get(N.VOffsetTFlags, vtable + vtableOffset)
  33. return 0
  34. def Indirect(self, off):
  35. """Indirect retrieves the relative offset stored at `offset`."""
  36. N.enforce_number(off, N.UOffsetTFlags)
  37. return off + encode.Get(N.UOffsetTFlags.packer_type, self.Bytes, off)
  38. def String(self, off):
  39. """String gets a string from data stored inside the flatbuffer."""
  40. N.enforce_number(off, N.UOffsetTFlags)
  41. off += encode.Get(N.UOffsetTFlags.packer_type, self.Bytes, off)
  42. start = off + N.UOffsetTFlags.bytewidth
  43. length = encode.Get(N.UOffsetTFlags.packer_type, self.Bytes, off)
  44. return bytes(self.Bytes[start : start + length])
  45. def VectorLen(self, off):
  46. """VectorLen retrieves the length of the vector whose offset is stored
  47. at "off" in this object.
  48. """
  49. N.enforce_number(off, N.UOffsetTFlags)
  50. off += self.Pos
  51. off += encode.Get(N.UOffsetTFlags.packer_type, self.Bytes, off)
  52. ret = encode.Get(N.UOffsetTFlags.packer_type, self.Bytes, off)
  53. return ret
  54. def Vector(self, off):
  55. """Vector retrieves the start of data of the vector whose offset is
  56. stored at "off" in this object.
  57. """
  58. N.enforce_number(off, N.UOffsetTFlags)
  59. off += self.Pos
  60. x = off + self.Get(N.UOffsetTFlags, off)
  61. # data starts after metadata containing the vector length
  62. x += N.UOffsetTFlags.bytewidth
  63. return x
  64. def Union(self, t2, off):
  65. """Union initializes any Table-derived type to point to the union at
  66. the given offset.
  67. """
  68. assert type(t2) is Table
  69. N.enforce_number(off, N.UOffsetTFlags)
  70. off += self.Pos
  71. t2.Pos = off + self.Get(N.UOffsetTFlags, off)
  72. t2.Bytes = self.Bytes
  73. def Get(self, flags, off):
  74. """Get retrieves a value of the type specified by `flags` at the
  75. given offset.
  76. """
  77. N.enforce_number(off, N.UOffsetTFlags)
  78. return flags.py_type(encode.Get(flags.packer_type, self.Bytes, off))
  79. def GetSlot(self, slot, d, validator_flags):
  80. N.enforce_number(slot, N.VOffsetTFlags)
  81. if validator_flags is not None:
  82. N.enforce_number(d, validator_flags)
  83. off = self.Offset(slot)
  84. if off == 0:
  85. return d
  86. return self.Get(validator_flags, self.Pos + off)
  87. def GetVectorAsNumpy(self, flags, off):
  88. """GetVectorAsNumpy returns the vector that starts at `Vector(off)`
  89. as a numpy array with the type specified by `flags`. The array is
  90. a `view` into Bytes, so modifying the returned array will
  91. modify Bytes in place.
  92. """
  93. offset = self.Vector(off)
  94. length = self.VectorLen(off) # TODO: length accounts for bytewidth, right?
  95. numpy_dtype = N.to_numpy_type(flags)
  96. return encode.GetVectorAsNumpy(numpy_dtype, self.Bytes, length, offset)
  97. def GetArrayAsNumpy(self, flags, off, length):
  98. """GetArrayAsNumpy returns the array with fixed width that starts at `Vector(offset)`
  99. with length `length` as a numpy array with the type specified by `flags`.
  100. The
  101. array is a `view` into Bytes so modifying the returned will modify Bytes in
  102. place.
  103. """
  104. numpy_dtype = N.to_numpy_type(flags)
  105. return encode.GetVectorAsNumpy(numpy_dtype, self.Bytes, length, off)
  106. def GetVOffsetTSlot(self, slot, d):
  107. """GetVOffsetTSlot retrieves the VOffsetT that the given vtable location
  108. points to. If the vtable value is zero, the default value `d`
  109. will be returned.
  110. """
  111. N.enforce_number(slot, N.VOffsetTFlags)
  112. N.enforce_number(d, N.VOffsetTFlags)
  113. off = self.Offset(slot)
  114. if off == 0:
  115. return d
  116. return off