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 }