xref: /haiku/headers/libs/zydis/Zycore/String.h (revision 9a6a20d4689307142a7ed26a1437ba47e244e73f)
1 /***************************************************************************************************
2 
3   Zyan Core Library (Zycore-C)
4 
5   Original Author : Florian Bernd
6 
7  * Permission is hereby granted, free of charge, to any person obtaining a copy
8  * of this software and associated documentation files (the "Software"), to deal
9  * in the Software without restriction, including without limitation the rights
10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11  * copies of the Software, and to permit persons to whom the Software is
12  * furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in all
15  * copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23  * SOFTWARE.
24 
25 ***************************************************************************************************/
26 
27 /**
28  * @file
29  * Implements a string type.
30  */
31 
32 #ifndef ZYCORE_STRING_H
33 #define ZYCORE_STRING_H
34 
35 #include <Zycore/Allocator.h>
36 #include <Zycore/Status.h>
37 #include <Zycore/Types.h>
38 #include <Zycore/Vector.h>
39 
40 #ifdef __cplusplus
41 extern "C" {
42 #endif
43 
44 /* ============================================================================================== */
45 /* Constants                                                                                      */
46 /* ============================================================================================== */
47 
48 /**
49  * The initial minimum capacity (number of characters) for all dynamically allocated
50  * string instances - not including the terminating '\0'-character.
51  */
52 #define ZYAN_STRING_MIN_CAPACITY                32
53 
54 /**
55  * The default growth factor for all string instances.
56  */
57 #define ZYAN_STRING_DEFAULT_GROWTH_FACTOR       2
58 
59 /**
60  * The default shrink threshold for all string instances.
61  */
62 #define ZYAN_STRING_DEFAULT_SHRINK_THRESHOLD    4
63 
64 /* ============================================================================================== */
65 /* Enums and types                                                                                */
66 /* ============================================================================================== */
67 
68 /* ---------------------------------------------------------------------------------------------- */
69 /* String flags                                                                                   */
70 /* ---------------------------------------------------------------------------------------------- */
71 
72 /**
73  * Defines the `ZyanStringFlags` data-type.
74  */
75 typedef ZyanU8 ZyanStringFlags;
76 
77 /**
78  * The string uses a custom user-defined buffer with a fixed capacity.
79  */
80 #define ZYAN_STRING_HAS_FIXED_CAPACITY  0x01 // (1 << 0)
81 
82 /* ---------------------------------------------------------------------------------------------- */
83 /* String                                                                                         */
84 /* ---------------------------------------------------------------------------------------------- */
85 
86 /**
87  * Defines the `ZyanString` struct.
88  *
89  * The `ZyanString` type is implemented as a size-prefixed string - which allows for a lot of
90  * performance optimizations.
91  * Nevertheless null-termination is guaranteed at all times to provide maximum compatibility with
92  * default C-style strings (use `ZyanStringGetData` to access the C-style string).
93  *
94  * All fields in this struct should be considered as "private". Any changes may lead to unexpected
95  * behavior.
96  */
97 typedef struct ZyanString_
98 {
99     /**
100      * String flags.
101      */
102     ZyanStringFlags flags;
103     /**
104      * The vector that contains the actual string.
105      */
106     ZyanVector vector;
107 } ZyanString;
108 
109 /* ---------------------------------------------------------------------------------------------- */
110 /* View                                                                                           */
111 /* ---------------------------------------------------------------------------------------------- */
112 
113 /**
114  * Defines the `ZyanStringView` struct.
115  *
116  * The `ZyanStringView` type provides a view inside a string (`ZyanString` instances, null-
117  * terminated C-style strings, or even not-null-terminated custom strings). A view is immutable
118  * by design and can't be directly converted to a C-style string.
119  *
120  * Views might become invalid (e.g. pointing to invalid memory), if the underlying string gets
121  * destroyed or resized.
122  *
123  * The `ZYAN_STRING_TO_VIEW` macro can be used to cast a `ZyanString` to a `ZyanStringView` pointer
124  * without any runtime overhead.
125  * Casting a view to a normal string is not supported and will lead to unexpected behavior (use
126  * `ZyanStringDuplicate` to create a deep-copy instead).
127  *
128  * All fields in this struct should be considered as "private". Any changes may lead to unexpected
129  * behavior.
130  */
131 typedef struct ZyanStringView_
132 {
133     /**
134      * The string data.
135      *
136      * The view internally re-uses the normal string struct to allow casts without any runtime
137      * overhead.
138      */
139     ZyanString string;
140 } ZyanStringView;
141 
142 /* ---------------------------------------------------------------------------------------------- */
143 
144 /* ============================================================================================== */
145 /* Macros                                                                                         */
146 /* ============================================================================================== */
147 
148 /* ---------------------------------------------------------------------------------------------- */
149 /* General                                                                                        */
150 /* ---------------------------------------------------------------------------------------------- */
151 
152 /**
153  * Defines an uninitialized `ZyanString` instance.
154  */
155 #define ZYAN_STRING_INITIALIZER \
156     { \
157         /* flags  */ 0, \
158         /* vector */ ZYAN_VECTOR_INITIALIZER \
159     }
160 
161 /* ---------------------------------------------------------------------------------------------- */
162 /* Helper macros                                                                                  */
163 /* ---------------------------------------------------------------------------------------------- */
164 
165 /**
166  * Casts a `ZyanString` pointer to a constant `ZyanStringView` pointer.
167  */
168 #define ZYAN_STRING_TO_VIEW(string) (const ZyanStringView*)(string)
169 
170 /**
171  * Defines a `ZyanStringView` struct that provides a view into a static C-style string.
172  *
173  * @param   string  The C-style string.
174  */
175 #define ZYAN_DEFINE_STRING_VIEW(string) \
176     { \
177         /* string */ \
178         { \
179             /* flags  */ 0, \
180             /* vector */ \
181             { \
182                 /* allocator        */ ZYAN_NULL, \
183                 /* growth_factor    */ 1, \
184                 /* shrink_threshold */ 0, \
185                 /* size             */ sizeof(string), \
186                 /* capacity         */ sizeof(string), \
187                 /* element_size     */ sizeof(char), \
188                 /* destructor       */ ZYAN_NULL, \
189                 /* data             */ (char*)(string) \
190             } \
191         } \
192     }
193 
194 /* ---------------------------------------------------------------------------------------------- */
195 
196 /* ============================================================================================== */
197 /* Exported functions                                                                             */
198 /* ============================================================================================== */
199 
200 /* ---------------------------------------------------------------------------------------------- */
201 /* Constructor and destructor                                                                     */
202 /* ---------------------------------------------------------------------------------------------- */
203 
204 #ifndef ZYAN_NO_LIBC
205 
206 /**
207  * Initializes the given `ZyanString` instance.
208  *
209  * @param   string          A pointer to the `ZyanString` instance.
210  * @param   capacity        The initial capacity (number of characters).
211  *
212  * @return  A zyan status code.
213  *
214  * The memory for the string is dynamically allocated by the default allocator using the default
215  * growth factor and the default shrink threshold.
216  *
217  * The allocated buffer will be at least one character larger than the given `capacity`, to reserve
218  * space for the terminating '\0'.
219  *
220  * Finalization with `ZyanStringDestroy` is required for all strings created by this function.
221  */
222 ZYCORE_EXPORT ZYAN_REQUIRES_LIBC ZyanStatus ZyanStringInit(ZyanString* string, ZyanUSize capacity);
223 
224 #endif // ZYAN_NO_LIBC
225 
226 /**
227  * Initializes the given `ZyanString` instance and sets a custom `allocator` and memory
228  * allocation/deallocation parameters.
229  *
230  * @param   string              A pointer to the `ZyanString` instance.
231  * @param   capacity            The initial capacity (number of characters).
232  * @param   allocator           A pointer to a `ZyanAllocator` instance.
233  * @param   growth_factor       The growth factor.
234  * @param   shrink_threshold    The shrink threshold.
235  *
236  * @return  A zyan status code.
237  *
238  * A growth factor of `1` disables overallocation and a shrink threshold of `0` disables
239  * dynamic shrinking.
240  *
241  * The allocated buffer will be at least one character larger than the given `capacity`, to reserve
242  * space for the terminating '\0'.
243  *
244  * Finalization with `ZyanStringDestroy` is required for all strings created by this function.
245  */
246 ZYCORE_EXPORT ZyanStatus ZyanStringInitEx(ZyanString* string, ZyanUSize capacity,
247     ZyanAllocator* allocator, ZyanU8 growth_factor, ZyanU8 shrink_threshold);
248 
249 /**
250  * Initializes the given `ZyanString` instance and configures it to use a custom user
251  * defined buffer with a fixed size.
252  *
253  * @param   string          A pointer to the `ZyanString` instance.
254  * @param   buffer          A pointer to the buffer that is used as storage for the string.
255  * @param   capacity        The maximum capacity (number of characters) of the buffer, including
256  *                          the terminating '\0'.
257  *
258  * @return  A zyan status code.
259  *
260  * Finalization is not required for strings created by this function.
261  */
262 ZYCORE_EXPORT ZyanStatus ZyanStringInitCustomBuffer(ZyanString* string, char* buffer,
263     ZyanUSize capacity);
264 
265 /**
266  * Destroys the given `ZyanString` instance.
267  *
268  * @param   string  A pointer to the `ZyanString` instance.
269  *
270  * @return  A zyan status code.
271  *
272  */
273 ZYCORE_EXPORT ZyanStatus ZyanStringDestroy(ZyanString* string);
274 
275 /* ---------------------------------------------------------------------------------------------- */
276 /* Duplication                                                                                    */
277 /* ---------------------------------------------------------------------------------------------- */
278 
279 #ifndef ZYAN_NO_LIBC
280 
281 /**
282  * Initializes a new `ZyanString` instance by duplicating an existing string.
283  *
284  * @param   destination A pointer to the (uninitialized) destination `ZyanString` instance.
285  * @param   source      A pointer to the source string.
286  * @param   capacity    The initial capacity (number of characters).
287  *
288  *                      This value is automatically adjusted to the size of the source string, if
289  *                      a smaller value was passed.
290  *
291  * @return  A zyan status code.
292  *
293  * The behavior of this function is undefined, if `source` is a view into the `destination`
294  * string or `destination` points to an already initialized `ZyanString` instance.
295  *
296  * The memory for the string is dynamically allocated by the default allocator using the default
297  * growth factor and the default shrink threshold.
298  *
299  * The allocated buffer will be at least one character larger than the given `capacity`, to reserve
300  * space for the terminating '\0'.
301  *
302  * Finalization with `ZyanStringDestroy` is required for all strings created by this function.
303  */
304 ZYCORE_EXPORT ZYAN_REQUIRES_LIBC ZyanStatus ZyanStringDuplicate(ZyanString* destination,
305     const ZyanStringView* source, ZyanUSize capacity);
306 
307 #endif // ZYAN_NO_LIBC
308 
309 /**
310  * Initializes a new `ZyanString` instance by duplicating an existing string and sets a
311  * custom `allocator` and memory allocation/deallocation parameters.
312  *
313  * @param   destination         A pointer to the (uninitialized) destination `ZyanString` instance.
314  * @param   source              A pointer to the source string.
315  * @param   capacity            The initial capacity (number of characters).
316 
317  *                              This value is automatically adjusted to the size of the source
318  *                              string, if a smaller value was passed.
319  * @param   allocator           A pointer to a `ZyanAllocator` instance.
320  * @param   growth_factor       The growth factor.
321  * @param   shrink_threshold    The shrink threshold.
322  *
323  * @return  A zyan status code.
324  *
325  * The behavior of this function is undefined, if `source` is a view into the `destination`
326  * string or `destination` points to an already initialized `ZyanString` instance.
327  *
328  * A growth factor of `1` disables overallocation and a shrink threshold of `0` disables
329  * dynamic shrinking.
330  *
331  * The allocated buffer will be at least one character larger than the given `capacity`, to reserve
332  * space for the terminating '\0'.
333  *
334  * Finalization with `ZyanStringDestroy` is required for all strings created by this function.
335  */
336 ZYCORE_EXPORT ZyanStatus ZyanStringDuplicateEx(ZyanString* destination,
337     const ZyanStringView* source, ZyanUSize capacity, ZyanAllocator* allocator,
338     ZyanU8 growth_factor, ZyanU8 shrink_threshold);
339 
340 /**
341  * Initializes a new `ZyanString` instance by duplicating an existing string and
342  * configures it to use a custom user defined buffer with a fixed size.
343  *
344  * @param   destination A pointer to the (uninitialized) destination `ZyanString` instance.
345  * @param   source      A pointer to the source string.
346  * @param   buffer      A pointer to the buffer that is used as storage for the string.
347  * @param   capacity    The maximum capacity (number of characters) of the buffer, including the
348  *                      terminating '\0'.
349 
350  *                      This function will fail, if the capacity of the buffer is less or equal to
351  *                      the size of the source string.
352  *
353  * @return  A zyan status code.
354  *
355  * The behavior of this function is undefined, if `source` is a view into the `destination`
356  * string or `destination` points to an already initialized `ZyanString` instance.
357  *
358  * Finalization is not required for strings created by this function.
359  */
360 ZYCORE_EXPORT ZyanStatus ZyanStringDuplicateCustomBuffer(ZyanString* destination,
361     const ZyanStringView* source, char* buffer, ZyanUSize capacity);
362 
363 /* ---------------------------------------------------------------------------------------------- */
364 /* Concatenation                                                                                  */
365 /* ---------------------------------------------------------------------------------------------- */
366 
367 #ifndef ZYAN_NO_LIBC
368 
369 /**
370  * Initializes a new `ZyanString` instance by concatenating two existing strings.
371  *
372  * @param   destination A pointer to the (uninitialized) destination `ZyanString` instance.
373  *
374  *                      This function will fail, if the destination `ZyanString` instance equals
375  *                      one of the source strings.
376  * @param   s1          A pointer to the first source string.
377  * @param   s2          A pointer to the second source string.
378  * @param   capacity    The initial capacity (number of characters).
379 
380  *                      This value is automatically adjusted to the combined size of the source
381  *                      strings, if a smaller value was passed.
382  *
383  * @return  A zyan status code.
384  *
385  * The behavior of this function is undefined, if `s1` or `s2` are views into the `destination`
386  * string or `destination` points to an already initialized `ZyanString` instance.
387  *
388  * The memory for the string is dynamically allocated by the default allocator using the default
389  * growth factor and the default shrink threshold.
390  *
391  * The allocated buffer will be at least one character larger than the given `capacity`, to reserve
392  * space for the terminating '\0'.
393  *
394  * Finalization with `ZyanStringDestroy` is required for all strings created by this function.
395  */
396 ZYCORE_EXPORT ZYAN_REQUIRES_LIBC ZyanStatus ZyanStringConcat(ZyanString* destination,
397     const ZyanStringView* s1, const ZyanStringView* s2, ZyanUSize capacity);
398 
399 #endif // ZYAN_NO_LIBC
400 
401 /**
402  * Initializes a new `ZyanString` instance by concatenating two existing strings and sets
403  * a custom `allocator` and memory allocation/deallocation parameters.
404  *
405  * @param   destination         A pointer to the (uninitialized) destination `ZyanString` instance.
406  *
407  *                              This function will fail, if the destination `ZyanString` instance
408  *                              equals one of the source strings.
409  * @param   s1                  A pointer to the first source string.
410  * @param   s2                  A pointer to the second source string.
411  * @param   capacity            The initial capacity (number of characters).
412  *
413  *                              This value is automatically adjusted to the combined size of the
414  *                              source strings, if a smaller value was passed.
415  * @param   allocator           A pointer to a `ZyanAllocator` instance.
416  * @param   growth_factor       The growth factor.
417  * @param   shrink_threshold    The shrink threshold.
418  *
419  * @return  A zyan status code.
420  *
421  * The behavior of this function is undefined, if `s1` or `s2` are views into the `destination`
422  * string or `destination` points to an already initialized `ZyanString` instance.
423  *
424  * A growth factor of `1` disables overallocation and a shrink threshold of `0` disables
425  * dynamic shrinking.
426  *
427  * The allocated buffer will be at least one character larger than the given `capacity`, to reserve
428  * space for the terminating '\0'.
429  *
430  * Finalization with `ZyanStringDestroy` is required for all strings created by this function.
431  */
432 ZYCORE_EXPORT ZyanStatus ZyanStringConcatEx(ZyanString* destination, const ZyanStringView* s1,
433     const ZyanStringView* s2, ZyanUSize capacity, ZyanAllocator* allocator, ZyanU8 growth_factor,
434     ZyanU8 shrink_threshold);
435 
436 /**
437  * Initializes a new `ZyanString` instance by concatenating two existing strings and
438  * configures it to use a custom user defined buffer with a fixed size.
439  *
440  * @param   destination A pointer to the (uninitialized) destination `ZyanString` instance.
441  *
442  *                      This function will fail, if the destination `ZyanString` instance equals
443  *                      one of the source strings.
444  * @param   s1          A pointer to the first source string.
445  * @param   s2          A pointer to the second source string.
446  * @param   buffer      A pointer to the buffer that is used as storage for the string.
447  * @param   capacity    The maximum capacity (number of characters) of the buffer.
448  *
449  *                      This function will fail, if the capacity of the buffer is less or equal to
450  *                      the combined size of the source strings.
451  *
452  * @return  A zyan status code.
453  *
454  * The behavior of this function is undefined, if `s1` or `s2` are views into the `destination`
455  * string or `destination` points to an already initialized `ZyanString` instance.
456  *
457  * Finalization is not required for strings created by this function.
458  */
459 ZYCORE_EXPORT ZyanStatus ZyanStringConcatCustomBuffer(ZyanString* destination,
460     const ZyanStringView* s1, const ZyanStringView* s2, char* buffer, ZyanUSize capacity);
461 
462 /* ---------------------------------------------------------------------------------------------- */
463 /* Views                                                                                          */
464 /* ---------------------------------------------------------------------------------------------- */
465 
466 /**
467  * Returns a view inside an existing view/string.
468  *
469  * @param   view    A pointer to the `ZyanStringView` instance.
470  * @param   source  A pointer to the source string.
471  *
472  * @return  A zyan status code.
473  *
474  * The `ZYAN_STRING_TO_VEW` macro can be used to pass any `ZyanString` instance as value for the
475  * `source` string.
476  */
477 ZYCORE_EXPORT ZyanStatus ZyanStringViewInsideView(ZyanStringView* view,
478     const ZyanStringView* source);
479 
480 /**
481  * Returns a view inside an existing view/string starting from the given `index`.
482  *
483  * @param   view    A pointer to the `ZyanStringView` instance.
484  * @param   source  A pointer to the source string.
485  * @param   index   The start index.
486  * @param   count   The number of characters.
487  *
488  * @return  A zyan status code.
489  *
490  * The `ZYAN_STRING_TO_VEW` macro can be used to pass any `ZyanString` instance as value for the
491  * `source` string.
492  */
493 ZYCORE_EXPORT ZyanStatus ZyanStringViewInsideViewEx(ZyanStringView* view,
494     const ZyanStringView* source, ZyanUSize index, ZyanUSize count);
495 
496 /**
497  * Returns a view inside a null-terminated C-style string.
498  *
499  * @param   view    A pointer to the `ZyanStringView` instance.
500  * @param   string  The C-style string.
501  *
502  * @return  A zyan status code.
503  */
504 ZYCORE_EXPORT ZyanStatus ZyanStringViewInsideBuffer(ZyanStringView* view, const char* string);
505 
506 /**
507  * Returns a view inside a character buffer with custom length.
508  *
509  * @param   view    A pointer to the `ZyanStringView` instance.
510  * @param   buffer  A pointer to the buffer containing the string characters.
511  * @param   length  The length of the string (number of characters).
512  *
513  * @return  A zyan status code.
514  */
515 ZYCORE_EXPORT ZyanStatus ZyanStringViewInsideBufferEx(ZyanStringView* view, const char* buffer,
516     ZyanUSize length);
517 
518 /**
519  * Returns the size (number of characters) of the view.
520  *
521  * @param   view    A pointer to the `ZyanStringView` instance.
522  * @param   size    Receives the size (number of characters) of the view.
523  *
524  * @return  A zyan status code.
525  */
526 ZYCORE_EXPORT ZyanStatus ZyanStringViewGetSize(const ZyanStringView* view, ZyanUSize* size);
527 
528 /**
529  * Returns the C-style string of the given `ZyanString` instance.
530  *
531  * @warning The string is not guaranteed to be null terminated!
532  *
533  * @param   view    A pointer to the `ZyanStringView` instance.
534  * @param   buffer  Receives a pointer to the C-style string.
535  *
536  * @return  A zyan status code.
537  */
538 ZYCORE_EXPORT ZyanStatus ZyanStringViewGetData(const ZyanStringView* view, const char** buffer);
539 
540 /* ---------------------------------------------------------------------------------------------- */
541 /* Character access                                                                               */
542 /* ---------------------------------------------------------------------------------------------- */
543 
544 /**
545  * Returns the character at the given `index`.
546  *
547  * @param   string  A pointer to the `ZyanStringView` instance.
548  * @param   index   The character index.
549  * @param   value   Receives the desired character of the string.
550  *
551  * @return  A zyan status code.
552  */
553 ZYCORE_EXPORT ZyanStatus ZyanStringGetChar(const ZyanStringView* string, ZyanUSize index,
554     char* value);
555 
556 /**
557  * Returns a pointer to the character at the given `index`.
558  *
559  * @param   string  A pointer to the `ZyanString` instance.
560  * @param   index   The character index.
561  * @param   value   Receives a pointer to the desired character in the string.
562  *
563  * @return  A zyan status code.
564  */
565 ZYCORE_EXPORT ZyanStatus ZyanStringGetCharMutable(ZyanString* string, ZyanUSize index,
566     char** value);
567 
568 /**
569  * Assigns a new value to the character at the given `index`.
570  *
571  * @param   string  A pointer to the `ZyanString` instance.
572  * @param   index   The character index.
573  * @param   value   The character to assign.
574  *
575  * @return  A zyan status code.
576  */
577 ZYCORE_EXPORT ZyanStatus ZyanStringSetChar(ZyanString* string, ZyanUSize index, char value);
578 
579 /* ---------------------------------------------------------------------------------------------- */
580 /* Insertion                                                                                      */
581 /* ---------------------------------------------------------------------------------------------- */
582 
583 /**
584  * Inserts the content of the source string in the destination string at the given `index`.
585  *
586  * @param   destination The destination string.
587  * @param   index       The insert index.
588  * @param   source      The source string.
589  *
590  * @return  A zyan status code.
591  */
592 ZYCORE_EXPORT ZyanStatus ZyanStringInsert(ZyanString* destination, ZyanUSize index,
593     const ZyanStringView* source);
594 
595 /**
596  * Inserts `count` characters of the source string in the destination string at the given
597  * `index`.
598  *
599  * @param   destination         The destination string.
600  * @param   destination_index   The insert index.
601  * @param   source              The source string.
602  * @param   source_index        The index of the first character to be inserted from the source
603  *                              string.
604  * @param   count               The number of chars to insert from the source string.
605  *
606  * @return  A zyan status code.
607  */
608 ZYCORE_EXPORT ZyanStatus ZyanStringInsertEx(ZyanString* destination, ZyanUSize destination_index,
609     const ZyanStringView* source, ZyanUSize source_index, ZyanUSize count);
610 
611 /* ---------------------------------------------------------------------------------------------- */
612 /* Appending                                                                                      */
613 /* ---------------------------------------------------------------------------------------------- */
614 
615 /**
616  * Appends the content of the source string to the end of the destination string.
617  *
618  * @param   destination The destination string.
619  * @param   source      The source string.
620  *
621  * @return  A zyan status code.
622  */
623 ZYCORE_EXPORT ZyanStatus ZyanStringAppend(ZyanString* destination, const ZyanStringView* source);
624 
625 /**
626  * Appends `count` characters of the source string to the end of the destination string.
627  *
628  * @param   destination     The destination string.
629  * @param   source          The source string.
630  * @param   source_index    The index of the first character to be appended from the source string.
631  * @param   count           The number of chars to append from the source string.
632  *
633  * @return  A zyan status code.
634  */
635 ZYCORE_EXPORT ZyanStatus ZyanStringAppendEx(ZyanString* destination, const ZyanStringView* source,
636     ZyanUSize source_index, ZyanUSize count);
637 
638 /* ---------------------------------------------------------------------------------------------- */
639 /* Deletion                                                                                       */
640 /* ---------------------------------------------------------------------------------------------- */
641 
642 /**
643  * Deletes characters from the given string, starting at `index`.
644  *
645  * @param   string  A pointer to the `ZyanString` instance.
646  * @param   index   The index of the first character to delete.
647  * @param   count   The number of characters to delete.
648  *
649  * @return  A zyan status code.
650  */
651 ZYCORE_EXPORT ZyanStatus ZyanStringDelete(ZyanString* string, ZyanUSize index, ZyanUSize count);
652 
653 /**
654  * Deletes all remaining characters from the given string, starting at `index`.
655  *
656  * @param   string  A pointer to the `ZyanString` instance.
657  * @param   index   The index of the first character to delete.
658  *
659  * @return  A zyan status code.
660  */
661 ZYCORE_EXPORT ZyanStatus ZyanStringTruncate(ZyanString* string, ZyanUSize index);
662 
663 /**
664  * Erases the given string.
665  *
666  * @param   string  A pointer to the `ZyanString` instance.
667  *
668  * @return  A zyan status code.
669  */
670 ZYCORE_EXPORT ZyanStatus ZyanStringClear(ZyanString* string);
671 
672 /* ---------------------------------------------------------------------------------------------- */
673 /* Searching                                                                                      */
674 /* ---------------------------------------------------------------------------------------------- */
675 
676 /**
677  * Searches for the first occurrence of `needle` in the given `haystack` starting from the
678  * left.
679  *
680  * @param   haystack    The string to search in.
681  * @param   needle      The sub-string to search for.
682  * @param   found_index A pointer to a variable that receives the index of the first occurrence of
683  *                      `needle`.
684  *
685  * @return  `ZYAN_STATUS_TRUE`, if the needle was found, `ZYAN_STATUS_FALSE`, if not, or another
686  *          zyan status code, if an error occured.
687  *
688  * The `found_index` is set to `-1`, if the needle was not found.
689  */
690 ZYCORE_EXPORT ZyanStatus ZyanStringLPos(const ZyanStringView* haystack,
691     const ZyanStringView* needle, ZyanISize* found_index);
692 
693 /**
694  * Searches for the first occurrence of `needle` in the given `haystack` starting from the
695  * left.
696  *
697  * @param   haystack    The string to search in.
698  * @param   needle      The sub-string to search for.
699  * @param   found_index A pointer to a variable that receives the index of the first occurrence of
700  *                      `needle`.
701  * @param   index       The start index.
702  * @param   count       The maximum number of characters to iterate, beginning from the start
703  *                      `index`.
704  *
705  * @return  `ZYAN_STATUS_TRUE`, if the needle was found, `ZYAN_STATUS_FALSE`, if not, or another
706  *          zyan status code, if an error occured.
707  *
708  * The `found_index` is set to `-1`, if the needle was not found.
709  */
710 ZYCORE_EXPORT ZyanStatus ZyanStringLPosEx(const ZyanStringView* haystack,
711     const ZyanStringView* needle, ZyanISize* found_index, ZyanUSize index, ZyanUSize count);
712 
713 /**
714  * Performs a case-insensitive search for the first occurrence of `needle` in the given
715  * `haystack` starting from the left.
716  *
717  * @param   haystack    The string to search in.
718  * @param   needle      The sub-string to search for.
719  * @param   found_index A pointer to a variable that receives the index of the first occurrence of
720  *                      `needle`.
721  *
722  * @return  `ZYAN_STATUS_TRUE`, if the needle was found, `ZYAN_STATUS_FALSE`, if not, or another
723  *          zyan status code, if an error occured.
724  *
725  * The `found_index` is set to `-1`, if the needle was not found.
726  */
727 ZYCORE_EXPORT ZyanStatus ZyanStringLPosI(const ZyanStringView* haystack,
728     const ZyanStringView* needle, ZyanISize* found_index);
729 
730 /**
731  * Performs a case-insensitive search for the first occurrence of `needle` in the given
732  * `haystack` starting from the left.
733  *
734  * @param   haystack    The string to search in.
735  * @param   needle      The sub-string to search for.
736  * @param   found_index A pointer to a variable that receives the index of the first occurrence of
737  *                      `needle`.
738  * @param   index       The start index.
739  * @param   count       The maximum number of characters to iterate, beginning from the start
740  *                      `index`.
741  *
742  * @return  `ZYAN_STATUS_TRUE`, if the needle was found, `ZYAN_STATUS_FALSE`, if not, or another
743  *          zyan status code, if an error occurred.
744  *
745  * The `found_index` is set to `-1`, if the needle was not found.
746  */
747 ZYCORE_EXPORT ZyanStatus ZyanStringLPosIEx(const ZyanStringView* haystack,
748     const ZyanStringView* needle, ZyanISize* found_index, ZyanUSize index, ZyanUSize count);
749 
750 /**
751  * Searches for the first occurrence of `needle` in the given `haystack` starting from the
752  * right.
753  *
754  * @param   haystack    The string to search in.
755  * @param   needle      The sub-string to search for.
756  * @param   found_index A pointer to a variable that receives the index of the first occurrence of
757  *                      `needle`.
758  *
759  * @return  `ZYAN_STATUS_TRUE`, if the needle was found, `ZYAN_STATUS_FALSE`, if not, or another
760  *          zyan status code, if an error occurred.
761  *
762  * The `found_index` is set to `-1`, if the needle was not found.
763  */
764 ZYCORE_EXPORT ZyanStatus ZyanStringRPos(const ZyanStringView* haystack,
765     const ZyanStringView* needle, ZyanISize* found_index);
766 
767 /**
768  * Searches for the first occurrence of `needle` in the given `haystack` starting from the
769  *          right.
770  *
771  * @param   haystack    The string to search in.
772  * @param   needle      The sub-string to search for.
773  * @param   found_index A pointer to a variable that receives the index of the first occurrence of
774  *                      `needle`.
775  * @param   index       The start index.
776  * @param   count       The maximum number of characters to iterate, beginning from the start
777  *                      `index`.
778  *
779  * @return  `ZYAN_STATUS_TRUE`, if the needle was found, `ZYAN_STATUS_FALSE`, if not, or another
780  *          zyan status code, if an error occurred.
781  *
782  * The `found_index` is set to `-1`, if the needle was not found.
783  */
784 ZYCORE_EXPORT ZyanStatus ZyanStringRPosEx(const ZyanStringView* haystack,
785     const ZyanStringView* needle, ZyanISize* found_index, ZyanUSize index, ZyanUSize count);
786 
787 /**
788  * Performs a case-insensitive search for the first occurrence of `needle` in the given
789  * `haystack` starting from the right.
790  *
791  * @param   haystack    The string to search in.
792  * @param   needle      The sub-string to search for.
793  * @param   found_index A pointer to a variable that receives the index of the first occurrence of
794  *                      `needle`.
795  *
796  * @return  `ZYAN_STATUS_TRUE`, if the needle was found, `ZYAN_STATUS_FALSE`, if not, or another
797  *          zyan status code, if an error occurred.
798  *
799  * The `found_index` is set to `-1`, if the needle was not found.
800  */
801 ZYCORE_EXPORT ZyanStatus ZyanStringRPosI(const ZyanStringView* haystack,
802     const ZyanStringView* needle, ZyanISize* found_index);
803 
804 /**
805  * Performs a case-insensitive search for the first occurrence of `needle` in the given
806  * `haystack` starting from the right.
807  *
808  * @param   haystack    The string to search in.
809  * @param   needle      The sub-string to search for.
810  * @param   found_index A pointer to a variable that receives the index of the first occurrence of
811  *                      `needle`.
812  * @param   index       The start index.
813  * @param   count       The maximum number of characters to iterate, beginning from the start
814  *                      `index`.
815  *
816  * @return  `ZYAN_STATUS_TRUE`, if the needle was found, `ZYAN_STATUS_FALSE`, if not, or another
817  *          zyan status code, if an error occurred.
818  *
819  * The `found_index` is set to `-1`, if the needle was not found.
820  */
821 ZYCORE_EXPORT ZyanStatus ZyanStringRPosIEx(const ZyanStringView* haystack,
822     const ZyanStringView* needle, ZyanISize* found_index, ZyanUSize index, ZyanUSize count);
823 
824 /* ---------------------------------------------------------------------------------------------- */
825 /* Comparing                                                                                      */
826 /* ---------------------------------------------------------------------------------------------- */
827 
828 /**
829  * Compares two strings.
830  *
831  * @param   s1      The first string
832  * @param   s2      The second string.
833  * @param   result  Receives the comparison result.
834  *
835  *                  Values:
836  *                  - `result  < 0` -> The first character that does not match has a lower value
837  *                    in `s1` than in `s2`.
838  *                  - `result == 0` -> The contents of both strings are equal.
839  *                  - `result  > 0` -> The first character that does not match has a greater value
840  *                    in `s1` than in `s2`.
841  *
842  * @return  `ZYAN_STATUS_TRUE`, if the strings are equal, `ZYAN_STATUS_FALSE`, if not, or another
843  *          zyan status code, if an error occurred.
844  */
845 ZYCORE_EXPORT ZyanStatus ZyanStringCompare(const ZyanStringView* s1, const ZyanStringView* s2,
846     ZyanI32* result);
847 
848 /**
849  * Performs a case-insensitive comparison of two strings.
850  *
851  * @param   s1      The first string
852  * @param   s2      The second string.
853  * @param   result  Receives the comparison result.
854  *
855  *                  Values:
856  *                  - `result  < 0` -> The first character that does not match has a lower value
857  *                    in `s1` than in `s2`.
858  *                  - `result == 0` -> The contents of both strings are equal.
859  *                  - `result  > 0` -> The first character that does not match has a greater value
860  *                    in `s1` than in `s2`.
861  *
862  * @return  `ZYAN_STATUS_TRUE`, if the strings are equal, `ZYAN_STATUS_FALSE`, if not, or another
863  *          zyan status code, if an error occurred.
864  */
865 ZYCORE_EXPORT ZyanStatus ZyanStringCompareI(const ZyanStringView* s1, const ZyanStringView* s2,
866     ZyanI32* result);
867 
868 /* ---------------------------------------------------------------------------------------------- */
869 /* Case conversion                                                                                */
870 /* ---------------------------------------------------------------------------------------------- */
871 
872 /**
873  * Converts the given string to lowercase letters.
874  *
875  * @param   string      A pointer to the `ZyanString` instance.
876  *
877  * @return  A zyan status code.
878  *
879  * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified
880  * `ZyanString` instance.
881  */
882 ZYCORE_EXPORT ZyanStatus ZyanStringToLowerCase(ZyanString* string);
883 
884 /**
885  * Converts `count` characters of the given string to lowercase letters.
886  *
887  * @param   string  A pointer to the `ZyanString` instance.
888  * @param   index   The start index.
889  * @param   count   The number of characters to convert, beginning from the start `index`.
890  *
891  * @return  A zyan status code.
892  *
893  * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified
894  * `ZyanString` instance.
895  */
896 ZYCORE_EXPORT ZyanStatus ZyanStringToLowerCaseEx(ZyanString* string, ZyanUSize index,
897     ZyanUSize count);
898 
899 /**
900  * Converts the given string to uppercase letters.
901  *
902  * @param   string      A pointer to the `ZyanString` instance.
903  *
904  * @return  A zyan status code.
905  *
906  * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified
907  * `ZyanString` instance.
908  */
909 ZYCORE_EXPORT ZyanStatus ZyanStringToUpperCase(ZyanString* string);
910 
911 /**
912  * Converts `count` characters of the given string to uppercase letters.
913  *
914  * @param   string  A pointer to the `ZyanString` instance.
915  * @param   index   The start index.
916  * @param   count   The number of characters to convert, beginning from the start `index`.
917  *
918  * @return  A zyan status code.
919  *
920  * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified
921  * `ZyanString` instance.
922  */
923 ZYCORE_EXPORT ZyanStatus ZyanStringToUpperCaseEx(ZyanString* string, ZyanUSize index,
924     ZyanUSize count);
925 
926 /* ---------------------------------------------------------------------------------------------- */
927 /* Memory management                                                                              */
928 /* ---------------------------------------------------------------------------------------------- */
929 
930 /**
931  * Resizes the given `ZyanString` instance.
932  *
933  * @param   string  A pointer to the `ZyanString` instance.
934  * @param   size    The new size of the string.
935  *
936  * @return  A zyan status code.
937  *
938  * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified
939  * `ZyanString` instance.
940  */
941 ZYCORE_EXPORT ZyanStatus ZyanStringResize(ZyanString* string, ZyanUSize size);
942 
943 /**
944  * Changes the capacity of the given `ZyanString` instance.
945  *
946  * @param   string      A pointer to the `ZyanString` instance.
947  * @param   capacity    The new minimum capacity of the string.
948  *
949  * @return  A zyan status code.
950  *
951  * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified
952  * `ZyanString` instance.
953  */
954 ZYCORE_EXPORT ZyanStatus ZyanStringReserve(ZyanString* string, ZyanUSize capacity);
955 
956 /**
957  * Shrinks the capacity of the given string to match it's size.
958  *
959  * @param   string  A pointer to the `ZyanString` instance.
960  *
961  * @return  A zyan status code.
962  *
963  * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified
964  * `ZyanString` instance.
965  */
966 ZYCORE_EXPORT ZyanStatus ZyanStringShrinkToFit(ZyanString* string);
967 
968 /* ---------------------------------------------------------------------------------------------- */
969 /* Information                                                                                    */
970 /* ---------------------------------------------------------------------------------------------- */
971 
972 /**
973  * Returns the current capacity of the string.
974  *
975  * @param   string      A pointer to the `ZyanString` instance.
976  * @param   capacity    Receives the size of the string.
977  *
978  * @return  A zyan status code.
979  */
980 ZYCORE_EXPORT ZyanStatus ZyanStringGetCapacity(const ZyanString* string, ZyanUSize* capacity);
981 
982 /**
983  * Returns the current size (number of characters) of the string (excluding the
984  * terminating zero character).
985  *
986  * @param   string  A pointer to the `ZyanString` instance.
987  * @param   size    Receives the size (number of characters) of the string.
988  *
989  * @return  A zyan status code.
990  */
991 ZYCORE_EXPORT ZyanStatus ZyanStringGetSize(const ZyanString* string, ZyanUSize* size);
992 
993 /**
994  * Returns the C-style string of the given `ZyanString` instance.
995  *
996  * @param   string  A pointer to the `ZyanString` instance.
997  * @param   value   Receives a pointer to the C-style string.
998  *
999  * @return  A zyan status code.
1000  */
1001 ZYCORE_EXPORT ZyanStatus ZyanStringGetData(const ZyanString* string, const char** value);
1002 
1003 /* ---------------------------------------------------------------------------------------------- */
1004 
1005 /* ============================================================================================== */
1006 
1007 #ifdef __cplusplus
1008 }
1009 #endif
1010 
1011 #endif // ZYCORE_STRING_H
1012