1 /*******************************************************************************
2 
3     Module for conversion between strings in C and D. Needed for C library
4     bindings.
5 
6     Usage:
7 
8     ---
9 
10         mstring text;
11 
12         char* cText = StringC.toCString(text);
13         mstring text = StringC.toDString(cText);
14 
15     ---
16 
17     FIXME: the functions here are not memory safe, they need to be re-written to
18     accept ref char[].
19 
20     Copyright:
21         Copyright (c) 2009-2016 dunnhumby Germany GmbH.
22         All rights reserved.
23 
24     License:
25         Boost Software License Version 1.0. See LICENSE_BOOST.txt for details.
26         Alternatively, this file may be distributed under the terms of the Tango
27         3-Clause BSD License (see LICENSE_BSD.txt for details).
28 
29 *******************************************************************************/
30 
31 module ocean.text.util.StringC;
32 
33 
34 
35 import ocean.transition;
36 
37 import ocean.core.Buffer;
38 import ocean.stdc.string: strlen, wcslen;
39 import core.stdc.stddef: wchar_t;
40 
41 
42 /*******************************************************************************
43 
44     Class containing the string conversion functions
45 
46 *******************************************************************************/
47 
48 class StringC
49 {
50     /***************************************************************************
51 
52         Wide character type alias (platform dependent)
53 
54      **************************************************************************/
55 
56     public alias wchar_t Wchar;
57 
58     /***************************************************************************
59 
60         Null terminators
61 
62      **************************************************************************/
63 
64     public static immutable char  Term  = '\0';
65     public static immutable Wchar Wterm = '\0';
66 
67     /***************************************************************************
68 
69         Converts str to a C string, that is, if a null terminator is not
70         present then it is appended to the original string. A pointer to the
71         string is returned.
72 
73         Params:
74             str = input string
75 
76         Returns:
77             C compatible (null terminated) string
78 
79     ***************************************************************************/
80 
81     public static char* toCString ( ref mstring str )
82     {
83         return typeof(this).toCString(*(cast(Buffer!(char)*)&str));
84     }
85 
86     /***************************************************************************
87 
88         Converts str to a C string, that is, if a null terminator is not
89         present then it is appended to the original string. A pointer to the
90         string is returned.
91 
92         Params:
93             str = input string buffer
94 
95         Returns:
96             C compatible (null terminated) string
97 
98     ***************************************************************************/
99 
100     public static char* toCString ( ref Buffer!(char) str )
101     {
102         if (!str.length || !!*str[str.length - 1])
103         {
104             str.length = str.length + 1;
105             str[str.length - 1] = StringC.Term;
106         }
107 
108         return str[].ptr;
109     }
110 
111     /***************************************************************************
112 
113         Converts str to a D string: str is sliced from the beginning up to its
114         null terminator.
115 
116         Params:
117             str = C compatible input string (pointer to the first character of
118                 the null terminated string)
119 
120         Returns:
121             D compatible (non-null terminated) string
122 
123     ***************************************************************************/
124 
125     public static Inout!(char)[] toDString ( Inout!(char)* str )
126     {
127         return str ? str[0 .. strlen(str)] : null;
128     }
129 
130     /***************************************************************************
131 
132         Converts str to a D string: str is sliced from the beginning up to its
133         null terminator.
134 
135         Params:
136             str = C compatible input string (pointer to the first character of
137                 the null terminated string)
138 
139         Returns:
140             D compatible (non-null terminated) string
141 
142     ***************************************************************************/
143 
144     public static Inout!(Wchar)[] toDString ( Inout!(Wchar)* str )
145     {
146         return str ? str[0 .. wcslen(str)] : null;
147     }
148 }
149 
150 version ( UnitTest )
151 {
152     import ocean.core.Test;
153 }
154 
155 unittest
156 {
157     mstring str;
158 
159     str = "".dup;
160     test!("!is")(StringC.toCString(str), null);
161     test!("==")(str, "\0");
162 
163     str = "Already null-terminated\0".dup;
164     StringC.toCString(str);
165     test!("==")(str, "Already null-terminated\0");
166 
167     str = "Regular D string".dup;
168     StringC.toCString(str);
169     test!("==")(str, "Regular D string\0");
170 
171     test!("==")(StringC.toDString(cast(char *)null), "");
172 
173     str = "Hello\0".dup;
174     test!("==")(StringC.toDString(str.ptr), "Hello");
175 
176     // String literals are null terminated
177     istring r1 = StringC.toDString("Hello".ptr);
178     test!("==")(r1, "Hello");
179     Const!(char)* const_empty = "".ptr;
180     test(const_empty !is null);
181     cstring r2 = StringC.toDString(const_empty);
182     test!("is")(const_empty, r2.ptr);
183 
184     Buffer!(char) buff;
185     buff = "Regular D string".dup;
186     StringC.toCString(buff);
187     test!("==")(buff[], "Regular D string\0");
188 }