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 }