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 }