1 /*
2 * Wide character string functions
3 *
4 * Copyright (C) 2008-2020, Joachim Metz <joachim.metz@gmail.com>
5 *
6 * Refer to AUTHORS for acknowledgements.
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 */
21
22 #include <common.h>
23 #include <types.h>
24
25 #include "libcsplit_libcerror.h"
26 #include "libcsplit_wide_split_string.h"
27 #include "libcsplit_wide_string.h"
28 #include "libcsplit_types.h"
29
30 #if defined( HAVE_WIDE_CHARACTER_TYPE )
31
32 /* Splits a wide character string
33 * Make sure the value split_string is referencing, is set to NULL
34 * Returns 1 if successful or -1 on error
35 */
libcsplit_wide_string_split(const wchar_t * string,size_t string_size,wchar_t delimiter,libcsplit_wide_split_string_t ** split_string,libcerror_error_t ** error)36 int libcsplit_wide_string_split(
37 const wchar_t *string,
38 size_t string_size,
39 wchar_t delimiter,
40 libcsplit_wide_split_string_t **split_string,
41 libcerror_error_t **error )
42 {
43 wchar_t *segment_start = NULL;
44 wchar_t *segment_end = NULL;
45 wchar_t *string_end = NULL;
46 wchar_t *string_start = NULL;
47 static char *function = "libcsplit_wide_string_split";
48 ssize_t segment_length = 0;
49 int number_of_segments = 0;
50 int segment_index = 0;
51
52 if( string == NULL )
53 {
54 libcerror_error_set(
55 error,
56 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
57 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
58 "%s: invalid string.",
59 function );
60
61 return( -1 );
62 }
63 if( string_size > (size_t) SSIZE_MAX )
64 {
65 libcerror_error_set(
66 error,
67 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
68 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
69 "%s: invalid string size value exceeds maximum.",
70 function );
71
72 return( -1 );
73 }
74 if( split_string == NULL )
75 {
76 libcerror_error_set(
77 error,
78 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
79 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
80 "%s: invalid split string.",
81 function );
82
83 return( -1 );
84 }
85 if( *split_string != NULL )
86 {
87 libcerror_error_set(
88 error,
89 LIBCERROR_ERROR_DOMAIN_RUNTIME,
90 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
91 "%s: invalid split string already set.",
92 function );
93
94 return( -1 );
95 }
96 /* An empty string has no segments
97 */
98 if( ( string_size == 0 )
99 || ( string[ 0 ] == 0 ) )
100 {
101 return( 1 );
102 }
103 /* Determine the number of segments
104 */
105 segment_start = (wchar_t *) string;
106 string_end = (wchar_t *) &( string[ string_size - 1 ] );
107
108 do
109 {
110 segment_end = segment_start;
111
112 while( segment_end <= string_end )
113 {
114 if( ( segment_end == string_end )
115 || ( *segment_end == 0 ) )
116 {
117 segment_end = NULL;
118
119 break;
120 }
121 else if( *segment_end == delimiter )
122 {
123 break;
124 }
125 segment_end++;
126 }
127 if( segment_end > string_end )
128 {
129 break;
130 }
131 segment_index++;
132
133 if( segment_end == NULL )
134 {
135 break;
136 }
137 if( segment_end == segment_start )
138 {
139 segment_start++;
140 }
141 else if( segment_end != string )
142 {
143 segment_start = segment_end + 1;
144 }
145 }
146 while( segment_end != NULL );
147
148 number_of_segments = segment_index;
149
150 if( libcsplit_wide_split_string_initialize(
151 split_string,
152 string,
153 string_size,
154 number_of_segments,
155 error ) != 1 )
156 {
157 libcerror_error_set(
158 error,
159 LIBCERROR_ERROR_DOMAIN_RUNTIME,
160 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
161 "%s: unable to initialize split string.",
162 function );
163
164 goto on_error;
165 }
166 /* Do not bother with strings that do not need splitting
167 */
168 if( number_of_segments == 0 )
169 {
170 return( 1 );
171 }
172 /* Determine the segments
173 * empty segments are stored as strings only containing the end of character
174 */
175 if( libcsplit_wide_split_string_get_string(
176 *split_string,
177 &string_start,
178 &string_size,
179 error ) != 1 )
180 {
181 libcerror_error_set(
182 error,
183 LIBCERROR_ERROR_DOMAIN_RUNTIME,
184 LIBCERROR_RUNTIME_ERROR_GET_FAILED,
185 "%s: unable to retrieve split string.",
186 function );
187
188 goto on_error;
189 }
190 if( string_start == NULL )
191 {
192 libcerror_error_set(
193 error,
194 LIBCERROR_ERROR_DOMAIN_RUNTIME,
195 LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
196 "%s: missing string start.",
197 function );
198
199 goto on_error;
200 }
201 if( string_size < 1 )
202 {
203 libcerror_error_set(
204 error,
205 LIBCERROR_ERROR_DOMAIN_RUNTIME,
206 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
207 "%s: invalid string size value out of bounds.",
208 function );
209
210 goto on_error;
211 }
212 segment_start = string_start;
213 string_end = &( string_start[ string_size - 1 ] );
214
215 for( segment_index = 0;
216 segment_index < number_of_segments;
217 segment_index++ )
218 {
219 segment_end = segment_start;
220
221 while( segment_end <= string_end )
222 {
223 if( ( segment_end == string_end )
224 || ( *segment_end == 0 ) )
225 {
226 segment_end = NULL;
227
228 break;
229 }
230 else if( *segment_end == delimiter )
231 {
232 break;
233 }
234 segment_end++;
235 }
236 if( segment_end == NULL )
237 {
238 segment_length = (ssize_t) ( string_end - segment_start );
239 }
240 else
241 {
242 segment_length = (ssize_t) ( segment_end - segment_start );
243 }
244 if( segment_length >= 0 )
245 {
246 segment_start[ segment_length ] = 0;
247
248 if( libcsplit_wide_split_string_set_segment_by_index(
249 *split_string,
250 segment_index,
251 segment_start,
252 segment_length + 1,
253 error ) != 1 )
254 {
255 libcerror_error_set(
256 error,
257 LIBCERROR_ERROR_DOMAIN_RUNTIME,
258 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
259 "%s: unable to set split string segment: %d.",
260 function,
261 segment_index );
262
263 goto on_error;
264 }
265 }
266 if( segment_end == NULL )
267 {
268 break;
269 }
270 if( segment_end == string_start )
271 {
272 segment_start++;
273 }
274 else
275 {
276 segment_start = segment_end + 1;
277 }
278 }
279 return( 1 );
280
281 on_error:
282 if( *split_string != NULL )
283 {
284 libcsplit_wide_split_string_free(
285 split_string,
286 NULL );
287 }
288 return( -1 );
289 }
290
291 #endif /* defined( HAVE_WIDE_CHARACTER_TYPE ) */
292
293