Coverage Report

Created: 2025-06-24 07:14

/src/libsmraw/libcsplit/libcsplit_narrow_string.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Narrow character string functions
3
 *
4
 * Copyright (C) 2008-2024, 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_narrow_split_string.h"
27
#include "libcsplit_narrow_string.h"
28
#include "libcsplit_types.h"
29
30
/* Splits a narrow character string
31
 * Make sure the value split_string is referencing, is set to NULL
32
 * Returns 1 if successful or -1 on error
33
 */
34
int libcsplit_narrow_string_split(
35
     const char *string,
36
     size_t string_size,
37
     char delimiter,
38
     libcsplit_narrow_split_string_t **split_string,
39
     libcerror_error_t **error )
40
387k
{
41
387k
  char *segment_start    = NULL;
42
387k
  char *segment_end      = NULL;
43
387k
  char *string_end       = NULL;
44
387k
  char *string_start     = NULL;
45
387k
  static char *function  = "libcsplit_narrow_string_split";
46
387k
  ssize_t segment_length = 0;
47
387k
  int number_of_segments = 0;
48
387k
  int segment_index      = 0;
49
50
387k
  if( string == NULL )
51
0
  {
52
0
    libcerror_error_set(
53
0
     error,
54
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
55
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
56
0
     "%s: invalid string.",
57
0
     function );
58
59
0
    return( -1 );
60
0
  }
61
387k
  if( string_size > (size_t) SSIZE_MAX )
62
0
  {
63
0
    libcerror_error_set(
64
0
     error,
65
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
66
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
67
0
     "%s: invalid string size value exceeds maximum.",
68
0
     function );
69
70
0
    return( -1 );
71
0
  }
72
387k
  if( split_string == NULL )
73
0
  {
74
0
    libcerror_error_set(
75
0
     error,
76
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
77
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
78
0
     "%s: invalid split string.",
79
0
     function );
80
81
0
    return( -1 );
82
0
  }
83
387k
  if( *split_string != NULL )
84
0
  {
85
0
    libcerror_error_set(
86
0
     error,
87
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
88
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
89
0
     "%s: invalid split string already set.",
90
0
     function );
91
92
0
    return( -1 );
93
0
  }
94
  /* An empty string has no segments
95
   */
96
387k
  if( ( string_size == 0 )
97
387k
   || ( string[ 0 ] == 0 ) )
98
22
  {
99
22
    return( 1 );
100
22
  }
101
  /* Determine the number of segments
102
   */
103
387k
  segment_start = (char *) string;
104
387k
  string_end    = (char *) &( string[ string_size - 1 ] );
105
106
387k
  do
107
49.5M
  {
108
49.5M
    segment_end = segment_start;
109
110
126M
    while( segment_end <= string_end )
111
126M
    {
112
126M
      if( ( segment_end == string_end )
113
126M
       || ( *segment_end == 0 ) )
114
387k
      {
115
387k
        segment_end = NULL;
116
117
387k
        break;
118
387k
      }
119
126M
      else if( *segment_end == delimiter )
120
49.2M
      {
121
49.2M
        break;
122
49.2M
      }
123
76.9M
      segment_end++;
124
76.9M
    }
125
49.5M
    if( segment_end > string_end )
126
0
    {
127
0
      break;
128
0
    }
129
49.5M
    segment_index++;
130
131
49.5M
    if( segment_end == NULL )
132
387k
    {
133
387k
      break;
134
387k
    }
135
49.2M
    if( segment_end == segment_start )
136
46.7M
    {
137
46.7M
      segment_start++;
138
46.7M
    }
139
2.45M
    else if( segment_end != string )
140
2.45M
    {
141
2.45M
      segment_start = segment_end + 1;
142
2.45M
    }
143
49.2M
  }
144
49.2M
  while( segment_end != NULL );
145
146
0
  number_of_segments = segment_index;
147
148
387k
  if( libcsplit_narrow_split_string_initialize(
149
387k
       split_string,
150
387k
       string,
151
387k
       string_size,
152
387k
       number_of_segments,
153
387k
       error ) != 1 )
154
0
  {
155
0
    libcerror_error_set(
156
0
     error,
157
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
158
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
159
0
     "%s: unable to initialize split string.",
160
0
     function );
161
162
0
    goto on_error;
163
0
  }
164
  /* Do not bother with strings that do not need splitting
165
   */
166
387k
  if( number_of_segments == 0 )
167
0
  {
168
0
    return( 1 );
169
0
  }
170
  /* Determine the segments
171
   * empty segments are stored as strings only containing the end of character
172
   */
173
387k
  if( libcsplit_narrow_split_string_get_string(
174
387k
       *split_string,
175
387k
       &string_start,
176
387k
       &string_size,
177
387k
       error ) != 1 )
178
0
  {
179
0
    libcerror_error_set(
180
0
     error,
181
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
182
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
183
0
     "%s: unable to retrieve split string.",
184
0
     function );
185
186
0
    goto on_error;
187
0
  }
188
387k
  if( string_start == NULL )
189
0
  {
190
0
    libcerror_error_set(
191
0
     error,
192
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
193
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
194
0
     "%s: missing string start.",
195
0
     function );
196
197
0
    goto on_error;
198
0
  }
199
387k
  if( string_size < 1 )
200
0
  {
201
0
    libcerror_error_set(
202
0
     error,
203
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
204
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
205
0
     "%s: invalid string size value out of bounds.",
206
0
     function );
207
208
0
    goto on_error;
209
0
  }
210
387k
  segment_start = string_start;
211
387k
  string_end    = &( string_start[ string_size - 1 ] );
212
213
387k
  for( segment_index = 0;
214
49.5M
       segment_index < number_of_segments;
215
49.2M
       segment_index++ )
216
49.5M
  {
217
49.5M
    segment_end = segment_start;
218
219
126M
    while( segment_end <= string_end )
220
126M
    {
221
126M
      if( ( segment_end == string_end )
222
126M
       || ( *segment_end == 0 ) )
223
387k
      {
224
387k
        segment_end = NULL;
225
226
387k
        break;
227
387k
      }
228
126M
      else if( *segment_end == delimiter )
229
49.2M
      {
230
49.2M
        break;
231
49.2M
      }
232
76.9M
      segment_end++;
233
76.9M
    }
234
49.5M
    if( segment_end == NULL )
235
387k
    {
236
387k
      segment_length = (ssize_t) ( string_end - segment_start );
237
387k
    }
238
49.2M
    else
239
49.2M
    {
240
49.2M
      segment_length = (ssize_t) ( segment_end - segment_start );
241
49.2M
    }
242
49.5M
    if( segment_length >= 0 )
243
49.5M
    {
244
49.5M
      segment_start[ segment_length ] = 0;
245
246
49.5M
      if( libcsplit_narrow_split_string_set_segment_by_index(
247
49.5M
           *split_string,
248
49.5M
           segment_index,
249
49.5M
           segment_start,
250
49.5M
           segment_length + 1,
251
49.5M
           error ) != 1 )
252
0
      {
253
0
        libcerror_error_set(
254
0
         error,
255
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
256
0
         LIBCERROR_RUNTIME_ERROR_SET_FAILED,
257
0
         "%s: unable to set split string segment: %d.",
258
0
         function,
259
0
         segment_index );
260
261
0
        goto on_error;
262
0
      }
263
49.5M
    }
264
49.5M
    if( segment_end == NULL )
265
387k
    {
266
387k
      break;
267
387k
    }
268
49.2M
    if( segment_end == string_start )
269
12.6k
    {
270
12.6k
      segment_start++;
271
12.6k
    }
272
49.1M
    else
273
49.1M
    {
274
49.1M
      segment_start = segment_end + 1;
275
49.1M
    }
276
49.2M
  }
277
387k
  return( 1 );
278
279
0
on_error:
280
0
  if( *split_string != NULL )
281
0
  {
282
0
    libcsplit_narrow_split_string_free(
283
0
     split_string,
284
0
     NULL );
285
0
  }
286
0
  return( -1 );
287
387k
}
288