1 /**
2  * Copyright: Copyright (c) 2008-2009 Jacob Carlborg. All rights reserved.
3  * Authors: Jacob Carlborg
4  * Version: Initial created: 2008
5  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0)
6  *
7  */
8 module mambo.core..string;
9 
10 import std.array;
11 static import std.ascii;
12 
13 static import tango.stdc.stringz;
14 import tango.text.Unicode;
15 import tango.text.convert.Format;
16 import tango.text.convert.Utf;
17 import tango.text.Util;
18 
19 
20 public import mambo.core.Array;
21 import mambo.util.Version;
22 import mambo.util.Traits;
23 
24 alias tango.stdc.stringz.toStringz toStringz;
25 alias tango.stdc.stringz.toString16z toString16z;
26 alias tango.stdc.stringz.toString32z toString32z;
27 
28 alias tango.stdc.stringz.fromStringz fromStringz;
29 alias tango.stdc.stringz.fromString16z fromString16z;
30 alias tango.stdc.stringz.fromString32z fromString32z;
31 
32 alias tango.text.convert.Utf.toString16 toString16;
33 alias tango.text.convert.Utf.toString32 toString32;
34 
35 alias tango.text.Unicode.isUpper isUpper;
36 alias tango.text.Unicode.isLower isLower;
37 
38 alias std.array.replace replace;
39 alias std.ascii.isHexDigit isHexDigit;
40 
41 /**
42  * Compares the $(D_PSYMBOL string) to another $(D_PSYMBOL string), ignoring case
43  * considerations.  Two strings are considered equal ignoring case if they are of the
44  * same length and corresponding characters in the two strings  are equal ignoring case.
45  *
46  * Params:
47  *     str = The $(D_PSYMBOL string) first string to compare to
48  *     anotherString = The $(D_PSYMBOL string) to compare the first $(D_PSYMBOL string) with
49  *
50  * Returns: $(D_KEYWORD true) if the arguments is not $(D_KEYWORD null) and it
51  *          represents an equivalent $(D_PSYMBOL string) ignoring case; $(D_KEYWORD false) otherwise
52  *
53  * Throws: AssertException if the length of any of the strings is 0
54  *
55  * See_Also: opEquals(Object)
56  */
57 bool equalsIgnoreCase (string str, string anotherString)
58 in
59 {
60 	assert(str.length > 0, "mambo.string.equalsIgnoreCase: The length of the first string was 0");
61 	assert(anotherString.length > 0, "mambo.string.equalsIgnoreCase: The length of the second string was 0");
62 }
63 body
64 {
65 	if (str == anotherString)
66 		return true;
67 
68 	return toFold(str) == toFold(anotherString);
69 }
70 
71 /**
72  * Compares the $(D_PSYMBOL wstring) to another $(D_PSYMBOL wstring), ignoring case
73  * considerations. Two wstrings are considered equal ignoring case if they are of the
74  * same length and corresponding characters in the two wstrings are equal ignoring case.
75  *
76  * Params:
77  *     str = The $(D_PSYMBOL wstring) first string to compre to
78  *     anotherString = The $(D_PSYMBOL wstring) to compare the first $(D_PSYMBOL wstring) against
79  *
80  * Returns: $(D_KEYWORD true) if the argument is not $(D_KEYWORD null) and it
81  *          represents an equivalent $(D_PSYMBOL wstring) ignoring case; (D_KEYWORD
82  *          false) otherwise
83  *
84  * Throws: AssertException if the length of any of the wstrings is 0
85  *
86  * See_Also: opEquals(Object)
87  */
88 bool equalsIgnoreCase (wstring str, wstring anotherString)
89 in
90 {
91 	assert(str.length > 0, "mambo.string.equalsIgnoreCase: The length of the first string was 0");
92 	assert(anotherString.length > 0, "mambo.string.equalsIgnoreCase: The length of the second string was 0");
93 }
94 body
95 {
96 	if (str == anotherString)
97 		return true;
98 
99 	return toFold(str) == toFold(anotherString);
100 }
101 
102 /**
103  * Compares the $(D_PSYMBOL dstring) to another $(D_PSYMBOL dstring), ignoring case
104  * considerations. Two wstrings are considered equal ignoring case if they are of the
105  * same length and corresponding characters in the two wstrings are equal ignoring case.
106  *
107  * Params:
108  *     str = The $(D_PSYMBOL dstring) first string to compare to
109  *     anotherString = The $(D_PSYMBOL wstring) to compare the first $(D_PSYMBOL dstring) against
110  *
111  * Returns: $(D_KEYWORD true) if the argument is not $(D_KEYWORD null) and it
112  *          represents an equivalent $(D_PSYMBOL dstring) ignoring case; $(D_KEYWORD false) otherwise
113  *
114  * Throws: AssertException if the length of any of the dstrings are 0
115  *
116  * See_Also: opEquals(Object)
117  */
118 bool equalsIgnoreCase (dstring str, dstring anotherString)
119 in
120 {
121 	assert(str.length > 0, "mambo.string.equalsIgnoreCase: The length of the first string was 0");
122 	assert(anotherString.length > 0, "mambo.string.equalsIgnoreCase: The length of the second string was 0");
123 }
124 body
125 {
126 	if (str == anotherString)
127 		return true;
128 
129 	return toFold(str) == toFold(anotherString);
130 }
131 
132 /**
133  * Finds the first occurence of sub in str
134  *
135  * Params:
136  *     str = the string to find in
137  *     sub = the substring to find
138  *     start = where to start finding
139  *
140  * Returns: the index of the substring or size_t.max when nothing was found
141  */
142 /+size_t find (string str, string sub, size_t start = 0)
143 {
144 	size_t index = str.locatePattern(sub, start);
145 
146 	if (index == str.length)
147 		return size_t.max;
148 
149 	return index;
150 }
151 
152 /**
153  * Finds the first occurence of sub in str
154  *
155  * Params:
156  *     str = the string to find in
157  *     sub = the substring to find
158  *     start = where to start finding
159  *
160  * Returns: the index of the substring or size_t.max when nothing was found
161  */
162 size_t find (wstring str, wstring sub, size_t start = 0)
163 {
164 	size_t index = str.locatePattern(sub, start);
165 
166 	if (index == str.length)
167 		return size_t.max;
168 
169 	return index;
170 }
171 
172 /**
173  * Finds the first occurence of sub in str
174  *
175  * Params:
176  *     str = the string to find in
177  *     sub = the substring to find
178  *     start = where to start finding
179  *
180  * Returns: the index of the substring or size_t.max when nothing was found
181  */
182 size_t find (dstring str, dstring sub, size_t start = 0)
183 {
184 	size_t index = str.locatePattern(sub, start);
185 
186 	if (index == str.length)
187 		return size_t.max;
188 
189 	return index;
190 }+/
191 
192 /**
193  * Compares to strings, ignoring case differences. Returns 0 if the content
194  * matches, less than zero if a is "less" than b, or greater than zero
195  * where a is "bigger".
196  *
197  * Params:
198  *     a = the first array
199  *     b = the second array
200  *     end = the index where the comparision will end
201  *
202  * Returns: Returns 0 if the content matches, less than zero if a is
203  * 			"less" than b, or greater than zero where a is "bigger".
204  *
205  * See_Also: mambo.collection.array.compare
206  */
207 int compareIgnoreCase (U = size_t) (string a, string b, U end = U.max)
208 {
209 	return a.toFold().compare(b.toFold(), end);
210 }
211 
212 /**
213  * Compares to strings, ignoring case differences. Returns 0 if the content
214  * matches, less than zero if a is "less" than b, or greater than zero
215  * where a is "bigger".
216  *
217  * Params:
218  *     a = the first array
219  *     b = the second array
220  *     end = the index where the comparision will end
221  *
222  * Returns: Returns 0 if the content matches, less than zero if a is
223  * 			"less" than b, or greater than zero where a is "bigger".
224  *
225  * See_Also: mambo.collection.array.compare
226  */
227 int compareIgnoreCase (U = size_t) (wstring a, wstring b, U end = U.max)
228 {
229 	return a.toFold().compare(b.toFold(), end);
230 }
231 
232 /**
233  * Compares to strings, ignoring case differences. Returns 0 if the content
234  * matches, less than zero if a is "less" than b, or greater than zero
235  * where a is "bigger".
236  *
237  * Params:
238  *     a = the first array
239  *     b = the second array
240  *     end = the index where the comparision will end
241  *
242  * Returns: Returns 0 if the content matches, less than zero if a is
243  * 			"less" than b, or greater than zero where a is "bigger".
244  *
245  * See_Also: mambo.collection.array.compare
246  */
247 int compareIgnoreCase (U = size_t) (dstring a, dstring b, U end = U.max)
248 {
249 	return a.toFold().compare(b.toFold(), end);
250 }
251 
252 /// Converts the given value to a string.
253 string toString (T) (T value)
254 {
255 	import std.conv;
256 	return to!(string)(value);
257 }
258 
259 /// Converts the given string to lowercase.
260 inout(T)[] toLower (T) (inout(T)[] value)
261 {
262 	auto r = tango.text.Unicode.toLower(value);
263 	inout(T)[] dest;
264 
265 	return assumeUnique(r, dest);
266 }
267 
268 /// Converts the given string to uppercase.
269 inout(T)[] toUpper (T) (inout(T)[] value)
270 {
271 	auto r = tango.text.Unicode.toUpper(value);
272 	inout(T)[] dest;
273 
274 	return assumeUnique(r, dest);
275 }
276 
277 string format (Args ...) (Args args)
278 {
279 	return Format(args).assumeUnique;
280 }