Line data Source code
1 : /* File: utf8stringbuf.inl; Copyright and License: see below */
2 :
3 : #include "utf8stringbuf/utf8codepoint.h"
4 : #include <string.h>
5 : #include <stdio.h>
6 : #include <stdint.h>
7 :
8 : #ifdef __cplusplus
9 : extern "C" {
10 : #endif
11 :
12 : /*!
13 : * \enum utf8stringbuf_bool_enum
14 : * \private
15 : */
16 : /* enumeration for true and false or success and failure */
17 : enum utf8stringbuf_bool_enum {UTF8STRINGBUF_FALSE=0, UTF8STRINGBUF_TRUE=1,};
18 :
19 : /*!
20 : * \enum utf8stringbuf_search_enum
21 : * \private
22 : */
23 : /* enumeration for search pattern not found */
24 : enum utf8stringbuf_search_enum {UTF8STRINGBUF_NOT_FOUND=-1,};
25 :
26 : /*!
27 : * \var utf8stringbuf_private_format_signed_64_bit_int
28 : * \private
29 : */
30 : /* a character array containing nothing but a single zero */
31 : extern const char *utf8stringbuf_private_format_signed_64_bit_int;
32 :
33 : /*!
34 : * \var utf8stringbuf_private_format_64_bit_hex
35 : * \private
36 : */
37 : /* a character array containing nothing but a single zero */
38 : extern const char *utf8stringbuf_private_format_64_bit_hex;
39 :
40 : /*!
41 : * \var utf8stringbuf_private_empty_buf
42 : * \private
43 : */
44 : /* a character array containing nothing but a single zero */
45 : extern char utf8stringbuf_private_empty_buf[1];
46 :
47 : /*!
48 : * \fn utf8_string_buf_private_make_null_termination( utf8stringbuf_t this_ )
49 : * \private
50 : * \return new, truncated length of the string
51 : */
52 : /* function to make a buffer null terminated while ensuring that all utf8 character sequences are valid */
53 : extern unsigned int utf8_string_buf_private_make_null_termination( utf8stringbuf_t this_ );
54 :
55 : /*!
56 : * \fn utf8_string_buf_private_replace_region_by_str( utf8stringbuf_t this_, unsigned int this_Length, int start, int length, const char *replacement )
57 : * \private
58 : */
59 : /* function to replace a region within a string buffer, the original string length must be provided in this_Length */
60 : extern utf8error_t utf8_string_buf_private_replace_region_by_str( utf8stringbuf_t this_, unsigned int this_Length, int start, int length, const char *replacement );
61 :
62 21 : static inline utf8stringbuf_t utf8stringbuf( char *that )
63 : {
64 : utf8stringbuf_t result;
65 21 : if ( that == NULL )
66 : {
67 1 : result.size = 1;
68 1 : result.buf = utf8stringbuf_private_empty_buf;
69 : }
70 : else
71 : {
72 20 : result.size = strlen( that )+1;
73 20 : result.buf = that;
74 : }
75 21 : return result;
76 : }
77 :
78 67350 : static inline utf8stringbuf_t utf8stringbuf_init( size_t size, char *buf )
79 : {
80 : utf8stringbuf_t result;
81 67350 : if (( buf == NULL )||(size==0))
82 : {
83 1 : result.size = 1;
84 1 : result.buf = utf8stringbuf_private_empty_buf;
85 : }
86 : else
87 : {
88 67349 : result.size = size;
89 67349 : result.buf = buf;
90 : }
91 67350 : return result;
92 : }
93 :
94 7648 : static inline void utf8stringbuf_clear( utf8stringbuf_t this_ )
95 : {
96 7648 : memset( this_.buf, '\0', this_.size );
97 7648 : }
98 :
99 28426 : static inline char* utf8stringbuf_get_string( const utf8stringbuf_t this_ )
100 : {
101 28426 : return this_.buf;
102 : }
103 :
104 1126 : static inline size_t utf8stringbuf_get_size( const utf8stringbuf_t this_ )
105 : {
106 1126 : return this_.size;
107 : }
108 :
109 13947 : static inline unsigned int utf8stringbuf_get_length( const utf8stringbuf_t this_ )
110 : {
111 : unsigned int lenResult;
112 13947 : lenResult = strlen( this_.buf );
113 13947 : return lenResult;
114 : }
115 :
116 1 : static inline utf8stringview_t utf8stringbuf_get_view( const utf8stringbuf_t this_ )
117 : {
118 : utf8stringview_t result;
119 1 : assert( NULL != this_.buf );
120 1 : const utf8error_t err = utf8stringview_init( &result, this_.buf, strlen( this_.buf ) );
121 1 : assert( UTF8ERROR_SUCCESS == err );
122 : (void) err; /* do not warn on unused value */
123 1 : return result;
124 : }
125 :
126 5144 : static inline int utf8stringbuf_equals_str( const utf8stringbuf_t this_, const char *that )
127 : {
128 5144 : int cmpResult = -1;
129 5144 : if ( that != NULL ) {
130 5142 : cmpResult = strcmp( this_.buf, that );
131 : }
132 5144 : return ( cmpResult == 0 ) ? UTF8STRINGBUF_TRUE : UTF8STRINGBUF_FALSE;
133 : }
134 :
135 : static inline int utf8stringbuf_equals_view( const utf8stringbuf_t this_, const utf8stringview_t *that )
136 : {
137 : assert( that != NULL );
138 : int result;
139 : const size_t len = utf8stringview_get_length( that );
140 : if ( len == utf8stringbuf_get_length(this_) )
141 : {
142 : if ( ( len == 0 )/*&&( this_.length == 0 )*/)
143 : {
144 : result = 1;
145 : }
146 : else
147 : {
148 : result = ( 0 == memcmp ( this_.buf, utf8stringview_get_start(that), len ) ) ? 1 : 0;
149 : }
150 : }
151 : else
152 : {
153 : result = 0;
154 : }
155 : return result;
156 : }
157 :
158 4 : static inline int utf8stringbuf_equals_buf( const utf8stringbuf_t this_, const utf8stringbuf_t that )
159 : {
160 4 : int cmpResult = -1;
161 4 : cmpResult = strcmp( this_.buf, that.buf );
162 4 : return ( cmpResult == 0 ) ? UTF8STRINGBUF_TRUE : UTF8STRINGBUF_FALSE;
163 : }
164 :
165 : #ifdef UTF8STRINGBUF_DEPRECATED_INDEX
166 : static inline int utf8stringbuf_equals_region_str( const utf8stringbuf_t this_, int start, const char *that )
167 : {
168 : int cmpResult = -1;
169 : if ( that != NULL ) {
170 : int thisLen = strlen(this_.buf);
171 : int thatLen = strlen(that);
172 : unsigned int end = ((unsigned int)start) + ((unsigned int)thatLen);
173 : if (( 0 <= start )&&( end <= thisLen )) {
174 : cmpResult = memcmp( &(this_.buf[start]), that, thatLen );
175 : }
176 : }
177 : return ( cmpResult == 0 ) ? UTF8STRINGBUF_TRUE : UTF8STRINGBUF_FALSE;
178 : }
179 : #endif /* UTF8STRINGBUF_DEPRECATED_INDEX */
180 :
181 : #ifdef UTF8STRINGBUF_DEPRECATED_INDEX
182 : static inline int utf8stringbuf_equals_region_buf( const utf8stringbuf_t this_, int start, const utf8stringbuf_t that )
183 : {
184 : int cmpResult = -1;
185 : int thisLen = strlen(this_.buf);
186 : int thatLen = strlen(that.buf);
187 : unsigned int end = ((unsigned int)start) + ((unsigned int)thatLen);
188 : if (( 0 <= start )&&( end <= thisLen )) {
189 : cmpResult = memcmp( &(this_.buf[start]), that.buf, thatLen );
190 : }
191 : return ( cmpResult == 0 ) ? UTF8STRINGBUF_TRUE : UTF8STRINGBUF_FALSE;
192 : }
193 : #endif /* UTF8STRINGBUF_DEPRECATED_INDEX */
194 :
195 : static inline int utf8stringbuf_find_first_buf( const utf8stringbuf_t this_, const utf8stringbuf_t pattern )
196 : {
197 : int result = UTF8STRINGBUF_NOT_FOUND;
198 : const char *ptrResult = strstr( this_.buf, pattern.buf );
199 : if ( ptrResult != NULL ) {
200 : result = (int) (ptrResult - this_.buf);
201 : }
202 : return result;
203 : }
204 :
205 11 : static inline int utf8stringbuf_starts_with_str( const utf8stringbuf_t this_, const char *that )
206 : {
207 11 : int cmpResult = -1;
208 11 : if ( that != NULL ) {
209 10 : unsigned int thatLen = strlen( that );
210 10 : cmpResult = strncmp( this_.buf, that, thatLen );
211 : }
212 11 : return ( cmpResult == 0 ) ? UTF8STRINGBUF_TRUE : UTF8STRINGBUF_FALSE;
213 : }
214 :
215 5 : static inline int utf8stringbuf_starts_with_buf( const utf8stringbuf_t this_, const utf8stringbuf_t that ) {
216 5 : int cmpResult = -1;
217 5 : unsigned int thatLen = strlen( that.buf );
218 5 : cmpResult = strncmp( this_.buf, that.buf, thatLen );
219 5 : return ( cmpResult == 0 ) ? UTF8STRINGBUF_TRUE : UTF8STRINGBUF_FALSE;
220 : }
221 :
222 6 : static inline int utf8stringbuf_ends_with_str( const utf8stringbuf_t this_, const char *that ) {
223 6 : int cmpResult = -1;
224 6 : if ( that != NULL ) {
225 5 : unsigned int thatLen = strlen( that );
226 5 : unsigned int thisLen = strlen( this_.buf );
227 5 : if ( thatLen <= thisLen ) {
228 4 : cmpResult = memcmp( &(this_.buf[thisLen-thatLen]), that, thatLen );
229 : }
230 : }
231 6 : return ( cmpResult == 0 ) ? UTF8STRINGBUF_TRUE : UTF8STRINGBUF_FALSE;
232 : }
233 :
234 5 : static inline int utf8stringbuf_ends_with_buf( const utf8stringbuf_t this_, const utf8stringbuf_t that ) {
235 5 : int cmpResult = -1;
236 5 : unsigned int thatLen = strlen( that.buf );
237 5 : unsigned int thisLen = strlen( this_.buf );
238 5 : if ( thatLen <= thisLen ) {
239 4 : cmpResult = memcmp( &(this_.buf[thisLen-thatLen]), that.buf, thatLen );
240 : }
241 5 : return ( cmpResult == 0 ) ? UTF8STRINGBUF_TRUE : UTF8STRINGBUF_FALSE;
242 : }
243 :
244 : #ifdef UTF8STRINGBUF_DEPRECATED_INDEX
245 : static inline int utf8stringbuf_find_first_str( const utf8stringbuf_t this_, const char *pattern ) {
246 : int result = UTF8STRINGBUF_NOT_FOUND;
247 : if ( pattern != NULL ) {
248 : const char *ptrResult = strstr( this_.buf, pattern );
249 : if ( ptrResult != NULL ) {
250 : result = (int) (ptrResult - this_.buf);
251 : }
252 : }
253 : return result;
254 : }
255 : #endif /* UTF8STRINGBUF_DEPRECATED_INDEX */
256 :
257 : #ifdef UTF8STRINGBUF_DEPRECATED_INDEX
258 : static inline int utf8stringbuf_find_last_buf( const utf8stringbuf_t this_, const utf8stringbuf_t pattern ) {
259 : int result = UTF8STRINGBUF_NOT_FOUND;
260 : int thisLen = utf8stringbuf_get_length( this_ );
261 : int patternLen = strlen( pattern.buf );
262 : if ( patternLen <= thisLen ) {
263 : for ( int probeIdx = (thisLen-patternLen); probeIdx >= 0; probeIdx --) {
264 : if ( 0 == memcmp( &(this_.buf[probeIdx]), pattern.buf, patternLen )) {
265 : /* last occurrence found! */
266 : result = probeIdx;
267 : break;
268 : }
269 : }
270 : }
271 : return result;
272 : }
273 : #endif /* UTF8STRINGBUF_DEPRECATED_INDEX */
274 :
275 : #ifdef UTF8STRINGBUF_DEPRECATED_INDEX
276 : static inline int utf8stringbuf_find_last_str( const utf8stringbuf_t this_, const char *pattern ) {
277 : int result = UTF8STRINGBUF_NOT_FOUND;
278 : if ( pattern != NULL ) {
279 : int thisLen = utf8stringbuf_get_length( this_ );
280 : int patternLen = strlen( pattern );
281 : if ( patternLen <= thisLen ) {
282 : for ( int probeIdx = (thisLen-patternLen); probeIdx >= 0; probeIdx --) {
283 : if ( 0 == memcmp( &(this_.buf[probeIdx]), pattern, patternLen )) {
284 : /* last occurrence found! */
285 : result = probeIdx;
286 : break;
287 : }
288 : }
289 : }
290 : }
291 : return result;
292 : }
293 : #endif /* UTF8STRINGBUF_DEPRECATED_INDEX */
294 :
295 : #ifdef UTF8STRINGBUF_DEPRECATED_INDEX
296 : static inline int utf8stringbuf_find_next_buf( const utf8stringbuf_t this_, const utf8stringbuf_t pattern, int start_index ) {
297 : int result = UTF8STRINGBUF_NOT_FOUND;
298 : if (( start_index >= 0 ) && ( start_index < this_.size )) {
299 : const char *ptrResult = strstr( &(this_.buf[start_index]), pattern.buf );
300 : if ( ptrResult != NULL ) {
301 : result = (int) (ptrResult - this_.buf);
302 : }
303 : }
304 : return result;
305 : }
306 : #endif /* UTF8STRINGBUF_DEPRECATED_INDEX */
307 :
308 : #ifdef UTF8STRINGBUF_DEPRECATED_INDEX
309 : static inline int utf8stringbuf_find_next_str( const utf8stringbuf_t this_, const char *pattern, int start_index ) {
310 : int result = UTF8STRINGBUF_NOT_FOUND;
311 : if (( pattern != NULL ) && ( start_index >= 0 ) && ( start_index < this_.size )) {
312 : const char *ptrResult = strstr( &(this_.buf[start_index]), pattern );
313 : if ( ptrResult != NULL ) {
314 : result = (int) (ptrResult - this_.buf);
315 : }
316 : }
317 : return result;
318 : }
319 : #endif /* UTF8STRINGBUF_DEPRECATED_INDEX */
320 :
321 : #ifdef UTF8STRINGBUF_DEPRECATED_INDEX
322 : static inline utf8codepoint_t utf8stringbuf_get_char_at( const utf8stringbuf_t this_, unsigned int byte_index ) {
323 : utf8codepoint_t result = UTF8CODEPOINT_INVAL_CHAR;
324 : if ( byte_index < this_.size ) {
325 : result = utf8codepoint_init( &(this_.buf[byte_index]), this_.size-byte_index );
326 : }
327 : return result;
328 : }
329 : #endif /* UTF8STRINGBUF_DEPRECATED_INDEX */
330 :
331 4 : static inline utf8error_t utf8stringbuf_copy_buf( utf8stringbuf_t this_, const utf8stringbuf_t original ) {
332 4 : utf8error_t complete = UTF8ERROR_SUCCESS;
333 : #if __GNUC__ >= 8
334 : #pragma GCC diagnostic push
335 : #pragma GCC diagnostic ignored "-Wstringop-truncation"
336 : #endif
337 4 : strncpy( this_.buf, original.buf, this_.size );
338 : #if __GNUC__ >= 8
339 : #pragma GCC diagnostic pop
340 : #endif
341 4 : if ( this_.buf[this_.size-1] != '\0' ) {
342 2 : utf8_string_buf_private_make_null_termination( this_ );
343 2 : complete = UTF8ERROR_TRUNCATED;
344 : }
345 4 : return complete;
346 : }
347 :
348 58612 : static inline utf8error_t utf8stringbuf_copy_str( utf8stringbuf_t this_, const char *original ) {
349 58612 : utf8error_t complete = UTF8ERROR_SUCCESS;
350 58612 : if ( original == NULL ) {
351 1 : this_.buf[0] = '\0';
352 1 : complete = UTF8ERROR_NULL_PARAM;
353 : }
354 : else {
355 : #if __GNUC__ >= 8
356 : #pragma GCC diagnostic push
357 : #pragma GCC diagnostic ignored "-Wstringop-truncation"
358 : #endif
359 58611 : strncpy( this_.buf, original, this_.size );
360 : #if __GNUC__ >= 8
361 : #pragma GCC diagnostic pop
362 : #endif
363 58611 : if ( this_.buf[this_.size-1] != '\0' ) {
364 63 : utf8_string_buf_private_make_null_termination( this_ );
365 63 : complete = UTF8ERROR_TRUNCATED;
366 : }
367 : }
368 58612 : return complete;
369 : }
370 :
371 35 : static inline utf8error_t utf8stringbuf_copy_view( utf8stringbuf_t this_, const utf8stringview_t *original )
372 : {
373 35 : assert( original != NULL );
374 35 : utf8error_t result = UTF8ERROR_SUCCESS;
375 :
376 35 : const size_t origLen = utf8stringview_get_length( original );
377 35 : if ( origLen < this_.size ) {
378 33 : memcpy( &(this_.buf[0]), utf8stringview_get_start( original ), origLen );
379 33 : this_.buf[origLen] = '\0';
380 : }
381 : else {
382 2 : if ( this_.size > 0 )
383 : {
384 2 : memcpy( &(this_.buf[0]), utf8stringview_get_start( original ), (this_.size-1) );
385 : }
386 : else
387 : {
388 : /* buffer non-existant */
389 : }
390 2 : utf8_string_buf_private_make_null_termination( this_ );
391 2 : result = UTF8ERROR_TRUNCATED;
392 : }
393 :
394 35 : return result;
395 : }
396 :
397 2 : static inline utf8error_t utf8stringbuf_replace_all_str_by_str( const utf8stringbuf_t this_, const char *pattern, const char *replacement ) {
398 2 : utf8error_t result = UTF8ERROR_NULL_PARAM;
399 2 : if ( pattern != NULL ) {
400 1 : const char *const patterns_and_replacements[][2] = { { pattern, replacement }, { NULL, NULL } };
401 1 : result = utf8stringbuf_replace_all( this_, &patterns_and_replacements );
402 : }
403 2 : return result;
404 : }
405 :
406 : #ifdef UTF8STRINGBUF_DEPRECATED_INPLACE
407 : static inline utf8error_t utf8stringbuf_replace_all_buf_by_buf( const utf8stringbuf_t this_, const utf8stringbuf_t pattern, const utf8stringbuf_t replacement ) {
408 : const char *const patterns_and_replacements[][2] = { { pattern.buf, replacement.buf }, { NULL, NULL } };
409 : return utf8stringbuf_replace_all( this_, &patterns_and_replacements );
410 : }
411 : #endif /* UTF8STRINGBUF_DEPRECATED_INPLACE */
412 :
413 19089 : static inline utf8error_t utf8stringbuf_append_str( utf8stringbuf_t this_, const char *appendix ) {
414 19089 : utf8error_t result = UTF8ERROR_SUCCESS;
415 19089 : if ( appendix == NULL ) {
416 1 : result = UTF8ERROR_NULL_PARAM;
417 : }
418 : else {
419 19088 : const size_t start = strlen( this_.buf );
420 :
421 19088 : const size_t appLen = strlen( appendix );
422 19088 : if ( start + appLen < this_.size ) {
423 : /* gcc does not reliably evaluate the if condition above */
424 : #if __GNUC__ >= 8
425 : #pragma GCC diagnostic push
426 : #pragma GCC diagnostic ignored "-Wstringop-overflow"
427 : #endif
428 19074 : memcpy( &(this_.buf[start]), appendix, appLen+1 );
429 : #if __GNUC__ >= 8
430 : #pragma GCC diagnostic pop
431 : #endif
432 : }
433 : else {
434 14 : const size_t appPartLen = (this_.size-start)-1;
435 14 : if (( appPartLen > 0 )&&( appPartLen <= PTRDIFF_MAX )) /* check to suppress compiler warning */
436 : {
437 13 : memcpy( &(this_.buf[start]), appendix, appPartLen );
438 : }
439 : else
440 : {
441 : /* buffer full */
442 : }
443 14 : utf8_string_buf_private_make_null_termination( this_ );
444 14 : result = UTF8ERROR_TRUNCATED;
445 : }
446 :
447 : /* For the standard use case, strlen and memcpy are faster than strncpy; strncat does not provide an error */
448 : }
449 19089 : return result;
450 : }
451 :
452 3 : static inline utf8error_t utf8stringbuf_append_buf( utf8stringbuf_t this_, const utf8stringbuf_t appendix ) {
453 3 : utf8error_t result = UTF8ERROR_SUCCESS;
454 3 : const size_t start = strlen( this_.buf );
455 :
456 3 : const size_t appLen = strlen( appendix.buf );
457 3 : if ( start + appLen < this_.size ) {
458 1 : memcpy( &(this_.buf[start]), appendix.buf, appLen+1 );
459 : }
460 : else {
461 2 : const size_t appPartLen = (this_.size-start)-1;
462 2 : if (( appPartLen > 0 )&&( appPartLen <= PTRDIFF_MAX )) /* check to suppress compiler warning */
463 : {
464 1 : memcpy( &(this_.buf[start]), appendix.buf, appPartLen );
465 : }
466 : else
467 : {
468 : /* buffer full */
469 : }
470 2 : utf8_string_buf_private_make_null_termination( this_ );
471 2 : result = UTF8ERROR_TRUNCATED;
472 : }
473 :
474 : /* For the standard use case, strlen and memcpy are faster than strncpy; strncat does not provide an error */
475 3 : return result;
476 : }
477 :
478 5088 : static inline utf8error_t utf8stringbuf_append_int( utf8stringbuf_t this_, const int64_t appendix ) {
479 : char numberStr[21]; /* this is sufficient for signed 64 bit integers: -9223372036854775806 */
480 : /* Note: snprintf is not available on every OS */
481 5088 : sprintf( numberStr, utf8stringbuf_private_format_signed_64_bit_int, appendix );
482 5088 : return utf8stringbuf_append_str( this_, numberStr );
483 : }
484 :
485 3 : static inline utf8error_t utf8stringbuf_append_hex( utf8stringbuf_t this_, const uint64_t appendix ) {
486 : char numberStr[17]; /* this is sufficient for 64 bit integers */
487 : /* Note: snprintf is not available on every OS */
488 3 : sprintf( numberStr, utf8stringbuf_private_format_64_bit_hex, appendix );
489 3 : return utf8stringbuf_append_str( this_, numberStr );
490 : }
491 :
492 : #ifdef UTF8STRINGBUF_UNCHECKED_RANGE
493 : static inline utf8error_t utf8stringbuf_replace_region_by_str( utf8stringbuf_t this_, int start, int length, const char *replacement ) {
494 : unsigned int this_Length = utf8stringbuf_get_length( this_ );
495 : return utf8_string_buf_private_replace_region_by_str( this_, this_Length, start, length, replacement );
496 : }
497 : #endif /* UTF8STRINGBUF_UNCHECKED_RANGE */
498 :
499 : #ifdef UTF8STRINGBUF_UNCHECKED_RANGE
500 : static inline utf8error_t utf8stringbuf_replace_region_by_buf( utf8stringbuf_t this_, int start, int length, const utf8stringbuf_t replacement ) {
501 : unsigned int this_Length = utf8stringbuf_get_length( this_ );
502 : return utf8_string_buf_private_replace_region_by_str( this_, this_Length, start, length, replacement.buf );
503 : }
504 : #endif /* UTF8STRINGBUF_UNCHECKED_RANGE */
505 :
506 : #ifdef UTF8STRINGBUF_UNCHECKED_RANGE
507 : static inline utf8error_t utf8stringbuf_delete( utf8stringbuf_t this_, int start, int length ) {
508 : unsigned int this_Length = utf8stringbuf_get_length( this_ );
509 : return utf8_string_buf_private_replace_region_by_str( this_, this_Length, start, length, NULL );
510 : }
511 : #endif /* UTF8STRINGBUF_UNCHECKED_RANGE */
512 :
513 : #ifdef UTF8STRINGBUF_UNCHECKED_RANGE
514 : static inline utf8error_t utf8stringbuf_delete_from_end( utf8stringbuf_t this_, int length ) {
515 : int this_Length = utf8stringbuf_get_length( this_ );
516 : return utf8_string_buf_private_replace_region_by_str( this_, this_Length, this_Length-length, length, NULL );
517 : }
518 : #endif /* UTF8STRINGBUF_UNCHECKED_RANGE */
519 :
520 : #ifdef UTF8STRINGBUF_UNCHECKED_RANGE
521 : static inline utf8error_t utf8stringbuf_delete_to_end( utf8stringbuf_t this_, int start ) {
522 : int this_Length = utf8stringbuf_get_length( this_ );
523 : return utf8_string_buf_private_replace_region_by_str( this_, this_Length, start, this_Length-start, NULL );
524 : }
525 : #endif /* UTF8STRINGBUF_UNCHECKED_RANGE */
526 :
527 : #ifdef UTF8STRINGBUF_UNCHECKED_RANGE
528 : static inline utf8error_t utf8stringbuf_insert_str( utf8stringbuf_t this_, int start, const char *insert ) {
529 : unsigned int this_Length = utf8stringbuf_get_length( this_ );
530 : return utf8_string_buf_private_replace_region_by_str( this_, this_Length, start, 0, insert );
531 : }
532 : #endif /* UTF8STRINGBUF_UNCHECKED_RANGE */
533 :
534 : #ifdef UTF8STRINGBUF_UNCHECKED_RANGE
535 : static inline utf8error_t utf8stringbuf_insert_buf( utf8stringbuf_t this_, int start, const utf8stringbuf_t insert ) {
536 : unsigned int this_Length = utf8stringbuf_get_length( this_ );
537 : return utf8_string_buf_private_replace_region_by_str( this_, this_Length, start, 0, insert.buf );
538 : }
539 : #endif /* UTF8STRINGBUF_UNCHECKED_RANGE */
540 :
541 61 : static inline utf8stringbuf_t utf8stringbuf_get_end( utf8stringbuf_t this_ ) {
542 61 : unsigned int this_Length = utf8stringbuf_get_length( this_ );
543 61 : return utf8stringbuf_init( this_.size-this_Length, &(this_.buf[this_Length]) );
544 : }
545 :
546 6 : static inline utf8error_t utf8stringbuf_append_view( utf8stringbuf_t this_, const utf8stringview_t *appendix )
547 : {
548 6 : assert( appendix != NULL );
549 6 : utf8error_t result = UTF8ERROR_SUCCESS;
550 6 : const size_t start = strlen( this_.buf );
551 :
552 6 : const size_t appLen = utf8stringview_get_length( appendix );
553 6 : if ( start + appLen < this_.size ) {
554 4 : memcpy( &(this_.buf[start]), utf8stringview_get_start( appendix ), appLen );
555 4 : this_.buf[start+appLen] = '\0';
556 : }
557 : else {
558 2 : const size_t appPartLen = (this_.size-start)-1;
559 2 : if (( appPartLen > 0 )&&( appPartLen <= PTRDIFF_MAX )) /* check to suppress compiler warning */
560 : {
561 1 : memcpy( &(this_.buf[start]), utf8stringview_get_start( appendix ), appPartLen );
562 : }
563 : else
564 : {
565 : /* buffer full */
566 : }
567 2 : utf8_string_buf_private_make_null_termination( this_ );
568 2 : result = UTF8ERROR_TRUNCATED;
569 : }
570 :
571 6 : return result;
572 : }
573 :
574 : #ifdef __cplusplus
575 : }
576 : #endif
577 :
578 :
579 : /*
580 : * Copyright 2012-2024 Andreas Warnke
581 : *
582 : * Licensed under the Apache License, Version 2.0 (the "License");
583 : * you may not use this file except in compliance with the License.
584 : * You may obtain a copy of the License at
585 : *
586 : * http://www.apache.org/licenses/LICENSE-2.0
587 : *
588 : * Unless required by applicable law or agreed to in writing, software
589 : * distributed under the License is distributed on an "AS IS" BASIS,
590 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
591 : * See the License for the specific language governing permissions and
592 : * limitations under the License.
593 : */
|