1 /**
2  * Betterc: Frequently used primitives suitable for use in the BetterC D subset.
3  *
4  * Copyright: Maxim Freck, 2018.
5  * Authors:   Maxim Freck <maxim@freck.pp.ru>
6  * License:   $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
7  */
8 module betterc.ds.stringz;
9 
10 /*******
11  * Reference-counted null-terminated string
12  */
13 struct Stringz
14 {
15 	private struct Payload {
16 		char* dst;
17 		size_t length;
18 
19 		size_t count;
20 		@disable this(this); // not copyable
21 	}
22 
23 	private Payload *payload;
24 
25 	/*******
26 	* Constructor
27 	*
28 	* Params:
29 	*  src = the D-style string
30 	*/
31 	public this(string src) nothrow @nogc
32 	{
33 		import core.stdc.stdlib: malloc;
34 		import core.stdc.string: memcpy;
35 
36 		payload = (cast(Payload*)malloc(Payload.sizeof));
37 
38 		payload.count = 1;
39 		payload.length = src.length;
40 		payload.dst = cast(char*)malloc(src.length+1);
41 		memcpy(payload.dst, src.ptr, src.length);
42 		payload.dst[src.length] = 0;
43 
44 	}
45 
46 	///ditto
47 	this (this) nothrow @nogc
48 	{
49 		if (payload !is null)
50 			payload.count++;
51 	}
52 
53 	///Ref. counting during structure assignment
54 	ref typeof(this) opAssign()(auto ref typeof(this) rhs) nothrow @nogc
55 	{
56 		this.payload = rhs.payload;
57 		if (payload !is null)
58 			payload.count++;
59 		return this;
60 	}
61 
62 	/*******
63 	* Destructor: frees all memory
64 	*/
65 	~this() nothrow @nogc
66 	{
67 		import core.stdc.stdlib: free;
68 		if (payload !is null && --payload.count == 0) {
69 			free(payload.dst);
70 			free(payload);
71 		}
72 	}
73 
74 	/*******
75 	* Returns: immutable(char)* null terminated string
76 	*/
77 	pragma(inline)
78 	T opCast(T:immutable(char)*)() pure nothrow @nogc
79 	{
80 		return *this;
81 	}
82 
83 	///ditto
84 	immutable(char)* opUnary(string s)() nothrow @nogc if (s == "*")
85 	{
86 		return cast(immutable(char)*)payload.dst;
87 	}
88 
89 	/*******
90 	* Returns: the length of the string
91 	*/
92 	immutable(size_t) length() nothrow @nogc
93 	{
94 		return payload.length;
95 	}
96 }