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 |