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.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 	this (this) nothrow @nogc
47 	{
48 		if (payload !is null)
49 			payload.count++;
50 	}
51 
52 	///Ref. counting during structure assignment
53 	ref typeof(this) opAssign()(auto ref typeof(this) rhs) nothrow @nogc
54 	{
55 		this.payload = rhs.payload;
56 		if (payload !is null)
57 			payload.count++;
58 		return this;
59 	}
60 
61 	~this() nothrow @nogc
62 	{
63 		import core.stdc.stdlib: free;
64 		if (payload !is null && --payload.count == 0) {
65 			free(payload.dst);
66 			free(payload);
67 		}
68 	}
69 
70 	pragma(inline)
71 	T opCast(T:immutable(char)*)() pure nothrow @nogc
72 	{
73 		return *this;
74 	}
75 
76 	immutable(char)* opUnary(string s)() nothrow @nogc if (s == "*")
77 	{
78 		return cast(immutable(char)*)payload.dst;
79 	}
80 
81 	immutable(size_t) length() nothrow @nogc
82 	{
83 		return payload.length;
84 	}
85 }