1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 | #ifndef NAN_WEAK_H_
|
10 | #define NAN_WEAK_H_
|
11 |
|
12 | static const int kInternalFieldsInWeakCallback = 2;
|
13 | static const int kNoInternalFieldIndex = -1;
|
14 |
|
15 | #if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \
|
16 | (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3))
|
17 | # define NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ \
|
18 | v8::WeakCallbackInfo<WeakCallbackInfo<T> > const&
|
19 | # define NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ \
|
20 | NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_
|
21 | # define NAN_WEAK_PARAMETER_CALLBACK_SIG_ NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_
|
22 | # define NAN_WEAK_TWOFIELD_CALLBACK_SIG_ NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_
|
23 | #elif NODE_MODULE_VERSION > IOJS_1_1_MODULE_VERSION
|
24 | # define NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ \
|
25 | v8::PhantomCallbackData<WeakCallbackInfo<T> > const&
|
26 | # define NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ \
|
27 | NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_
|
28 | # define NAN_WEAK_PARAMETER_CALLBACK_SIG_ NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_
|
29 | # define NAN_WEAK_TWOFIELD_CALLBACK_SIG_ NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_
|
30 | #elif NODE_MODULE_VERSION > NODE_0_12_MODULE_VERSION
|
31 | # define NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ \
|
32 | v8::PhantomCallbackData<WeakCallbackInfo<T> > const&
|
33 | # define NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ \
|
34 | v8::InternalFieldsCallbackData<WeakCallbackInfo<T>, void> const&
|
35 | # define NAN_WEAK_PARAMETER_CALLBACK_SIG_ NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_
|
36 | # define NAN_WEAK_TWOFIELD_CALLBACK_SIG_ NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_
|
37 | #elif NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION
|
38 | # define NAN_WEAK_CALLBACK_DATA_TYPE_ \
|
39 | v8::WeakCallbackData<S, WeakCallbackInfo<T> > const&
|
40 | # define NAN_WEAK_CALLBACK_SIG_ NAN_WEAK_CALLBACK_DATA_TYPE_
|
41 | #else
|
42 | # define NAN_WEAK_CALLBACK_DATA_TYPE_ void *
|
43 | # define NAN_WEAK_CALLBACK_SIG_ \
|
44 | v8::Persistent<v8::Value>, NAN_WEAK_CALLBACK_DATA_TYPE_
|
45 | #endif
|
46 |
|
47 | template<typename T>
|
48 | class WeakCallbackInfo {
|
49 | public:
|
50 | typedef void (*Callback)(const WeakCallbackInfo<T>& data);
|
51 | WeakCallbackInfo(
|
52 | Persistent<v8::Value> *persistent
|
53 | , Callback callback
|
54 | , void *parameter
|
55 | , void *field1 = 0
|
56 | , void *field2 = 0) :
|
57 | callback_(callback), isolate_(0), parameter_(parameter) {
|
58 | std::memcpy(&persistent_, persistent, sizeof (v8::Persistent<v8::Value>));
|
59 | internal_fields_[0] = field1;
|
60 | internal_fields_[1] = field2;
|
61 | }
|
62 | inline v8::Isolate *GetIsolate() const { return isolate_; }
|
63 | inline T *GetParameter() const { return static_cast<T*>(parameter_); }
|
64 | inline void *GetInternalField(int index) const {
|
65 | assert((index == 0 || index == 1) && "internal field index out of bounds");
|
66 | if (index == 0) {
|
67 | return internal_fields_[0];
|
68 | } else {
|
69 | return internal_fields_[1];
|
70 | }
|
71 | }
|
72 |
|
73 | private:
|
74 | NAN_DISALLOW_ASSIGN_COPY_MOVE(WeakCallbackInfo)
|
75 | Callback callback_;
|
76 | v8::Isolate *isolate_;
|
77 | void *parameter_;
|
78 | void *internal_fields_[kInternalFieldsInWeakCallback];
|
79 | v8::Persistent<v8::Value> persistent_;
|
80 | template<typename S, typename M> friend class Persistent;
|
81 | template<typename S> friend class PersistentBase;
|
82 | #if NODE_MODULE_VERSION <= NODE_0_12_MODULE_VERSION
|
83 | # if NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION
|
84 | template<typename S>
|
85 | static void invoke(NAN_WEAK_CALLBACK_SIG_ data);
|
86 | template<typename S>
|
87 | static WeakCallbackInfo *unwrap(NAN_WEAK_CALLBACK_DATA_TYPE_ data);
|
88 | # else
|
89 | static void invoke(NAN_WEAK_CALLBACK_SIG_ data);
|
90 | static WeakCallbackInfo *unwrap(NAN_WEAK_CALLBACK_DATA_TYPE_ data);
|
91 | # endif
|
92 | #else
|
93 | # if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \
|
94 | (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3))
|
95 | template<bool isFirstPass>
|
96 | static void invokeparameter(NAN_WEAK_PARAMETER_CALLBACK_SIG_ data);
|
97 | template<bool isFirstPass>
|
98 | static void invoketwofield(NAN_WEAK_TWOFIELD_CALLBACK_SIG_ data);
|
99 | # else
|
100 | static void invokeparameter(NAN_WEAK_PARAMETER_CALLBACK_SIG_ data);
|
101 | static void invoketwofield(NAN_WEAK_TWOFIELD_CALLBACK_SIG_ data);
|
102 | # endif
|
103 | static WeakCallbackInfo *unwrapparameter(
|
104 | NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ data);
|
105 | static WeakCallbackInfo *unwraptwofield(
|
106 | NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ data);
|
107 | #endif
|
108 | };
|
109 |
|
110 |
|
111 | #if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \
|
112 | (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3))
|
113 |
|
114 | template<typename T>
|
115 | template<bool isFirstPass>
|
116 | void
|
117 | WeakCallbackInfo<T>::invokeparameter(NAN_WEAK_PARAMETER_CALLBACK_SIG_ data) {
|
118 | WeakCallbackInfo<T> *cbinfo = unwrapparameter(data);
|
119 | if (isFirstPass) {
|
120 | cbinfo->persistent_.Reset();
|
121 | data.SetSecondPassCallback(invokeparameter<false>);
|
122 | } else {
|
123 | cbinfo->callback_(*cbinfo);
|
124 | delete cbinfo;
|
125 | }
|
126 | }
|
127 |
|
128 | template<typename T>
|
129 | template<bool isFirstPass>
|
130 | void
|
131 | WeakCallbackInfo<T>::invoketwofield(NAN_WEAK_TWOFIELD_CALLBACK_SIG_ data) {
|
132 | WeakCallbackInfo<T> *cbinfo = unwraptwofield(data);
|
133 | if (isFirstPass) {
|
134 | cbinfo->persistent_.Reset();
|
135 | data.SetSecondPassCallback(invoketwofield<false>);
|
136 | } else {
|
137 | cbinfo->callback_(*cbinfo);
|
138 | delete cbinfo;
|
139 | }
|
140 | }
|
141 |
|
142 | template<typename T>
|
143 | WeakCallbackInfo<T> *WeakCallbackInfo<T>::unwrapparameter(
|
144 | NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ data) {
|
145 | WeakCallbackInfo<T> *cbinfo =
|
146 | static_cast<WeakCallbackInfo<T>*>(data.GetParameter());
|
147 | cbinfo->isolate_ = data.GetIsolate();
|
148 | return cbinfo;
|
149 | }
|
150 |
|
151 | template<typename T>
|
152 | WeakCallbackInfo<T> *WeakCallbackInfo<T>::unwraptwofield(
|
153 | NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ data) {
|
154 | WeakCallbackInfo<T> *cbinfo =
|
155 | static_cast<WeakCallbackInfo<T>*>(data.GetInternalField(0));
|
156 | cbinfo->isolate_ = data.GetIsolate();
|
157 | return cbinfo;
|
158 | }
|
159 |
|
160 | #undef NAN_WEAK_PARAMETER_CALLBACK_SIG_
|
161 | #undef NAN_WEAK_TWOFIELD_CALLBACK_SIG_
|
162 | #undef NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_
|
163 | #undef NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_
|
164 | # elif NODE_MODULE_VERSION > NODE_0_12_MODULE_VERSION
|
165 |
|
166 | template<typename T>
|
167 | void
|
168 | WeakCallbackInfo<T>::invokeparameter(NAN_WEAK_PARAMETER_CALLBACK_SIG_ data) {
|
169 | WeakCallbackInfo<T> *cbinfo = unwrapparameter(data);
|
170 | cbinfo->persistent_.Reset();
|
171 | cbinfo->callback_(*cbinfo);
|
172 | delete cbinfo;
|
173 | }
|
174 |
|
175 | template<typename T>
|
176 | void
|
177 | WeakCallbackInfo<T>::invoketwofield(NAN_WEAK_TWOFIELD_CALLBACK_SIG_ data) {
|
178 | WeakCallbackInfo<T> *cbinfo = unwraptwofield(data);
|
179 | cbinfo->persistent_.Reset();
|
180 | cbinfo->callback_(*cbinfo);
|
181 | delete cbinfo;
|
182 | }
|
183 |
|
184 | template<typename T>
|
185 | WeakCallbackInfo<T> *WeakCallbackInfo<T>::unwrapparameter(
|
186 | NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_ data) {
|
187 | WeakCallbackInfo<T> *cbinfo =
|
188 | static_cast<WeakCallbackInfo<T>*>(data.GetParameter());
|
189 | cbinfo->isolate_ = data.GetIsolate();
|
190 | return cbinfo;
|
191 | }
|
192 |
|
193 | template<typename T>
|
194 | WeakCallbackInfo<T> *WeakCallbackInfo<T>::unwraptwofield(
|
195 | NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_ data) {
|
196 | WeakCallbackInfo<T> *cbinfo =
|
197 | static_cast<WeakCallbackInfo<T>*>(data.GetInternalField1());
|
198 | cbinfo->isolate_ = data.GetIsolate();
|
199 | return cbinfo;
|
200 | }
|
201 |
|
202 | #undef NAN_WEAK_PARAMETER_CALLBACK_SIG_
|
203 | #undef NAN_WEAK_TWOFIELD_CALLBACK_SIG_
|
204 | #undef NAN_WEAK_PARAMETER_CALLBACK_DATA_TYPE_
|
205 | #undef NAN_WEAK_TWOFIELD_CALLBACK_DATA_TYPE_
|
206 | #elif NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION
|
207 |
|
208 | template<typename T>
|
209 | template<typename S>
|
210 | void WeakCallbackInfo<T>::invoke(NAN_WEAK_CALLBACK_SIG_ data) {
|
211 | WeakCallbackInfo<T> *cbinfo = unwrap(data);
|
212 | cbinfo->persistent_.Reset();
|
213 | cbinfo->callback_(*cbinfo);
|
214 | delete cbinfo;
|
215 | }
|
216 |
|
217 | template<typename T>
|
218 | template<typename S>
|
219 | WeakCallbackInfo<T> *WeakCallbackInfo<T>::unwrap(
|
220 | NAN_WEAK_CALLBACK_DATA_TYPE_ data) {
|
221 | void *parameter = data.GetParameter();
|
222 | WeakCallbackInfo<T> *cbinfo =
|
223 | static_cast<WeakCallbackInfo<T>*>(parameter);
|
224 | cbinfo->isolate_ = data.GetIsolate();
|
225 | return cbinfo;
|
226 | }
|
227 |
|
228 | #undef NAN_WEAK_CALLBACK_SIG_
|
229 | #undef NAN_WEAK_CALLBACK_DATA_TYPE_
|
230 | #else
|
231 |
|
232 | template<typename T>
|
233 | void WeakCallbackInfo<T>::invoke(NAN_WEAK_CALLBACK_SIG_ data) {
|
234 | WeakCallbackInfo<T> *cbinfo = unwrap(data);
|
235 | cbinfo->persistent_.Dispose();
|
236 | cbinfo->persistent_.Clear();
|
237 | cbinfo->callback_(*cbinfo);
|
238 | delete cbinfo;
|
239 | }
|
240 |
|
241 | template<typename T>
|
242 | WeakCallbackInfo<T> *WeakCallbackInfo<T>::unwrap(
|
243 | NAN_WEAK_CALLBACK_DATA_TYPE_ data) {
|
244 | WeakCallbackInfo<T> *cbinfo =
|
245 | static_cast<WeakCallbackInfo<T>*>(data);
|
246 | cbinfo->isolate_ = v8::Isolate::GetCurrent();
|
247 | return cbinfo;
|
248 | }
|
249 |
|
250 | #undef NAN_WEAK_CALLBACK_SIG_
|
251 | #undef NAN_WEAK_CALLBACK_DATA_TYPE_
|
252 | #endif
|
253 |
|
254 | #if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \
|
255 | (V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3))
|
256 | template<typename T, typename M>
|
257 | template<typename P>
|
258 | inline void Persistent<T, M>::SetWeak(
|
259 | P *parameter
|
260 | , typename WeakCallbackInfo<P>::Callback callback
|
261 | , WeakCallbackType type) {
|
262 | WeakCallbackInfo<P> *wcbd;
|
263 | if (type == WeakCallbackType::kParameter) {
|
264 | wcbd = new WeakCallbackInfo<P>(
|
265 | reinterpret_cast<Persistent<v8::Value>*>(this)
|
266 | , callback
|
267 | , parameter);
|
268 | v8::PersistentBase<T>::SetWeak(
|
269 | wcbd
|
270 | , WeakCallbackInfo<P>::template invokeparameter<true>
|
271 | , type);
|
272 | } else {
|
273 | v8::Local<v8::Value>* self_v(reinterpret_cast<v8::Local<v8::Value>*>(this));
|
274 | assert((*self_v)->IsObject());
|
275 | v8::Local<v8::Object> self((*self_v).As<v8::Object>());
|
276 | int count = self->InternalFieldCount();
|
277 | void *internal_fields[kInternalFieldsInWeakCallback] = {0, 0};
|
278 | for (int i = 0; i < count && i < kInternalFieldsInWeakCallback; i++) {
|
279 | internal_fields[i] = self->GetAlignedPointerFromInternalField(i);
|
280 | }
|
281 | wcbd = new WeakCallbackInfo<P>(
|
282 | reinterpret_cast<Persistent<v8::Value>*>(this)
|
283 | , callback
|
284 | , 0
|
285 | , internal_fields[0]
|
286 | , internal_fields[1]);
|
287 | self->SetAlignedPointerInInternalField(0, wcbd);
|
288 | v8::PersistentBase<T>::SetWeak(
|
289 | static_cast<WeakCallbackInfo<P>*>(0)
|
290 | , WeakCallbackInfo<P>::template invoketwofield<true>
|
291 | , type);
|
292 | }
|
293 | }
|
294 | #elif NODE_MODULE_VERSION > IOJS_1_1_MODULE_VERSION
|
295 | template<typename T, typename M>
|
296 | template<typename P>
|
297 | inline void Persistent<T, M>::SetWeak(
|
298 | P *parameter
|
299 | , typename WeakCallbackInfo<P>::Callback callback
|
300 | , WeakCallbackType type) {
|
301 | WeakCallbackInfo<P> *wcbd;
|
302 | if (type == WeakCallbackType::kParameter) {
|
303 | wcbd = new WeakCallbackInfo<P>(
|
304 | reinterpret_cast<Persistent<v8::Value>*>(this)
|
305 | , callback
|
306 | , parameter);
|
307 | v8::PersistentBase<T>::SetPhantom(
|
308 | wcbd
|
309 | , WeakCallbackInfo<P>::invokeparameter);
|
310 | } else {
|
311 | v8::Local<v8::Value>* self_v(reinterpret_cast<v8::Local<v8::Value>*>(this));
|
312 | assert((*self_v)->IsObject());
|
313 | v8::Local<v8::Object> self((*self_v).As<v8::Object>());
|
314 | int count = self->InternalFieldCount();
|
315 | void *internal_fields[kInternalFieldsInWeakCallback] = {0, 0};
|
316 | for (int i = 0; i < count && i < kInternalFieldsInWeakCallback; i++) {
|
317 | internal_fields[i] = self->GetAlignedPointerFromInternalField(i);
|
318 | }
|
319 | wcbd = new WeakCallbackInfo<P>(
|
320 | reinterpret_cast<Persistent<v8::Value>*>(this)
|
321 | , callback
|
322 | , 0
|
323 | , internal_fields[0]
|
324 | , internal_fields[1]);
|
325 | self->SetAlignedPointerInInternalField(0, wcbd);
|
326 | v8::PersistentBase<T>::SetPhantom(
|
327 | static_cast<WeakCallbackInfo<P>*>(0)
|
328 | , WeakCallbackInfo<P>::invoketwofield
|
329 | , 0
|
330 | , count > 1 ? 1 : kNoInternalFieldIndex);
|
331 | }
|
332 | }
|
333 | #elif NODE_MODULE_VERSION > NODE_0_12_MODULE_VERSION
|
334 | template<typename T, typename M>
|
335 | template<typename P>
|
336 | inline void Persistent<T, M>::SetWeak(
|
337 | P *parameter
|
338 | , typename WeakCallbackInfo<P>::Callback callback
|
339 | , WeakCallbackType type) {
|
340 | WeakCallbackInfo<P> *wcbd;
|
341 | if (type == WeakCallbackType::kParameter) {
|
342 | wcbd = new WeakCallbackInfo<P>(
|
343 | reinterpret_cast<Persistent<v8::Value>*>(this)
|
344 | , callback
|
345 | , parameter);
|
346 | v8::PersistentBase<T>::SetPhantom(
|
347 | wcbd
|
348 | , WeakCallbackInfo<P>::invokeparameter);
|
349 | } else {
|
350 | v8::Local<v8::Value>* self_v(reinterpret_cast<v8::Local<v8::Value>*>(this));
|
351 | assert((*self_v)->IsObject());
|
352 | v8::Local<v8::Object> self((*self_v).As<v8::Object>());
|
353 | int count = self->InternalFieldCount();
|
354 | void *internal_fields[kInternalFieldsInWeakCallback] = {0, 0};
|
355 | for (int i = 0; i < count && i < kInternalFieldsInWeakCallback; i++) {
|
356 | internal_fields[i] = self->GetAlignedPointerFromInternalField(i);
|
357 | }
|
358 | wcbd = new WeakCallbackInfo<P>(
|
359 | reinterpret_cast<Persistent<v8::Value>*>(this)
|
360 | , callback
|
361 | , 0
|
362 | , internal_fields[0]
|
363 | , internal_fields[1]);
|
364 | self->SetAlignedPointerInInternalField(0, wcbd);
|
365 | v8::PersistentBase<T>::SetPhantom(
|
366 | WeakCallbackInfo<P>::invoketwofield
|
367 | , 0
|
368 | , count > 1 ? 1 : kNoInternalFieldIndex);
|
369 | }
|
370 | }
|
371 | #elif NODE_MODULE_VERSION > NODE_0_10_MODULE_VERSION
|
372 | template<typename T, typename M>
|
373 | template<typename P>
|
374 | inline void Persistent<T, M>::SetWeak(
|
375 | P *parameter
|
376 | , typename WeakCallbackInfo<P>::Callback callback
|
377 | , WeakCallbackType type) {
|
378 | WeakCallbackInfo<P> *wcbd;
|
379 | if (type == WeakCallbackType::kParameter) {
|
380 | wcbd = new WeakCallbackInfo<P>(
|
381 | reinterpret_cast<Persistent<v8::Value>*>(this)
|
382 | , callback
|
383 | , parameter);
|
384 | v8::PersistentBase<T>::SetWeak(wcbd, WeakCallbackInfo<P>::invoke);
|
385 | } else {
|
386 | v8::Local<v8::Value>* self_v(reinterpret_cast<v8::Local<v8::Value>*>(this));
|
387 | assert((*self_v)->IsObject());
|
388 | v8::Local<v8::Object> self((*self_v).As<v8::Object>());
|
389 | int count = self->InternalFieldCount();
|
390 | void *internal_fields[kInternalFieldsInWeakCallback] = {0, 0};
|
391 | for (int i = 0; i < count && i < kInternalFieldsInWeakCallback; i++) {
|
392 | internal_fields[i] = self->GetAlignedPointerFromInternalField(i);
|
393 | }
|
394 | wcbd = new WeakCallbackInfo<P>(
|
395 | reinterpret_cast<Persistent<v8::Value>*>(this)
|
396 | , callback
|
397 | , 0
|
398 | , internal_fields[0]
|
399 | , internal_fields[1]);
|
400 | v8::PersistentBase<T>::SetWeak(wcbd, WeakCallbackInfo<P>::invoke);
|
401 | }
|
402 | }
|
403 | #else
|
404 | template<typename T>
|
405 | template<typename P>
|
406 | inline void PersistentBase<T>::SetWeak(
|
407 | P *parameter
|
408 | , typename WeakCallbackInfo<P>::Callback callback
|
409 | , WeakCallbackType type) {
|
410 | WeakCallbackInfo<P> *wcbd;
|
411 | if (type == WeakCallbackType::kParameter) {
|
412 | wcbd = new WeakCallbackInfo<P>(
|
413 | reinterpret_cast<Persistent<v8::Value>*>(this)
|
414 | , callback
|
415 | , parameter);
|
416 | persistent.MakeWeak(wcbd, WeakCallbackInfo<P>::invoke);
|
417 | } else {
|
418 | v8::Local<v8::Value>* self_v(reinterpret_cast<v8::Local<v8::Value>*>(this));
|
419 | assert((*self_v)->IsObject());
|
420 | v8::Local<v8::Object> self((*self_v).As<v8::Object>());
|
421 | int count = self->InternalFieldCount();
|
422 | void *internal_fields[kInternalFieldsInWeakCallback] = {0, 0};
|
423 | for (int i = 0; i < count && i < kInternalFieldsInWeakCallback; i++) {
|
424 | internal_fields[i] = self->GetPointerFromInternalField(i);
|
425 | }
|
426 | wcbd = new WeakCallbackInfo<P>(
|
427 | reinterpret_cast<Persistent<v8::Value>*>(this)
|
428 | , callback
|
429 | , 0
|
430 | , internal_fields[0]
|
431 | , internal_fields[1]);
|
432 | persistent.MakeWeak(wcbd, WeakCallbackInfo<P>::invoke);
|
433 | }
|
434 | }
|
435 | #endif
|
436 |
|
437 | #endif
|