1 module dpq.smartptr;
2 
3 import dpq.exception;
4 
5 version(unittest)
6 {
7 	int nFrees = 0;
8 	void fakeFree(T)(T* val)
9 	{
10 		++nFrees;
11 	}
12 }
13 
14 class SmartPointer(T, alias _free)
15 {
16 	private T _ptr;
17 
18 	alias get this;
19 
20 	this()
21 	{
22 		_ptr = null;
23 	}
24 
25 	this(T ptr)
26 	{
27 		_ptr = ptr;
28 	}
29 
30 	~this()
31 	{
32 		clear();
33 	}
34 
35 	@property T get()
36 	{
37 		if (_ptr == null)
38 			throw new DPQException("get called on a null SmartPointer!(" ~ T.stringof ~ ")");
39 		return _ptr;
40 	}
41 
42 	@property bool isNull()
43 	{
44 		return _ptr == null;
45 	}
46 
47 	void opAssign(typeof(null) n)
48 	{
49 		clear();
50 	}
51 
52 	void opAssign(T ptr)
53 	{
54 		if (ptr == _ptr)
55 			return;
56 
57 		clear();
58 		_ptr = ptr;
59 	}
60 
61 	void clear()
62 	{
63 		if (_ptr == null)
64 			return;
65 
66 		_free(_ptr);
67 
68 		_ptr = null;
69 	}
70 }
71 
72 unittest
73 {
74 	import std.stdio;
75 
76 	writeln(" * SmartPointer");
77 
78 	alias Ptr = SmartPointer!(ubyte*, fakeFree);
79 
80 	ubyte* p = new ubyte;
81 	*p = 2;
82 	auto sp = new Ptr;
83 
84 	assert(sp._ptr == null);
85 
86 	sp = p;
87 	assert(sp._ptr == p);
88 
89 	// assign the same ptr
90 	sp = p;
91 	assert(nFrees == 0);
92 	assert(!sp.isNull);
93 	assert(sp._ptr == p);
94 
95 	ubyte* p2 = new ubyte;
96 	*p2 = 255;
97 
98 	sp = p2;
99 	assert(nFrees == 1);
100 	assert(sp._ptr == p2);
101 
102 	sp = new Ptr(p2);
103 	assert(sp._ptr == p2);
104 
105 	sp.clear();
106 	assert(sp.isNull);
107 	assert(sp._ptr == null);
108 }
109