| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2015, the Dartino project authors. Please see the AUTHORS file | |
| 2 // for details. All rights reserved. Use of this source code is governed by a | |
| 3 // BSD-style license that can be found in the LICENSE.md file. | |
| 4 | |
| 5 #ifndef STRUCT_H_ | |
| 6 #define STRUCT_H_ | |
| 7 | |
| 8 #include "include/service_api.h" | |
| 9 | |
| 10 #include <inttypes.h> | |
| 11 #include <stdlib.h> | |
| 12 #include <string.h> | |
| 13 | |
| 14 class Builder; | |
| 15 class MessageBuilder; | |
| 16 class MessageReader; | |
| 17 | |
| 18 class Segment { | |
| 19 public: | |
| 20 Segment(MessageReader* reader); | |
| 21 Segment(MessageReader* reader, char* memory, int size); | |
| 22 Segment(char* memory, int size); | |
| 23 virtual ~Segment(); | |
| 24 | |
| 25 void* At(int offset) const { return memory_ + offset; } | |
| 26 MessageReader* reader() const { return reader_; } | |
| 27 | |
| 28 char* memory() const { return memory_; } | |
| 29 int size() const { return size_; } | |
| 30 | |
| 31 protected: | |
| 32 // Detach the memory from the segment because ownership | |
| 33 // has been transferred. Typically, because the message | |
| 34 // has been transmitted to Dart in a call and will be | |
| 35 // deleted on return. | |
| 36 void Detach() { memory_ = NULL; } | |
| 37 | |
| 38 private: | |
| 39 MessageReader* reader_; | |
| 40 char* memory_; | |
| 41 int size_; | |
| 42 bool is_root_; | |
| 43 }; | |
| 44 | |
| 45 class MessageReader { | |
| 46 public: | |
| 47 MessageReader(int segments, char* memory); | |
| 48 ~MessageReader(); | |
| 49 int segment_count() const { return segment_count_; } | |
| 50 Segment* GetSegment(int id) { return segments_[id]; } | |
| 51 | |
| 52 static Segment* GetRootSegment(char* memory); | |
| 53 | |
| 54 private: | |
| 55 int segment_count_; | |
| 56 Segment** segments_; | |
| 57 }; | |
| 58 | |
| 59 class BuilderSegment : public Segment { | |
| 60 public: | |
| 61 virtual ~BuilderSegment(); | |
| 62 | |
| 63 int Allocate(int bytes); | |
| 64 | |
| 65 void* At(int offset) const { return memory() + offset; } | |
| 66 | |
| 67 // Detach all builder segments in the current chain because | |
| 68 // something else is taking ownership of the memory for the | |
| 69 // segments. This happens when built messages are transferred | |
| 70 // to Dart in a call. The memory will be freed on method | |
| 71 // return in that case. | |
| 72 void Detach(); | |
| 73 | |
| 74 int id() const { return id_; } | |
| 75 int used() const { return used_; } | |
| 76 MessageBuilder* builder() const { return builder_; } | |
| 77 | |
| 78 BuilderSegment* next() const { return next_; } | |
| 79 bool HasNext() const { return next_ != NULL; } | |
| 80 bool HasSpaceForBytes(int bytes) const { return used_ + bytes <= size(); } | |
| 81 | |
| 82 private: | |
| 83 BuilderSegment(MessageBuilder* builder, int id, int capacity); | |
| 84 | |
| 85 MessageBuilder* const builder_; | |
| 86 const int id_; | |
| 87 BuilderSegment* next_; | |
| 88 int used_; | |
| 89 | |
| 90 void set_next(BuilderSegment* segment) { next_ = segment; } | |
| 91 | |
| 92 friend class MessageBuilder; | |
| 93 }; | |
| 94 | |
| 95 class MessageBuilder { | |
| 96 public: | |
| 97 explicit MessageBuilder(int space); | |
| 98 | |
| 99 BuilderSegment* first() { return &first_; } | |
| 100 int segments() const { return segments_; } | |
| 101 | |
| 102 template<typename T> | |
| 103 T initRoot() { return T(InternalInitRoot(T::kSize)); } | |
| 104 | |
| 105 int ComputeUsed() const; | |
| 106 | |
| 107 BuilderSegment* FindSegmentForBytes(int bytes); | |
| 108 | |
| 109 static void DeleteMessage(char* message); | |
| 110 | |
| 111 private: | |
| 112 BuilderSegment first_; | |
| 113 BuilderSegment* last_; | |
| 114 int segments_; | |
| 115 | |
| 116 Builder InternalInitRoot(int size); | |
| 117 }; | |
| 118 | |
| 119 class Reader; | |
| 120 | |
| 121 template<typename T> | |
| 122 class List { | |
| 123 public: | |
| 124 List(Segment* segment, int offset, int length) | |
| 125 : segment_(segment), offset_(offset), length_(length) { } | |
| 126 | |
| 127 int length() const { return length_; } | |
| 128 | |
| 129 T operator[](int index) { | |
| 130 // TODO(kasperl): Bounds check? | |
| 131 return T(segment_, offset_ + (index * T::kSize)); | |
| 132 } | |
| 133 | |
| 134 const T operator[](int index) const { | |
| 135 // TODO(kasperl): Bounds check? | |
| 136 return T(segment_, offset_ + (index * T::kSize)); | |
| 137 } | |
| 138 | |
| 139 private: | |
| 140 Segment* segment_; | |
| 141 int offset_; | |
| 142 int length_; | |
| 143 }; | |
| 144 | |
| 145 template<typename T> | |
| 146 class PrimitiveList { | |
| 147 public: | |
| 148 PrimitiveList(Segment* segment, int offset, int length) | |
| 149 : data_(reinterpret_cast<T*>(segment->At(offset))), | |
| 150 length_(length) { } | |
| 151 | |
| 152 T* data() { return data_; } | |
| 153 int length() const { return length_; } | |
| 154 | |
| 155 T& operator[](int index) { | |
| 156 // TODO(kasperl): Bounds check? | |
| 157 return data_[index]; | |
| 158 } | |
| 159 | |
| 160 private: | |
| 161 T* const data_; | |
| 162 const int length_; | |
| 163 }; | |
| 164 | |
| 165 #define PRIMITIVE_LIST(T) \ | |
| 166 template<> \ | |
| 167 class List<T> : public PrimitiveList<T> { \ | |
| 168 public: \ | |
| 169 List(Segment* segment, int offset, int length) \ | |
| 170 : PrimitiveList(segment, offset, length) { } \ | |
| 171 }; | |
| 172 | |
| 173 // TODO(kasperl): Support List<bool>. | |
| 174 | |
| 175 PRIMITIVE_LIST(uint8_t) | |
| 176 PRIMITIVE_LIST(uint16_t) | |
| 177 | |
| 178 PRIMITIVE_LIST(int8_t) | |
| 179 PRIMITIVE_LIST(int16_t) | |
| 180 PRIMITIVE_LIST(int32_t) | |
| 181 PRIMITIVE_LIST(int64_t) | |
| 182 | |
| 183 PRIMITIVE_LIST(float) | |
| 184 PRIMITIVE_LIST(double) | |
| 185 | |
| 186 #undef PRIMITIVE_LIST | |
| 187 | |
| 188 class Reader { | |
| 189 public: | |
| 190 Reader(const Reader& reader) | |
| 191 : segment_(reader.segment()), offset_(reader.offset()) { } | |
| 192 | |
| 193 Segment* segment() const { return segment_; } | |
| 194 int offset() const { return offset_; } | |
| 195 | |
| 196 int ComputeUsed() const; | |
| 197 | |
| 198 // TODO(ager): Delete should only be possible on root readers. | |
| 199 void Delete() { delete segment_; } | |
| 200 | |
| 201 protected: | |
| 202 Reader(Segment* segment, int offset) | |
| 203 : segment_(segment), offset_(offset) { } | |
| 204 | |
| 205 template<typename T> | |
| 206 const T* PointerTo(int n) const { | |
| 207 return reinterpret_cast<T*>(segment()->At(offset() + n)); | |
| 208 } | |
| 209 | |
| 210 template<typename T> | |
| 211 T ReadStruct(int offset) const { | |
| 212 Segment* segment = segment_; | |
| 213 offset += offset_; | |
| 214 while (true) { | |
| 215 char* memory = segment->memory(); | |
| 216 int lo = *reinterpret_cast<int*>(memory + offset + 0); | |
| 217 int hi = *reinterpret_cast<int*>(memory + offset + 4); | |
| 218 int tag = lo & 3; | |
| 219 if (tag == 0) { | |
| 220 // Cannot read uninitialized structs. | |
| 221 abort(); | |
| 222 } else if (tag == 1) { | |
| 223 return T(segment, lo >> 2); | |
| 224 } else { | |
| 225 segment = segment->reader()->GetSegment(hi); | |
| 226 offset = lo >> 2; | |
| 227 } | |
| 228 } | |
| 229 } | |
| 230 | |
| 231 template<typename T> | |
| 232 List<T> ReadList(int offset) const { | |
| 233 Segment* segment = segment_; | |
| 234 offset += offset_; | |
| 235 while (true) { | |
| 236 char* memory = segment->memory(); | |
| 237 int lo = *reinterpret_cast<int*>(memory + offset + 0); | |
| 238 int hi = *reinterpret_cast<int*>(memory + offset + 4); | |
| 239 int tag = lo & 3; | |
| 240 if (tag == 0) { | |
| 241 // Uninitialized, return empty list. | |
| 242 return List<T>(NULL, 0, 0); | |
| 243 } else if (tag == 1) { | |
| 244 return List<T>(segment, lo >> 2, hi); | |
| 245 } else { | |
| 246 segment = segment->reader()->GetSegment(hi); | |
| 247 offset = lo >> 2; | |
| 248 } | |
| 249 } | |
| 250 } | |
| 251 | |
| 252 char* ReadString(int offset) const; | |
| 253 | |
| 254 private: | |
| 255 Segment* const segment_; | |
| 256 const int offset_; | |
| 257 | |
| 258 friend class Builder; | |
| 259 }; | |
| 260 | |
| 261 class Builder { | |
| 262 public: | |
| 263 Builder(const Builder& builder) | |
| 264 : segment_(builder.segment()), offset_(builder.offset()) { } | |
| 265 | |
| 266 BuilderSegment* segment() const { return segment_; } | |
| 267 int offset() const { return offset_; } | |
| 268 | |
| 269 int64_t InvokeMethod(ServiceId service, MethodId method); | |
| 270 void InvokeMethodAsync(ServiceId service, | |
| 271 MethodId method, | |
| 272 ServiceApiCallback api_callback, | |
| 273 void* callback_function, | |
| 274 void* callback_data); | |
| 275 | |
| 276 protected: | |
| 277 Builder(Segment* segment, int offset) | |
| 278 : segment_(static_cast<BuilderSegment*>(segment)), offset_(offset) { } | |
| 279 | |
| 280 template<typename T> | |
| 281 T* PointerTo(int n) { | |
| 282 return reinterpret_cast<T*>(segment()->At(offset() + n)); | |
| 283 } | |
| 284 | |
| 285 Builder NewStruct(int offset, int size); | |
| 286 Reader NewList(int offset, int length, int size); | |
| 287 void NewString(int offset, const char* value); | |
| 288 | |
| 289 private: | |
| 290 BuilderSegment* const segment_; | |
| 291 const int offset_; | |
| 292 | |
| 293 friend class MessageBuilder; | |
| 294 }; | |
| 295 | |
| 296 #endif // STRUCT_H_ | |
| OLD | NEW |