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 import ocean.core.Buffer;
34 import ocean.meta.types.Qualifiers;
35
36 import core.stdc.string: strlen;
37 import core.stdc.wchar_: wcslen;
38 import core.stdc.stddef: wchar_t;
39
40
41 /*******************************************************************************
42
43 Class containing the string conversion functions
44
45 *******************************************************************************/
46
47 class StringC
48 {
49 /***************************************************************************
50
51 Wide character type alias (platform dependent)
52
53 **************************************************************************/
54
55 public alias wchar_t Wchar;
56
57 /***************************************************************************
58
59 Null terminators
60
61 **************************************************************************/
62
63 public static immutable char Term = '\0';
64 public static immutable Wchar Wterm = '\0';
65
66 /***************************************************************************
67
68 Converts str to a C string, that is, if a null terminator is not
69 present then it is appended to the original string. A pointer to the
70 string is returned.
71
72 Params:
73 str = input string
74
75 Returns:
76 C compatible (null terminated) string
77
78 ***************************************************************************/
79
80 public static char* toCString ( ref mstring str )
81 {
82 return typeof(this).toCString(*(cast(Buffer!(char)*)&str));
83 }
84
85 /***************************************************************************
86
87 Converts str to a C string, that is, if a null terminator is not
88 present then it is appended to the original string. A pointer to the
89 string is returned.
90
91 Params:
92 str = input string buffer
93
94 Returns:
95 C compatible (null terminated) string
96
97 ***************************************************************************/
98
99 public static char* toCString ( ref Buffer!(char) str )
100 {
101 if (!str.length || !!*str[str.length - 1])
102 {
103 str.length = str.length + 1;
104 str[str.length - 1] = StringC.Term;
105 }
106
107 return str[].ptr;
108 }
109
110 /***************************************************************************
111
112 Converts str to a D string: str is sliced from the beginning up to its
113 null terminator.
114
115 Params:
116 str = C compatible input string (pointer to the first character of
117 the null terminated string)
118
119 Returns:
120 D compatible (non-null terminated) string
121
122 ***************************************************************************/
123
124 public static inout(char)[] toDString ( inout(char)* str )
125 {
126 return str ? str[0 .. strlen(str)] : null;
127 }
128
129 /***************************************************************************
130
131 Converts str to a D string: str is sliced from the beginning up to its
132 null terminator.
133
134 Params:
135 str = C compatible input string (pointer to the first character of
136 the null terminated string)
137
138 Returns:
139 D compatible (non-null terminated) string
140
141 ***************************************************************************/
142
143 public static inout(Wchar)[] toDString ( inout(Wchar)* str )
144 {
145 return str ? str[0 .. wcslen(str)] : null;
146 }
147 }
148
149 version (unittest)
150 {
151 import ocean.core.Test;
152 }
153
154 unittest
155 {
156 mstring str;
157
158 str = "".dup;
159 test!("!is")(StringC.toCString(str), null);
160 test!("==")(str, "\0");
161
162 str = "Already null-terminated\0".dup;
163 StringC.toCString(str);
164 test!("==")(str, "Already null-terminated\0");
165
166 str = "Regular D string".dup;
167 StringC.toCString(str);
168 test!("==")(str, "Regular D string\0");
169
170 test!("==")(StringC.toDString(cast(char *)null), "");
171
172 str = "Hello\0".dup;
173 test!("==")(StringC.toDString(str.ptr), "Hello");
174
175 // String literals are null terminated
176 istring r1 = StringC.toDString("Hello".ptr);
177 test!("==")(r1, "Hello");
178 const(char)* const_empty = "".ptr;
179 test(const_empty !is null);
180 cstring r2 = StringC.toDString(const_empty);
181 test!("is")(const_empty, r2.ptr);
182
183 Buffer!(char) buff;
184 buff = "Regular D string".dup;
185 StringC.toCString(buff);
186 test!("==")(buff[], "Regular D string\0");
187 }