1 //this file is part of notepad++
2 //Copyright (C)2003 Don HO <donho@altern.org>
3 //
4 //This program is free software; you can redistribute it and/or
5 //modify it under the terms of the GNU General Public License
6 //as published by the Free Software Foundation; either
7 //version 2 of the License, or (at your option) any later version.
8 //
9 //This program is distributed in the hope that it will be useful,
10 //but WITHOUT ANY WARRANTY; without even the implied warranty of
11 //MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 //GNU General Public License for more details.
13 //
14 //You should have received a copy of the GNU General Public License
15 //along with this program; if not, write to the Free Software
16 //Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 /**
18  * 
19  *
20  * Author: dokutoku, https://twitter.com/dokutoku3
21  * License: GPL-2.0 or later
22  */
23 module npp_api.pluginfunc..string;
24 
25 
26 private static import std.format;
27 private static import std.traits;
28 
29 template c_string(string input_string)
30 {
31 	enum string c_string = (input_string.length == 0) ? ("\0") : ((input_string[$ - 1] != '\0') ? (input_string ~ "\0") : (input_string));
32 }
33 
34 template c_wstring(wstring input_string)
35 {
36 	enum wstring c_wstring = (input_string.length == 0) ? ("\0"w) : ((input_string[$ - 1] != '\0') ? ((input_string ~ "\0"w)) : (input_string));
37 }
38 
39 pure nothrow @safe @nogc
40 void to_c_wstring(size_t LENGTH)(const wchar[] input, ref wchar[LENGTH] buffer)
41 
42 	in
43 	{
44 		assert(LENGTH >= (input.length + 1));
45 	}
46 
47 	do
48 	{
49 		size_t i = 0;
50 
51 		buffer[0 .. input.length] = input[0 .. input.length];
52 		buffer[input.length + 1] = '\0';
53 	}
54 
55 pure nothrow @safe @nogc
56 size_t count_string(S)(const S c_wstring)
57 	if (std.traits.isStaticArray!(S))
58 
59 	do
60 	{
61 		size_t i = 0;
62 
63 		for (; (i < c_wstring.length) && (c_wstring[i] != '\0') && (c_wstring[i] != '\xFF'); i++) {
64 		}
65 
66 		return i;
67 	}
68 
69 /**
70  * 文字列終端を'\0'にするようにしたしたコピー関数
71  */
72 pragma(inline, true)
73 pure nothrow @safe @nogc
74 void copy_string(S_array, T_array)(ref S_array output_string, const T_array input_string)
75 	if (std.traits.isArray!(S_array) && std.traits.isDynamicArray!(T_array))
76 
77 	in
78 	{
79 		assert(input_string.length != 0);
80 		assert(output_string.length != 0);
81 		assert(output_string.length >= input_string.length);
82 
83 		//not dchar
84 		assert(output_string[0].max >= wchar.max);
85 		assert(output_string[0].max == input_string[0].max);
86 	}
87 
88 	out
89 	{
90 		for (size_t i = 0; i < output_string.length; i++) {
91 			assert(output_string[i] != '\xFF');
92 		}
93 
94 		assert(output_string[$ - 1] == '\0');
95 	}
96 
97 	do
98 	{
99 		output_string[] = '\0';
100 		size_t c_max = output_string.length - 1;
101 
102 		for (size_t i = 0; (i < c_max) && (i < input_string.length) && (input_string[i] != '\0') && (input_string[i] != '\xFF'); i++) {
103 			output_string[i] = input_string[i];
104 		}
105 	}
106 
107 pure nothrow @safe @nogc
108 wchar[LENGTH] copy_string(size_t LENGTH)(const wchar[LENGTH] input_string)
109 
110 	out(result)
111 	{
112 		for (size_t i = 0; i < result.length; i++) {
113 			assert(result[i] != '\xFF');
114 		}
115 
116 		assert(result[$ - 1] == '\0');
117 	}
118 
119 	do
120 	{
121 		wchar[LENGTH] output_string;
122 		output_string[] = '\0';
123 		size_t c_max = output_string.length - 1;
124 
125 		for (size_t i = 0; (i < c_max) && (input_string[i] != '\0') && (input_string[i] != '\xFF'); i++) {
126 			output_string[i] = input_string[i];
127 		}
128 
129 		return output_string;
130 	}
131 
132 version (Not_betterC):
133 
134 pure nothrow @safe
135 wstring to_c_wstring(const wchar[] input)
136 
137 	do
138 	{
139 		return (input ~ '\0').idup;
140 	}
141 
142 pure nothrow @safe
143 immutable (C)[] from_stringz(C, size_t INPUT_LENGTH)(const ref C[INPUT_LENGTH] input)
144 	if (std.traits.isSomeChar!(C))
145 
146 	in
147 	{
148 		static assert(INPUT_LENGTH >= 1);
149 	}
150 
151 	do
152 	{
153 		size_t i = 0;
154 
155 		for (; (i < INPUT_LENGTH) && (input[i] != '\0') && (input[i] != '\xFF'); i++) {
156 		}
157 
158 		return input[0 .. i].idup;
159 	}
160 
161 pure nothrow @safe
162 immutable (C)[] from_stringz(C)(const ref C[] input)
163 	if (std.traits.isSomeChar!(C))
164 
165 	in
166 	{
167 		assert(input.length >= 1);
168 	}
169 
170 	do
171 	{
172 		size_t i = 0;
173 
174 		for (; (i < input.length) && (input[i] != '\0') && (input[i] != '\xFF'); i++) {
175 		}
176 
177 		return input[0 .. i].idup;
178 	}
179 
180 pure nothrow @trusted
181 immutable (C)[] from_stringz(C)(const C* input)
182 	if (std.traits.isSomeChar!(C))
183 
184 	do
185 	{
186 		size_t i = 0;
187 		C[] output_buf;
188 
189 		for (; ((*(input + i)) != '\0') && (*(input + i)) != '\xFF'; i++) {
190 			output_buf ~= *(input + i);
191 		}
192 
193 		output_buf ~= '\0';
194 
195 		return output_buf.idup;
196 	}
197 
198 pure nothrow @trusted
199 immutable (C)[] from_stringz(C)(const C* input, size_t max_length)
200 	if (std.traits.isSomeChar!(C))
201 
202 	do
203 	{
204 		if (max_length == 0) {
205 			return null;
206 		}
207 
208 		size_t i = 0;
209 		C[] output_buf = new C[max_length];
210 
211 		for (; (i < max_length) && ((*(input + i)) != '\0') && ((*(input + i)) != '\xFF'); i++) {
212 			output_buf[i] = *(input + i);
213 		}
214 
215 		return output_buf[0 .. i].idup;
216 	}
217 
218 pure nothrow @safe
219 immutable (C)[] to_cstring(C, size_t INPUT_LENGTH)(const ref C[INPUT_LENGTH] input)
220 	if (std.traits.isSomeChar!(C))
221 
222 	in
223 	{
224 		static assert(INPUT_LENGTH >= 2);
225 	}
226 
227 	do
228 	{
229 		enum size_t c_max = INPUT_LENGTH - 1;
230 		size_t i = 0;
231 		C[INPUT_LENGTH] output_buf;
232 
233 		for (; (i < c_max) && (input[i] != '\0') && (input[i] != '\xFF'); i++) {
234 			output_buf[i] = input[i];
235 		}
236 
237 		i++;
238 		output_buf[i] = '\0';
239 
240 		return output_buf[0 .. i].idup;
241 	}
242 
243 pure nothrow @safe
244 immutable (C)[] to_cstring(C, size_t INPUT_LENGTH, size_t OUTPUT_LENGTH)(const ref C[INPUT_LENGTH] input, ref C[OUTPUT_LENGTH] output_buf)
245 	if (std.traits.isSomeChar!(C))
246 
247 	in
248 	{
249 		static assert(input.length >= 2);
250 		static assert(OUTPUT_LENGTH >= INPUT_LENGTH);
251 	}
252 
253 	do
254 	{
255 		size_t i = 0;
256 		size_t c_max = INPUT_LENGTH - 1;
257 
258 		for (; (i < c_max) && (input[i] != '\0') && (input[i] != '\xFF'); i++) {
259 			output_buf[i] = input[i];
260 		}
261 
262 		i++;
263 		output_buf[i] = '\0';
264 
265 		return output_buf[0 .. i].idup;
266 	}
267 
268 pure nothrow @trusted
269 immutable (C)[] to_cstring(C)(const C* input, size_t max_length)
270 	if (std.traits.isSomeChar!(C))
271 
272 	do
273 	{
274 		if (max_length == 0) {
275 			return null;
276 		}
277 
278 		size_t i = 0;
279 		size_t c_max = max_length - 1;
280 		C[] output_buf = new C[max_length + 1];
281 
282 		for (; (i < c_max) && ((*(input + i)) != '\0') && ((*(input + i)) != '\xFF'); i++) {
283 			output_buf[i] = *(input + i);
284 		}
285 
286 		i++;
287 		output_buf[i] = '\0';
288 
289 		return output_buf[0 .. i].idup;
290 	}