1 /*******************************************************************************
2 
3         copyright:      Copyright (c) 2006 Keinfarbton. All rights reserved
4 
5         license:        BSD style: $(LICENSE)
6 
7         version:        Initial release: October 2006
8 
9         author:         Keinfarbton & Kris
10 
11 *******************************************************************************/
12 
13 module tango.stdc.stringz;
14 
15 /*********************************
16  * Convert array of chars to a C-style 0 terminated string.
17  * Providing a tmp will use that instead of the heap, where
18  * appropriate.
19  * 
20  * Warning, don't read from the memory pointed to in the tmp variable after calling this function.
21  */
22 
23 inout(char)* toStringz (inout(char)[] s, char[] tmp=null)
24 {
25         auto len = s.length;
26         if (s.ptr)
27         {
28             if (len is 0)
29             {
30                 s = cast(inout(char)[])("\0".dup);
31             }
32             else if (s[len-1] != 0)
33             {
34                   if (tmp.length <= len)
35                       tmp = new char[len+1];
36                   tmp [0..len] = s[];
37                   tmp [len] = 0;
38                   s = cast(inout(char)[])tmp;
39             }
40         }
41         return s.ptr;
42 }
43 
44 /*********************************
45  * Convert a series of char[] to C-style 0 terminated strings, using 
46  * tmp as a workspace and dst as a place to put the resulting char*'s.
47  * This is handy for efficiently converting multiple strings at once.
48  *
49  * Returns a populated slice of dst
50  * 
51  * Warning, don't read from the memory pointed to in the tmp variable after calling this function.
52  *
53  * Since: 0.99.7
54  */
55 
56 inout(char)*[] toStringz (char[] tmp, inout(char)*[] dst, inout(char)[][] strings...)
57 {
58         assert (dst.length >= strings.length);
59 
60         auto len = strings.length;
61         foreach (s; strings)
62                  len += s.length;
63         if (tmp.length < len)
64             tmp.length = len;
65 
66         foreach (i, s; strings)
67                 {
68                 dst[i] = toStringz (s, tmp);
69                 tmp = tmp [s.length + 1 .. len];
70                 }
71         return dst [0 .. strings.length];
72 }
73 
74 /*********************************
75  * Convert a C-style 0 terminated string to an array of char
76  */
77 
78 inout(char)[] fromStringz (inout(char)* s)
79 {
80         return s ? s[0 .. strlenz(s)] : null;
81 }
82 
83 /*********************************
84  * Convert array of wchars s[] to a C-style 0 terminated string.
85  */
86 
87 inout(wchar)* toString16z (inout(wchar)[] s)
88 {
89         if (s.ptr)
90             if (! (s.length && s[$-1] is 0))
91                    s = cast(inout(wchar)[])(s ~ "\0"w);
92         return s.ptr;
93 }
94 
95 /*********************************
96  * Convert a C-style 0 terminated string to an array of wchar
97  */
98 
99 inout(wchar)[] fromString16z (inout(wchar)* s)
100 {
101         return s ? s[0 .. strlenz(s)] : null;
102 }
103 
104 /*********************************
105  * Convert array of dchars s[] to a C-style 0 terminated string.
106  */
107 
108 inout(dchar)* toString32z (inout(dchar)[] s)
109 {
110         if (s.ptr)
111             if (! (s.length && s[$-1] is 0))
112                    s = cast(inout(dchar)[])(s ~ "\0"d);
113         return s.ptr;
114 }
115 
116 /*********************************
117  * Convert a C-style 0 terminated string to an array of dchar
118  */
119 
120 inout(dchar)[] fromString32z (inout(dchar)* s)
121 {
122         return s ? s[0 .. strlenz(s)] : null;
123 }
124 
125 /*********************************
126  * portable strlen
127  */
128 
129 size_t strlenz(T) (const(T)* s)
130 {
131         size_t i;
132 
133         if (s)
134             while (*s++)
135                    ++i;
136         return i;
137 }
138 
139 
140 
141 debug (UnitTest)
142 {
143         import tango.stdc.stdio;
144 
145         unittest
146         {
147         debug(string) printf("stdc.stringz.unittest\n");
148 
149         const(char)* p = toStringz("foo");
150         assert(strlenz(p) == 3);
151         const(char)[] foo = "abbzxyzzy";
152         p = toStringz(foo[3..5]);
153         assert(strlenz(p) == 2);
154 
155         const(char)[] test = "\0";
156         p = toStringz(test);
157         assert(*p == 0);
158         assert(p == test.ptr);
159         }
160 }
161