1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
|
/*!
* @file pointer.h
* @brief Contains a pointer class which has a counter-mechanism to prevent
* memory leak.
*
* @author cathook
*/
#ifndef __MEOW_BASES_POINTER_H__
#define __MEOW_BASES_POINTER_H__
#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <meow/bases/object.h>
#include <meow/debug/assert.h>
#include <meow/alloc.h>
namespace meow {
/*!
* @brief A normal pointer which is a child of the base class Object.
*/
template<typename Type>
class WeakPointer : public Object {
private:
Type* address_;
public:
/*!
* @brief Points to NULL.
*/
WeakPointer() : WeakPointer(NULL) {}
/*!
* @brief Points to the address pointed by the specified pointer.
*/
WeakPointer(WeakPointer const & ptr2) : WeakPointer(address()) {}
/*!
* @brief Points to the specified address.
*/
WeakPointer(Type* addr) : address_(addr) {}
/*!
* @brief Destructor.
* @note It will not delete/free the memory!
*/
~WeakPointer() {}
/*!
* @brief Returns the address it points to.
*/
Type* address() const { return address_; }
/*!
* @brief Returns the address it points to.
*/
operator Type*() const { return address(); }
/*!
* @brief Returns the address it points to.
*/
Type* operator->() const { return address(); }
/*!
* @brief Returns the reference of the address it points to.
*/
Type& operator*() const { return *address(); }
/*!
* @brief Returns an positive offseted pointer of myself.
* @param [in] diff number of offset.
*/
WeakPointer operator+(ptrdiff_t const & diff) const {
return WeakPointer(address() + diff);
}
/*!
* @brief Returns an negative offseted pointer of myself.
* @param [in] diff number of offset.
*/
WeakPointer operator-(ptrdiff_t const & diff) const {
return operator+(-diff);
}
/*!
* @brief Offsets myself positively and returns *this.
* @param [in] diff number of offset.
*/
WeakPointer& operator+=(ptrdiff_t const & diff) {
address_ += diff;
return *this;
}
/*!
* @brief Offsets myself negitavely and returns *this.
* @param [in] diff number of offset.
*/
WeakPointer& operator-=(ptrdiff_t const & diff) {
return operator+=(-diff);
}
/*!
* @brief Returns the distance between another WeakPointer.
* @param [in] t Another WeakPointer.
*/
ptrdiff_t operator-(WeakPointer const & t) const {
return address() - t.address();
}
/*!
* @brief Assign operator.
*/
WeakPointer& operator=(WeakPointer const & t) { return CopyFrom(t); }
/*!
* @brief Assign method.
*/
WeakPointer& CopyFrom(WeakPointer const & t) {
address_ = t.address_;
return *this;
}
/*!
* @brief Is-equal operator.
*/
bool operator==(WeakPointer const & t) const { return Equals(t); }
/*!
* @brief Is-equal method.
* @brief true if the addresses pointed to are same.
*/
bool Equals(WeakPointer const & t) const { return address() == t.address(); }
/*!
* @brief Less-than operator.
*/
bool operator<(WeakPointer const & t) const { return LessThan(t); }
/*!
* @brief Less-than method.
* @brief true if my address is less than the other address.
*/
bool LessThan(WeakPointer const & t) const {
return address() < t.address();
}
//! Settings for Object.
SET_MEOW_OBJECT_COPYABLE(true);
IMPL_MEOW_OBJECT_COPY_BY_COPYCONSTRUCTOR(WeakPointer);
DELEGATE_MEOW_OBJECT_COPYFROM(WeakPointer);
DELEGATE_MEOW_OBJECT_EQUALS(WeakPointer);
};
namespace {
/*!
* @brief For the data shared by difference type of Pointer.
*/
class PointerTypesShareCounter {
protected:
size_t* counter_;
public:
friend size_t* GetPointerCounter(PointerTypesShareCounter const* ptr);
};
size_t* GetPointerCounter(PointerTypesShareCounter const* ptr) {
return ptr->counter_;
}
}
/*!
* @brief For pointing to an array.
*/
template<typename Type>
class ArrayPointer : public Object, public PointerTypesShareCounter {
private:
//! Address of the array.
Type* address_;
//! The first valid index.
ssize_t begin_index_;
//! The next one of the last valid index.
ssize_t end_index_;
template<typename Type2>
void Attach_(ArrayPointer<Type2> const & ptr2) {
address_ = reinterpret_cast<Type*>(ptr2.address());
counter_ = GetPointerCounter(
dynamic_cast<PointerTypesShareCounter const*>(&ptr2));
(*counter_) += 1;
begin_index_ = ptr2.begin_index();
end_index_ = ptr2.end_index();
}
void Detach_() {
(*counter_) -= 1;
if (*counter_ == 0) {
address_ += reinterpret_cast<ptrdiff_t>(begin_index_);
if (address_ != NULL)
DeleteArray(address_);
DeleteEntry(counter_);
}
}
ArrayPointer(Type* addr, size_t len) :
address_(addr),
begin_index_(0),
end_index_(len) {
counter_ = NewEntry<size_t>(1);
}
template<typename Type2>
ArrayPointer(ArrayPointer<Type2> const & ptr2, ssize_t offset) {
Attach_(ptr2);
Offset(offset);
}
public:
/*!
* @brief Points to NULL.
*/
ArrayPointer() : ArrayPointer(reinterpret_cast<Type*>(NULL), 0) {}
/*!
* @brief Points to another array with same type.
* @param [in] ptr2 Pointer of another array.
*/
ArrayPointer(ArrayPointer const & ptr2) :
ArrayPointer(ptr2, 0) {}
/*!
* @brief Points to another array.
* @param [in] ptr2 Pointer of another array.
*/
template<typename Type2>
ArrayPointer(ArrayPointer<Type2> const & ptr2) :
ArrayPointer(ptr2, 0) {}
/*!
* @brief Creates an array and then points to it.
* @param [in] len Size of the array.
* @param [in] args Arguments of the constructor of the Type.
*/
template<typename... Args>
ArrayPointer(size_t len, Args... args) :
ArrayPointer(NewArray<Type>(len, args...), len) {}
/*!
* @brief Desturctor.
*
* It will automatically delete the array if nobody points to that array after
* itself be destroyed.
*/
~ArrayPointer() { Detach_(); }
/*!
* @brief Gets the address of the array.
*/
Type* address() const { return address_; }
/*!
* @brief Returns the number of pointer points to it.
*/
size_t counter() const { return *counter_; }
#ifdef MEOW_POINTER_TEST
/*!
* @brief For testing.
*/
size_t* ptr_counter() const { return counter_; }
#endif // MEOW_POINTER_TEST
/*!
* @brief Returns the smallest valid index.
*/
ssize_t begin_index() const { return begin_index_; }
/*!
* @brief Returns the one after the largest valid index.
*/
ssize_t end_index() const { return end_index_; }
/*!
* @brief Offsets a specified number.
* @param [in] offs Offset mount.
*/
ArrayPointer& Offset(ssize_t offs) {
address_ += reinterpret_cast<ptrdiff_t>(offs);
begin_index_ -= offs;
end_index_ -= offs;
return *this;
}
/*!
* @brief Returns the array.
*/
operator Type*() const { return address(); }
/*!
* @brief Transformates to WeakPointer.
*/
operator WeakPointer<Type>() const { return WeakPointer<Type>(address()); }
/*!
* @brief Transformates to another type.
*/
template<typename Type2>
operator ArrayPointer<Type2>() const { return ArrayPointer<Type2>(*this); }
/*!
* @brief Gets the address of the first element of the array.
*/
Type* operator->() const { return address(); }
/*!
* @brief Gets the reference of the first element of the array.
*/
Type& operator*() const { return *address(); }
/*!
* @brief Gets the reference of the i-th element of the array.
* @param [in] index Index of the element.
*/
Type& operator[](ssize_t index) const {
Assert(begin_index_ <= index && index < end_index_,
"Index %ld is not in the valid range [%ld, %ld)",
index, begin_index_, end_index_);
return *(address() + reinterpret_cast<ptrdiff_t>(index));
}
/*!
* @brief Returns an array after offset positively from itself.
* @param [in] diff Offset.
*/
ArrayPointer operator+(ptrdiff_t const & diff) const {
return ArrayPointer(*this, reinterpret_cast<ssize_t>(diff));
}
/*!
* @brief Returns an array after offset negatively from itself.
* @param [in] diff Offset.
*/
ArrayPointer operator-(ptrdiff_t const & diff) const {
return operator+(-diff);
}
/*!
* @brief Offsets itself positively.
* @param [in] diff Offset.
*/
ArrayPointer& operator+=(ptrdiff_t const & diff) {
return Offset(reinterpret_cast<ssize_t>(diff));
}
/*!
* @brief Offsets itself negatively.
* @param [in] diff Offset.
*/
ArrayPointer& operator-=(ptrdiff_t const & diff) {
return operator+=(-diff);
}
/*!
* @brief Gets the offset between itself and a WeakPointer.
* @param [in] t The instance of WeakPointer.
*/
ptrdiff_t operator-(WeakPointer<Type> const & t) const {
return address() - t.address();
}
/*!
* @brief Points to another array.
* @param [in] t Another array.
*/
ArrayPointer& operator=(ArrayPointer const & t) {
return CopyFrom(t);
}
/*!
* @brief Points to another array.
* @param [in] t Another array.
*/
ArrayPointer& CopyFrom(ArrayPointer const & t) {
Detach_();
Attach_(t);
return *this;
}
/*!
* @brief Return whether them are points to the same address or not.
* @param [in] t Another array.
*/
bool operator==(ArrayPointer const & t) const {
return Equals(t);
}
/*!
* @brief Return whether them are points to the same address or not.
* @param [in] t Another array.
*/
bool Equals(ArrayPointer const & t) const {
return address() == t.address();
}
/*!
* @brief Less-than operator.
*/
bool operator<(ArrayPointer const & t) const { return LessThan(t); }
/*!
* @brief Less-than method.
* @brief true if my address is less than the other address.
*/
bool LessThan(ArrayPointer const & t) const {
return address() < t.address();
}
//! Settings for Object.
SET_MEOW_OBJECT_COPYABLE(true);
IMPL_MEOW_OBJECT_COPY_BY_COPYCONSTRUCTOR(ArrayPointer);
DELEGATE_MEOW_OBJECT_COPYFROM(ArrayPointer);
DELEGATE_MEOW_OBJECT_EQUALS(ArrayPointer);
};
namespace {
/*!
* @brief Base class for information in types of EntryPointer.
*
* Because the EntryPointer may be an element of an array or not, we need to
* handle each case seperately.
*/
template<typename Type>
class EntryPointerBase : public Object {
public:
/*!
* @brief Destructor.
*/
virtual ~EntryPointerBase() {}
/*!
* @brief Gets the address.
*/
virtual Type* address() const = 0;
/*!
* @brief Gets the number of pointer points to the address.
*/
virtual size_t counter() const = 0;
#ifdef MEOW_POINTER_TEST
/*!
* @brief For testing.
*/
virtual size_t* ptr_counter() const = 0;
#endif // MEOW_POINTER_TEST
/*!
* @brief Returns whether it is an element in an array or not.
*/
virtual bool is_array_pointer() const = 0;
/*!
* @brief Copies from another EntryPointerBase.
*/
virtual void CopyFrom(EntryPointerBase const *) = 0;
/*!
* @brief Creates and returns a copy of itself.
*/
virtual EntryPointerBase* Copy() const = 0;
};
/*!
* @brief For the case that the address pointed to is an element of an array.
*/
template<typename Type>
class ArrayEntryPointer : public EntryPointerBase<Type> {
private:
//! Stores the pointer points to the array.
ArrayPointer<Type> ap_;
public:
ArrayEntryPointer(ArrayPointer<Type> const & ap) : ap_(ap) {}
template<typename Type2>
ArrayEntryPointer(ArrayPointer<Type2> const & ap) : ap_(ap) {}
ArrayPointer<Type> array_pointer() const { return ap_; }
Type* address() const { return ap_.address(); }
size_t counter() const { return ap_.counter(); }
#ifdef MEOW_POINTER_TEST
size_t* ptr_counter() const { return ap_.ptr_counter(); }
#endif // MEOW_POINTER_TEST
bool is_array_pointer() const { return true; }
void CopyFrom(EntryPointerBase<Type> const * epb2) {
ap_.CopyFrom(dynamic_cast<ArrayEntryPointer const *>(epb2)->ap_);
}
EntryPointerBase<Type>* Copy() const {
return dynamic_cast<EntryPointerBase<Type>*>(
NewEntry<ArrayEntryPointer>(ap_));
}
};
/*!
* @brief For the case that the address is not an element of an array.
*/
template<typename Type>
class NormalEntryPointer :
public EntryPointerBase<Type>, public PointerTypesShareCounter {
private:
//! Points to the address.
Type* address_;
template<typename Type2>
void Attach_(NormalEntryPointer<Type2> const & t) {
address_ = reinterpret_cast<Type*>(t.address());
counter_ = GetPointerCounter(
dynamic_cast<PointerTypesShareCounter const*>(&t));
(*counter_) += 1;
}
void Detach_() {
(*counter_) -= 1;
if (*counter_ <= 0) {
DeleteEntry(address_);
DeleteEntry(counter_);
}
}
NormalEntryPointer(Type* addr) : address_(addr) {
counter_ = NewEntry<size_t>(1);
}
public:
struct CREATE_OBJ {};
/*!
* @brief Points to NULL
*/
NormalEntryPointer() : NormalEntryPointer(NULL) {}
/*!
* @brief Points to the address pointed by the specified pointer.
* @param [in] t The pointer.
*/
NormalEntryPointer(NormalEntryPointer const & t) {
Attach_(t);
}
/*!
* @brief Points to the address pointed by the specified pointer with
* differnet type.
* @param [in] t The pointer.
*/
template<typename Type2>
NormalEntryPointer(NormalEntryPointer<Type2> const & t) {
Attach_(t);
}
/*!
* @brief Creates an instance of Type and points to it.
* @param [in] args Arguments for the constructor of the Type.
*/
template<typename... Args>
NormalEntryPointer(CREATE_OBJ, Args... args) :
NormalEntryPointer(NewEntry<Type>(args...)) {}
/*!
* @brief Desturctor.
*
* It will automatically delete the array if nobody points to that array after
* itself be destroyed.
*/
~NormalEntryPointer() { Detach_(); }
Type* address() const { return address_; }
size_t counter() const { return *counter_; }
#ifdef MEOW_POINTER_TEST
/*!
* @brief For testing.
*/
size_t* ptr_counter() const { return counter_; }
#endif // MEOW_POINTER_TEST
bool is_array_pointer() const { return false; }
void CopyFrom(EntryPointerBase<Type> const *epb) {
Detach_();
Attach_(*dynamic_cast<NormalEntryPointer const*>(epb));
}
EntryPointerBase<Type>* Copy() const {
return NewEntry<NormalEntryPointer>(*this);
}
};
/*!
* @brief For the data shared by difference type of EntryPointer.
*/
class EntryPointerTypesShareImpl {
protected:
Object* impl_;
public:
friend Object* GetEntryPointerImpl(EntryPointerTypesShareImpl const* ptr);
};
Object* GetEntryPointerImpl(EntryPointerTypesShareImpl const* ptr) {
return ptr->impl_;
}
}
/*!
* @brief Pointer points to an entry.
*/
template<typename Type>
class EntryPointer : public Object, public EntryPointerTypesShareImpl {
private:
EntryPointerBase<Type>* get_impl_() {
return dynamic_cast<EntryPointerBase<Type>*>(impl_);
}
EntryPointerBase<Type> const * get_impl_() const {
return dynamic_cast<EntryPointerBase<Type> const *>(impl_);
}
EntryPointerBase<Type>* set_impl_(EntryPointerBase<Type>* impl2) {
impl_ = dynamic_cast<Object*>(impl2);
return get_impl_();
}
public:
/*!
* @brief Points to NULL.
*/
EntryPointer() {
set_impl_(
dynamic_cast<EntryPointerBase<Type>*>(
NewEntry<NormalEntryPointer<Type>>()));
}
/*!
* @brief Creates the entry and points to it.
* @param [in] n Number of entry to be created, this must be 1.
* @param [in] args Arguments for the constructor.
*/
template<typename... Args>
EntryPointer(size_t n, Args... args) {
set_impl_(
dynamic_cast<EntryPointerBase<Type>*>(
NewEntry<NormalEntryPointer<Type>>(
typename NormalEntryPointer<Type>::CREATE_OBJ(), args...)));
}
/*!
* @brief Flags for constructor to know that it should creates new instance.
*/
#define EPCreateFlag 1
/*!
* @brief Copy constructor with the same type.
*/
EntryPointer(EntryPointer const & ptr2) {
set_impl_(ptr2.get_impl_()->Copy());
}
/*!
* @brief Copy from another type of pointer.
*/
template<typename Type2>
EntryPointer(EntryPointer<Type2> const & ptr2) {
Object* impl_of_ptr2 = GetEntryPointerImpl(
dynamic_cast<EntryPointerTypesShareImpl const*>(&ptr2));
if (ptr2.is_entry_of_array()) {
set_impl_(
dynamic_cast<EntryPointerBase<Type>*>(
NewEntry<ArrayEntryPointer<Type>>(
dynamic_cast<ArrayEntryPointer<Type2> const *>(
impl_of_ptr2)->array_pointer())));
} else {
set_impl_(
dynamic_cast<EntryPointerBase<Type>*>(
NewEntry<NormalEntryPointer<Type>>(
*dynamic_cast<NormalEntryPointer<Type2> const *>(
impl_of_ptr2))));
}
}
/*!
* @brief Points to an element of an array.
*/
template<typename Type2>
EntryPointer(ArrayPointer<Type2> const & ptr2) {
set_impl_(
dynamic_cast<EntryPointerBase<Type>*>(
NewEntry<ArrayEntryPointer<Type>>(ptr2)));
}
/*!
* @brief Desturctor.
*
* It will automatically delete the array if nobody points to that array after
* itself be destroyed.
*/
~EntryPointer() { DeleteEntry(get_impl_()); }
/*!
* @brief Gets the address of the pointer points to.
*/
Type* address() const { return get_impl_()->address(); }
/*!
* @brief Gets the number of pointers who point to the same address.
*/
size_t counter() const { return get_impl_()->counter(); }
#ifdef MEOW_POINTER_TEST
/*!
* @brief For testing.
*/
size_t* ptr_counter() const { return get_impl_()->ptr_counter(); }
#endif // MEOW_POINTER_TEST
/*!
* @brief Gets whether the address is an element of an array or not.
*/
bool is_entry_of_array() const { return get_impl_()->is_array_pointer(); }
/*!
* @brief Transformate to Type*.
*/
operator Type*() const { return address(); }
/*!
* @brief Transformate to WeakPointer.
*/
operator WeakPointer<Type>() const { return WeakPointer<Type>(address()); }
/*!
* @brief Transformate to different type of EntryPointer.
*/
template<typename Type2>
operator EntryPointer<Type2>() const { return EntryPointer<Type2>(*this); }
/*!
* @brief Returns the address it points to.
*/
Type* operator->() const { return address(); }
/*!
* @brief Returns the reference of the address it points to.
*/
Type& operator*() const { return *address(); }
/*!
* @brief Returns an negative offseted pointer of myself.
* @param [in] diff Number of offset.
*/
ptrdiff_t operator-(WeakPointer<Type> const & t) const {
return address() - t.address();
}
/*!
* @brief Assign operator.
* @param [in] t Another pointer.
*/
EntryPointer& operator=(EntryPointer const & t) { return CopyFrom(t); }
/*!
* @brief Assign method.
* @param [in] t Another pointer.
*/
EntryPointer& CopyFrom(EntryPointer const & t) {
DeleteEntry(get_impl_());
set_impl_(t.get_impl_()->Copy());
return *this;
}
/*!
* @brief Is-equal operation.
* @param [in] t Another pointer.
*/
bool operator==(EntryPointer const & t) const { return Equals(t); }
/*!
* @brief Is-equal method.
* @param [in] t Another pointer.
*/
bool Equals(EntryPointer const & t) const {
return address() == t.address();
}
/*!
* @brief Less-than operator.
*/
bool operator<(EntryPointer const & t) const { return LessThan(t); }
/*!
* @brief Less-than method.
* @brief true if my address is less than the other address.
*/
bool LessThan(EntryPointer const & t) const {
return address() < t.address();
}
//! Settings for Object.
SET_MEOW_OBJECT_COPYABLE(true);
IMPL_MEOW_OBJECT_COPY_BY_COPYCONSTRUCTOR(EntryPointer);
DELEGATE_MEOW_OBJECT_COPYFROM(EntryPointer);
DELEGATE_MEOW_OBJECT_EQUALS(EntryPointer);
};
} // meow
#endif // __MEOW_BASES_POINTER_H__
|