Slice99 0.7.8
Memory slices for C99
All Data Structures Files Functions Variables Macros Pages
slice99.h
Go to the documentation of this file.
1/*
2MIT License
3
4Copyright (c) 2020-2025 hirrolot
5
6Permission is hereby granted, free of charge, to any person obtaining a copy
7of this software and associated documentation files (the "Software"), to deal
8in the Software without restriction, including without limitation the rights
9to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10copies of the Software, and to permit persons to whom the Software is
11furnished to do so, subject to the following conditions:
12
13The above copyright notice and this permission notice shall be included in all
14copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22SOFTWARE.
23*/
24
49#ifndef SLICE99_H
50#define SLICE99_H
51
52#include <stdarg.h>
53#include <stdbool.h>
54#include <stddef.h>
55#include <stdint.h>
56
57#ifndef SLICE99_ASSERT
58#include <assert.h>
60#define SLICE99_ASSERT assert
61#endif // SLICE99_ASSERT
62
63#ifndef SLICE99_MEMCMP
64#include <string.h>
66#define SLICE99_MEMCMP memcmp
67#endif
68
69#ifndef SLICE99_MEMCPY
70#include <string.h>
72#define SLICE99_MEMCPY memcpy
73#endif
74
75#ifndef SLICE99_MEMMOVE
76#include <string.h>
78#define SLICE99_MEMMOVE memmove
79#endif
80
81#ifndef SLICE99_STRLEN
82#include <string.h>
84#define SLICE99_STRLEN strlen
85#endif
86
87#ifndef DOXYGEN_IGNORE
88
89#ifdef __GNUC__
90#define SLICE99_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
91#else
92#define SLICE99_WARN_UNUSED_RESULT
93#endif // __GNU__
94
95#if defined(__GNUC__) && !defined(__clang__)
96
97#define SLICE99_CONST __attribute__((const))
98#define SLICE99_PURE __attribute__((pure))
99#define SLICE99_ALWAYS_INLINE __attribute__((always_inline))
100#define SLICE99_FORMAT_HINT(archetype, string_idx, first_to_check) \
101 __attribute__((format(archetype, string_idx, first_to_check)))
102
103#else
104
105#define SLICE99_CONST
106#define SLICE99_PURE
107#define SLICE99_ALWAYS_INLINE
108#define SLICE99_FORMAT_HINT(_archetype, _string_idx, _first_to_check)
109
110#endif
111
112#endif // DOXYGEN_IGNORE
113
117#define SLICE99_MAJOR 0
118
122#define SLICE99_MINOR 7
123
127#define SLICE99_PATCH 8
128
174#define SLICE99_DEF_TYPED(name, T) \
175 typedef struct { \
176 T *ptr; \
177 size_t len; \
178 } name; \
179 \
180 inline static SLICE99_ALWAYS_INLINE SLICE99_WARN_UNUSED_RESULT name name##_new( \
181 T *ptr, size_t len) { \
182 const Slice99 result = Slice99_new((void *)ptr, sizeof(T), len); \
183 return (name)SLICE99_TO_TYPED(result); \
184 } \
185 \
186 inline static SLICE99_ALWAYS_INLINE SLICE99_WARN_UNUSED_RESULT name name##_from_ptrdiff( \
187 T *start, T *end) { \
188 const Slice99 result = Slice99_from_ptrdiff((void *)start, (void *)end, sizeof(T)); \
189 return (name)SLICE99_TO_TYPED(result); \
190 } \
191 \
192 inline static SLICE99_ALWAYS_INLINE SLICE99_WARN_UNUSED_RESULT name name##_empty(void) { \
193 const Slice99 result = Slice99_empty(sizeof(T)); \
194 return (name)SLICE99_TO_TYPED(result); \
195 } \
196 \
197 inline static SLICE99_ALWAYS_INLINE SLICE99_WARN_UNUSED_RESULT name name##_update_len( \
198 name self, size_t new_len) { \
199 const Slice99 result = Slice99_update_len(SLICE99_TO_UNTYPED(self), new_len); \
200 return (name)SLICE99_TO_TYPED(result); \
201 } \
202 \
203 inline static SLICE99_ALWAYS_INLINE SLICE99_WARN_UNUSED_RESULT \
204 SLICE99_CONST bool name##_is_empty(name self) { \
205 return Slice99_is_empty(SLICE99_TO_UNTYPED(self)); \
206 } \
207 \
208 inline static SLICE99_ALWAYS_INLINE SLICE99_WARN_UNUSED_RESULT SLICE99_CONST size_t \
209 name##_size(name self) { \
210 return Slice99_size(SLICE99_TO_UNTYPED(self)); \
211 } \
212 \
213 inline static SLICE99_ALWAYS_INLINE SLICE99_WARN_UNUSED_RESULT SLICE99_CONST T *name##_get( \
214 name self, ptrdiff_t i) { \
215 return (T *)Slice99_get(SLICE99_TO_UNTYPED(self), i); \
216 } \
217 \
218 inline static SLICE99_ALWAYS_INLINE SLICE99_WARN_UNUSED_RESULT SLICE99_CONST T *name##_first( \
219 name self) { \
220 return (T *)Slice99_first(SLICE99_TO_UNTYPED(self)); \
221 } \
222 \
223 inline static SLICE99_ALWAYS_INLINE SLICE99_WARN_UNUSED_RESULT SLICE99_CONST T *name##_last( \
224 name self) { \
225 return (T *)Slice99_last(SLICE99_TO_UNTYPED(self)); \
226 } \
227 \
228 inline static SLICE99_ALWAYS_INLINE SLICE99_WARN_UNUSED_RESULT name name##_sub( \
229 name self, ptrdiff_t start_idx, ptrdiff_t end_idx) { \
230 const Slice99 result = Slice99_sub(SLICE99_TO_UNTYPED(self), start_idx, end_idx); \
231 return (name)SLICE99_TO_TYPED(result); \
232 } \
233 \
234 inline static SLICE99_ALWAYS_INLINE SLICE99_WARN_UNUSED_RESULT name name##_advance( \
235 name self, ptrdiff_t offset) { \
236 const Slice99 result = Slice99_advance(SLICE99_TO_UNTYPED(self), offset); \
237 return (name)SLICE99_TO_TYPED(result); \
238 } \
239 \
240 inline static SLICE99_ALWAYS_INLINE SLICE99_WARN_UNUSED_RESULT bool name##_primitive_eq( \
241 name lhs, name rhs) { \
242 return Slice99_primitive_eq(SLICE99_TO_UNTYPED(lhs), SLICE99_TO_UNTYPED(rhs)); \
243 } \
244 \
245 inline static SLICE99_ALWAYS_INLINE SLICE99_WARN_UNUSED_RESULT bool name##_eq( \
246 name lhs, name rhs, int (*cmp)(const T *, const T *)) { \
247 return Slice99_eq( \
248 SLICE99_TO_UNTYPED(lhs), SLICE99_TO_UNTYPED(rhs), \
249 (int (*)(const void *, const void *))cmp); \
250 } \
251 \
252 inline static SLICE99_ALWAYS_INLINE SLICE99_WARN_UNUSED_RESULT bool \
253 name##_primitive_starts_with(name self, name prefix) { \
254 return Slice99_primitive_starts_with( \
255 SLICE99_TO_UNTYPED(self), SLICE99_TO_UNTYPED(prefix)); \
256 } \
257 \
258 inline static SLICE99_ALWAYS_INLINE SLICE99_WARN_UNUSED_RESULT bool name##_starts_with( \
259 name self, name prefix, int (*cmp)(const T *, const T *)) { \
260 return Slice99_starts_with( \
261 SLICE99_TO_UNTYPED(self), SLICE99_TO_UNTYPED(prefix), \
262 (int (*)(const void *, const void *))cmp); \
263 } \
264 \
265 inline static SLICE99_ALWAYS_INLINE SLICE99_WARN_UNUSED_RESULT bool \
266 name##_primitive_ends_with(name self, name postfix) { \
267 return Slice99_primitive_ends_with(SLICE99_TO_UNTYPED(self), SLICE99_TO_UNTYPED(postfix)); \
268 } \
269 \
270 inline static SLICE99_ALWAYS_INLINE SLICE99_WARN_UNUSED_RESULT bool name##_ends_with( \
271 name self, name postfix, int (*cmp)(const T *, const T *)) { \
272 return Slice99_ends_with( \
273 SLICE99_TO_UNTYPED(self), SLICE99_TO_UNTYPED(postfix), \
274 (int (*)(const void *, const void *))cmp); \
275 } \
276 \
277 inline static SLICE99_ALWAYS_INLINE void name##_copy(name self, name other) { \
278 Slice99_copy(SLICE99_TO_UNTYPED(self), SLICE99_TO_UNTYPED(other)); \
279 } \
280 \
281 inline static SLICE99_ALWAYS_INLINE void name##_copy_non_overlapping(name self, name other) { \
282 Slice99_copy_non_overlapping(SLICE99_TO_UNTYPED(self), SLICE99_TO_UNTYPED(other)); \
283 } \
284 \
285 inline static SLICE99_ALWAYS_INLINE void name##_swap( \
286 name self, ptrdiff_t lhs, ptrdiff_t rhs, T *restrict backup) { \
287 Slice99_swap(SLICE99_TO_UNTYPED(self), lhs, rhs, (void *restrict)backup); \
288 } \
289 \
290 inline static SLICE99_ALWAYS_INLINE void name##_swap_with_slice( \
291 name self, name other, T *restrict backup) { \
292 Slice99_swap_with_slice( \
293 SLICE99_TO_UNTYPED(self), SLICE99_TO_UNTYPED(other), (void *restrict)backup); \
294 } \
295 \
296 inline static SLICE99_ALWAYS_INLINE void name##_reverse(name self, T *restrict backup) { \
297 Slice99_reverse(SLICE99_TO_UNTYPED(self), (void *restrict)backup); \
298 } \
299 \
300 inline static SLICE99_ALWAYS_INLINE void name##_split_at( \
301 name self, size_t i, name *restrict lhs, name *restrict rhs) { \
302 SLICE99_ASSERT(lhs); \
303 SLICE99_ASSERT(rhs); \
304 \
305 Slice99 lhs_untyped = SLICE99_TO_UNTYPED(*lhs), rhs_untyped = SLICE99_TO_UNTYPED(*rhs); \
306 \
307 Slice99_split_at(SLICE99_TO_UNTYPED(self), i, &lhs_untyped, &rhs_untyped); \
308 \
309 *lhs = (name)SLICE99_TO_TYPED(lhs_untyped); \
310 *rhs = (name)SLICE99_TO_TYPED(rhs_untyped); \
311 } \
312 \
313 struct slice99_priv_trailing_comma
314
332#define SLICE99_TO_TYPED(self) \
333 { .ptr = (self).ptr, .len = (self).len }
334
352#define SLICE99_TO_UNTYPED(self) Slice99_new((self).ptr, sizeof(*(self).ptr), (self).len)
353
357#define SLICE99_ARRAY_LEN(...) (sizeof(__VA_ARGS__) / sizeof((__VA_ARGS__)[0]))
358
384#define SLICE99_APPEND(buffer, obj) \
385 ((void *)((char *)SLICE99_MEMCPY((buffer), &(obj), sizeof(obj)) + sizeof(obj)))
386
393#define SLICE99_APPEND_ARRAY(buffer, ptr, len) \
394 /* clang-format off */ \
395 ((void *)((char *)SLICE99_MEMCPY((buffer), (ptr), sizeof((ptr)[0]) * (len)) + \
396 sizeof((ptr)[0]) * (len))) /* clang-format on */
397
398#ifdef UINT8_MAX
399
407#define SLICE99_TO_OCTETS(obj) U8Slice99_new((uint8_t *)&(obj), sizeof(obj))
408
409#endif
410
417#define Slice99_from_array(...) \
418 Slice99_new((void *)(__VA_ARGS__), sizeof((__VA_ARGS__)[0]), SLICE99_ARRAY_LEN(__VA_ARGS__))
419
434#define Slice99_typed_from_array(...) \
435 { .ptr = (__VA_ARGS__), .len = SLICE99_ARRAY_LEN(__VA_ARGS__) }
436
445#define Slice99_from_typed_ptr(ptr, len) Slice99_new(ptr, sizeof(*(ptr)), len)
446
455typedef struct {
459 void *ptr;
460
464 size_t item_size;
465
469 size_t len;
470} Slice99;
471
482inline static SLICE99_WARN_UNUSED_RESULT Slice99
483Slice99_new(void *ptr, size_t item_size, size_t len) {
484 SLICE99_ASSERT(ptr);
485 SLICE99_ASSERT(item_size > 0);
486
487 return (Slice99){.ptr = ptr, .item_size = item_size, .len = len};
488}
489
497inline static SLICE99_WARN_UNUSED_RESULT Slice99 Slice99_from_str(char *str) {
498 SLICE99_ASSERT(str);
499
500 return Slice99_new(str, sizeof(char), SLICE99_STRLEN(str));
501}
502
515inline static SLICE99_WARN_UNUSED_RESULT Slice99
516Slice99_from_ptrdiff(void *start, void *end, size_t item_size) {
517 SLICE99_ASSERT(start);
518 SLICE99_ASSERT(end);
519
520 const ptrdiff_t diff = (char *)end - (char *)start;
521
522 SLICE99_ASSERT(diff >= 0);
523 SLICE99_ASSERT((size_t)diff % item_size == 0);
524
525 return Slice99_new(start, item_size, (size_t)(diff / (ptrdiff_t)item_size));
526}
527
535inline static SLICE99_WARN_UNUSED_RESULT Slice99 Slice99_empty(size_t item_size) {
536 SLICE99_ASSERT(item_size > 0);
537 return Slice99_new("", item_size, 0);
538}
539
546inline static SLICE99_WARN_UNUSED_RESULT Slice99 Slice99_update_len(Slice99 self, size_t new_len) {
547 return Slice99_new(self.ptr, self.item_size, new_len);
548}
549
557inline static SLICE99_WARN_UNUSED_RESULT SLICE99_CONST bool Slice99_is_empty(Slice99 self) {
558 return self.len == 0;
559}
560
566inline static SLICE99_WARN_UNUSED_RESULT SLICE99_CONST size_t Slice99_size(Slice99 self) {
567 return self.item_size * self.len;
568}
569
578inline static SLICE99_WARN_UNUSED_RESULT SLICE99_CONST void *
579Slice99_get(Slice99 self, ptrdiff_t i) {
580 return (void *)((char *)self.ptr + i * (ptrdiff_t)self.item_size);
581}
582
588inline static SLICE99_WARN_UNUSED_RESULT SLICE99_CONST void *Slice99_first(Slice99 self) {
589 return Slice99_get(self, 0);
590}
591
599inline static SLICE99_WARN_UNUSED_RESULT SLICE99_CONST void *Slice99_last(Slice99 self) {
600 return Slice99_get(self, (ptrdiff_t)self.len - 1);
601}
602
614inline static SLICE99_WARN_UNUSED_RESULT Slice99
615Slice99_sub(Slice99 self, ptrdiff_t start_idx, ptrdiff_t end_idx) {
616 SLICE99_ASSERT(start_idx <= end_idx);
617
619 Slice99_get(self, start_idx), Slice99_get(self, end_idx), self.item_size);
620}
621
633inline static SLICE99_WARN_UNUSED_RESULT Slice99 Slice99_advance(Slice99 self, ptrdiff_t offset) {
634 return Slice99_sub(self, offset, (ptrdiff_t)self.len);
635}
636
645inline static SLICE99_WARN_UNUSED_RESULT bool Slice99_primitive_eq(Slice99 lhs, Slice99 rhs) {
646 return Slice99_size(lhs) != Slice99_size(rhs)
647 ? false
648 : SLICE99_MEMCMP(lhs.ptr, rhs.ptr, Slice99_size(lhs)) == 0;
649}
650
665inline static SLICE99_WARN_UNUSED_RESULT bool
666Slice99_eq(Slice99 lhs, Slice99 rhs, int (*cmp)(const void *, const void *)) {
668 SLICE99_ASSERT(cmp);
669
670 if (lhs.len != rhs.len) {
671 return false;
672 }
673
674 for (ptrdiff_t i = 0; i < (ptrdiff_t)lhs.len; i++) {
675 if (cmp(Slice99_get(lhs, i), Slice99_get(rhs, i)) != 0) {
676 return false;
677 }
678 }
679
680 return true;
681}
682
693inline static SLICE99_WARN_UNUSED_RESULT bool
695 return Slice99_size(self) < Slice99_size(prefix)
696 ? false
697 : Slice99_primitive_eq(Slice99_sub(self, 0, (ptrdiff_t)prefix.len), prefix);
698}
699
714inline static SLICE99_WARN_UNUSED_RESULT bool
715Slice99_starts_with(Slice99 self, Slice99 prefix, int (*cmp)(const void *, const void *)) {
716 SLICE99_ASSERT(self.item_size == prefix.item_size);
717 SLICE99_ASSERT(cmp);
718
719 return self.len < prefix.len
720 ? false
721 : Slice99_eq(Slice99_sub(self, 0, (ptrdiff_t)prefix.len), prefix, cmp);
722}
723
734inline static SLICE99_WARN_UNUSED_RESULT bool
736 return Slice99_size(self) < Slice99_size(postfix)
737 ? false
740 self, (ptrdiff_t)self.len - (ptrdiff_t)postfix.len, (ptrdiff_t)self.len),
741 postfix);
742}
743
758inline static SLICE99_WARN_UNUSED_RESULT bool
759Slice99_ends_with(Slice99 self, Slice99 postfix, int (*cmp)(const void *, const void *)) {
760 SLICE99_ASSERT(self.item_size == postfix.item_size);
761 SLICE99_ASSERT(cmp);
762
763 return self.len < postfix.len
764 ? false
765 : Slice99_eq(
767 self, (ptrdiff_t)self.len - (ptrdiff_t)postfix.len, (ptrdiff_t)self.len),
768 postfix, cmp);
769}
770
777inline static void Slice99_copy(Slice99 self, Slice99 other) {
778 SLICE99_MEMMOVE(self.ptr, other.ptr, Slice99_size(other));
779}
780
786inline static void Slice99_copy_non_overlapping(Slice99 self, Slice99 other) {
787 SLICE99_MEMCPY(self.ptr, other.ptr, Slice99_size(other));
788}
789
802inline static void Slice99_swap(Slice99 self, ptrdiff_t lhs, ptrdiff_t rhs, void *restrict backup) {
803 SLICE99_ASSERT(backup);
804
805 SLICE99_MEMCPY((backup), Slice99_get(self, lhs), (self).item_size);
806 SLICE99_MEMCPY(Slice99_get(self, lhs), Slice99_get(self, rhs), (self).item_size);
807 SLICE99_MEMCPY(Slice99_get(self, rhs), (backup), (self).item_size);
808}
809
823inline static void Slice99_swap_with_slice(Slice99 self, Slice99 other, void *restrict backup) {
824 SLICE99_ASSERT(self.len == other.len);
825 SLICE99_ASSERT(self.item_size == other.item_size);
826
827 for (ptrdiff_t i = 0; i < (ptrdiff_t)self.len; i++) {
828 SLICE99_MEMCPY(backup, Slice99_get(self, i), self.item_size);
829 SLICE99_MEMCPY(Slice99_get(self, i), Slice99_get(other, i), self.item_size);
830 SLICE99_MEMCPY(Slice99_get(other, i), backup, self.item_size);
831 }
832}
833
843inline static void Slice99_reverse(Slice99 self, void *restrict backup) {
844 SLICE99_ASSERT(backup);
845
846 for (ptrdiff_t i = 0; i < (ptrdiff_t)self.len / 2; i++) {
847 Slice99_swap(self, i, (ptrdiff_t)self.len - i - 1, backup);
848 }
849}
850
864inline static void
865Slice99_split_at(Slice99 self, size_t i, Slice99 *restrict lhs, Slice99 *restrict rhs) {
866 SLICE99_ASSERT(i <= self.len);
867 SLICE99_ASSERT(lhs);
868 SLICE99_ASSERT(rhs);
869
870 *lhs = Slice99_sub(self, 0, (ptrdiff_t)i);
871 *rhs = Slice99_sub(self, (ptrdiff_t)i, (ptrdiff_t)self.len);
872}
873
885inline static char *Slice99_c_str(Slice99 self, char out[restrict]) {
886 SLICE99_ASSERT(out);
887
888 SLICE99_MEMCPY(out, self.ptr, Slice99_size(self));
889 out[Slice99_size(self)] = '\0';
890 return out;
891}
892
893SLICE99_DEF_TYPED(CharSlice99, char);
894SLICE99_DEF_TYPED(SCharSlice99, signed char);
895SLICE99_DEF_TYPED(UCharSlice99, unsigned char);
896
897SLICE99_DEF_TYPED(ShortSlice99, short);
898SLICE99_DEF_TYPED(UShortSlice99, unsigned short);
899
900SLICE99_DEF_TYPED(IntSlice99, int);
901SLICE99_DEF_TYPED(UIntSlice99, unsigned int);
902
903SLICE99_DEF_TYPED(LongSlice99, long);
904SLICE99_DEF_TYPED(ULongSlice99, unsigned long);
905SLICE99_DEF_TYPED(LongLongSlice99, long long);
906SLICE99_DEF_TYPED(ULongLongSlice99, unsigned long long);
907
908SLICE99_DEF_TYPED(FloatSlice99, float);
909SLICE99_DEF_TYPED(DoubleSlice99, double);
910SLICE99_DEF_TYPED(LongDoubleSlice99, long double);
911
912SLICE99_DEF_TYPED(BoolSlice99, _Bool);
913
914// Unsigned integers {
915#ifdef UINT8_MAX
916SLICE99_DEF_TYPED(U8Slice99, uint8_t);
917#endif
918
919#ifdef UINT16_MAX
920SLICE99_DEF_TYPED(U16Slice99, uint16_t);
921#endif
922
923#ifdef UINT32_MAX
924SLICE99_DEF_TYPED(U32Slice99, uint32_t);
925#endif
926
927#ifdef UINT64_MAX
928SLICE99_DEF_TYPED(U64Slice99, uint64_t);
929#endif
930// } (Unsigned integers)
931
932// Signed integers {
933#ifdef INT8_MAX
934SLICE99_DEF_TYPED(I8Slice99, int8_t);
935#endif
936
937#ifdef INT16_MAX
938SLICE99_DEF_TYPED(I16Slice99, int16_t);
939#endif
940
941#ifdef INT32_MAX
942SLICE99_DEF_TYPED(I32Slice99, int32_t);
943#endif
944
945#ifdef INT64_MAX
946SLICE99_DEF_TYPED(I64Slice99, int64_t);
947#endif
948// } (Signed integers)
949
953inline static SLICE99_WARN_UNUSED_RESULT CharSlice99 CharSlice99_from_str(char *str) {
954 return (CharSlice99)SLICE99_TO_TYPED(Slice99_from_str(str));
955}
956
960inline static char *CharSlice99_c_str(CharSlice99 self, char out[restrict]) {
961 return Slice99_c_str(SLICE99_TO_UNTYPED(self), out);
962}
963
970#define CharSlice99_alloca_c_str(self) CharSlice99_c_str((self), alloca((self).len + 1))
971
972#ifndef SLICE99_DISABLE_STDIO
973
974#ifndef SLICE99_VSPRINTF
975#include <stdio.h>
978#define SLICE99_VSPRINTF vsprintf
979#endif
980
981#ifndef SLICE99_VSNPRINTF
982#include <stdio.h>
985#define SLICE99_VSNPRINTF vsnprintf
986#endif
987
988#ifndef SLICE99_SNPRINTF
989#include <stdio.h>
992#define SLICE99_SNPRINTF snprintf
993#endif
994
995#ifndef DOXYGEN_IGNORE
996
997// Doxygen fails to parse function declarations with function-like macro invocations.
998
999#define SLICE99_FORMAT_HINT_2_0 SLICE99_FORMAT_HINT(printf, 2, 0)
1000#define SLICE99_FORMAT_HINT_2_3 SLICE99_FORMAT_HINT(printf, 2, 3)
1001#define SLICE99_FORMAT_HINT_3_0 SLICE99_FORMAT_HINT(printf, 3, 0)
1002#define SLICE99_FORMAT_HINT_3_4 SLICE99_FORMAT_HINT(printf, 3, 4)
1003
1004#endif // DOXYGEN_IGNORE
1005
1021inline static SLICE99_WARN_UNUSED_RESULT SLICE99_FORMAT_HINT_2_0 CharSlice99
1022CharSlice99_vfmt(char out[restrict], const char *restrict fmt, va_list list) {
1023 SLICE99_ASSERT(out);
1024 SLICE99_ASSERT(fmt);
1025
1026 SLICE99_VSPRINTF(out, fmt, list);
1027 return CharSlice99_from_str(out);
1028}
1029
1035inline static SLICE99_WARN_UNUSED_RESULT SLICE99_FORMAT_HINT_2_3 CharSlice99
1036CharSlice99_fmt(char out[restrict], const char *restrict fmt, ...) {
1037 va_list ap;
1038 va_start(ap, fmt);
1039 const CharSlice99 result = CharSlice99_vfmt(out, fmt, ap);
1040 va_end(ap);
1041 return result;
1042}
1043
1049inline static SLICE99_WARN_UNUSED_RESULT SLICE99_FORMAT_HINT_3_0 CharSlice99
1050CharSlice99_vnfmt(char out[restrict], size_t bufsz, const char *restrict fmt, va_list list) {
1051 SLICE99_VSNPRINTF(out, bufsz, fmt, list);
1052 return CharSlice99_from_str(out);
1053}
1054
1060inline static SLICE99_WARN_UNUSED_RESULT SLICE99_FORMAT_HINT_3_4 CharSlice99
1061CharSlice99_nfmt(char out[restrict], size_t bufsz, const char *restrict fmt, ...) {
1062 va_list ap;
1063 va_start(ap, fmt);
1064 const CharSlice99 result = CharSlice99_vnfmt(out, bufsz, fmt, ap);
1065 va_end(ap);
1066 return result;
1067}
1068
1069#ifndef DOXYGEN_IGNORE
1070
1071#undef SLICE99_FORMAT_HINT_2_0
1072#undef SLICE99_FORMAT_HINT_2_3
1073#undef SLICE99_FORMAT_HINT_3_0
1074#undef SLICE99_FORMAT_HINT_3_4
1075
1076#endif // DOXYGEN_IGNORE
1077
1086#define CharSlice99_alloca_fmt(fmt, ...) \
1087 CharSlice99_fmt(alloca(SLICE99_SNPRINTF(NULL, 0, (fmt), __VA_ARGS__) + 1), (fmt), __VA_ARGS__)
1088
1089#endif // SLICE99_DISABLE_STDIO
1090
1091#endif // SLICE99_H
#define SLICE99_VSPRINTF
Like vsprintf.
Definition slice99.h:978
static SLICE99_WARN_UNUSED_RESULT SLICE99_FORMAT_HINT_2_3 CharSlice99 CharSlice99_fmt(char out[restrict], const char *restrict fmt,...)
The CharSlice99_vfmt twin.
Definition slice99.h:1036
static SLICE99_WARN_UNUSED_RESULT Slice99 Slice99_update_len(Slice99 self, size_t new_len)
Updates self with the new length new_len.
Definition slice99.h:546
static void Slice99_swap(Slice99 self, ptrdiff_t lhs, ptrdiff_t rhs, void *restrict backup)
Swaps the lhs -indexed and rhs -indexed items.
Definition slice99.h:802
static SLICE99_WARN_UNUSED_RESULT CharSlice99 CharSlice99_from_str(char *str)
The same as Slice99_from_str.
Definition slice99.h:953
static void Slice99_split_at(Slice99 self, size_t i, Slice99 *restrict lhs, Slice99 *restrict rhs)
Splits self into two parts.
Definition slice99.h:865
#define SLICE99_ASSERT
Like assert.
Definition slice99.h:60
static SLICE99_WARN_UNUSED_RESULT SLICE99_CONST size_t Slice99_size(Slice99 self)
Computes a total size in bytes.
Definition slice99.h:566
static SLICE99_WARN_UNUSED_RESULT bool Slice99_ends_with(Slice99 self, Slice99 postfix, int(*cmp)(const void *, const void *))
Checks whether postfix is a postfix of self with a user-supplied comparator.
Definition slice99.h:759
#define SLICE99_TO_TYPED(self)
Converts Slice99 to a typed representation.
Definition slice99.h:332
static SLICE99_WARN_UNUSED_RESULT Slice99 Slice99_new(void *ptr, size_t item_size, size_t len)
Constructs a slice.
Definition slice99.h:483
#define SLICE99_MEMCMP
Like memcmp.
Definition slice99.h:66
static SLICE99_WARN_UNUSED_RESULT bool Slice99_primitive_starts_with(Slice99 self, Slice99 prefix)
Checks whether prefix is a prefix of self, byte-by-byte.
Definition slice99.h:694
static SLICE99_WARN_UNUSED_RESULT SLICE99_FORMAT_HINT_2_0 CharSlice99 CharSlice99_vfmt(char out[restrict], const char *restrict fmt, va_list list)
Prints a formatted string to out and returns the corresponding character slice.
Definition slice99.h:1022
static void Slice99_reverse(Slice99 self, void *restrict backup)
Reverses the order of items in self.
Definition slice99.h:843
#define SLICE99_DEF_TYPED(name, T)
Defines the strongly typed slice name containing items of type T.
Definition slice99.h:174
static char * CharSlice99_c_str(CharSlice99 self, char out[restrict])
The same as Slice99_c_str.
Definition slice99.h:960
static void Slice99_swap_with_slice(Slice99 self, Slice99 other, void *restrict backup)
Swaps all the items in self with those in other.
Definition slice99.h:823
#define SLICE99_VSNPRINTF
Like vsnprintf.
Definition slice99.h:985
#define SLICE99_MEMCPY
Like memcpy.
Definition slice99.h:72
#define SLICE99_STRLEN
Like strlen.
Definition slice99.h:84
static SLICE99_WARN_UNUSED_RESULT bool Slice99_primitive_eq(Slice99 lhs, Slice99 rhs)
Performs a byte-by-byte comparison of lhs with rhs.
Definition slice99.h:645
static SLICE99_WARN_UNUSED_RESULT Slice99 Slice99_from_str(char *str)
Constructs a slice from str.
Definition slice99.h:497
static SLICE99_WARN_UNUSED_RESULT SLICE99_FORMAT_HINT_3_0 CharSlice99 CharSlice99_vnfmt(char out[restrict], size_t bufsz, const char *restrict fmt, va_list list)
The same as CharSlice99_vfmt but writes at most bufsz - 1 characters.
Definition slice99.h:1050
#define SLICE99_TO_UNTYPED(self)
Converts the typed slice self to Slice99.
Definition slice99.h:352
static SLICE99_WARN_UNUSED_RESULT bool Slice99_eq(Slice99 lhs, Slice99 rhs, int(*cmp)(const void *, const void *))
Performs a comparison of lhs with rhs with a user-supplied comparator.
Definition slice99.h:666
static SLICE99_WARN_UNUSED_RESULT bool Slice99_starts_with(Slice99 self, Slice99 prefix, int(*cmp)(const void *, const void *))
Checks whether prefix is a prefix of self with a user-supplied comparator.
Definition slice99.h:715
static SLICE99_WARN_UNUSED_RESULT SLICE99_CONST void * Slice99_first(Slice99 self)
Computes a pointer to the first item.
Definition slice99.h:588
static SLICE99_WARN_UNUSED_RESULT Slice99 Slice99_advance(Slice99 self, ptrdiff_t offset)
Advances self by offset items.
Definition slice99.h:633
static void Slice99_copy_non_overlapping(Slice99 self, Slice99 other)
The same as Slice99_copy except that self and other must be non-overlapping.
Definition slice99.h:786
static SLICE99_WARN_UNUSED_RESULT Slice99 Slice99_empty(size_t item_size)
Constructs an empty slice.
Definition slice99.h:535
static SLICE99_WARN_UNUSED_RESULT bool Slice99_primitive_ends_with(Slice99 self, Slice99 postfix)
Checks whether postfix is a postfix of self, byte-by-byte.
Definition slice99.h:735
static SLICE99_WARN_UNUSED_RESULT SLICE99_FORMAT_HINT_3_4 CharSlice99 CharSlice99_nfmt(char out[restrict], size_t bufsz, const char *restrict fmt,...)
The CharSlice99_vnfmt twin.
Definition slice99.h:1061
static SLICE99_WARN_UNUSED_RESULT SLICE99_CONST void * Slice99_last(Slice99 self)
Computes a pointer to the last item.
Definition slice99.h:599
static SLICE99_WARN_UNUSED_RESULT SLICE99_CONST bool Slice99_is_empty(Slice99 self)
Checks whether self is empty or not.
Definition slice99.h:557
static char * Slice99_c_str(Slice99 self, char out[restrict])
Copies self to out and appends '\0' to the end.
Definition slice99.h:885
static SLICE99_WARN_UNUSED_RESULT SLICE99_CONST void * Slice99_get(Slice99 self, ptrdiff_t i)
Computes a pointer to the i -indexed item.
Definition slice99.h:579
static void Slice99_copy(Slice99 self, Slice99 other)
Copies other to the beginning of self, byte-by-byte.
Definition slice99.h:777
static SLICE99_WARN_UNUSED_RESULT Slice99 Slice99_from_ptrdiff(void *start, void *end, size_t item_size)
Constructs a slice residing between start (inclusively) and end (exclusively).
Definition slice99.h:516
#define SLICE99_MEMMOVE
Like memmove.
Definition slice99.h:78
static SLICE99_WARN_UNUSED_RESULT Slice99 Slice99_sub(Slice99 self, ptrdiff_t start_idx, ptrdiff_t end_idx)
Subslicing self with [start_idx .. end_idx].
Definition slice99.h:615
A slice of some array.
Definition slice99.h:455
void * ptr
The pointer to data.
Definition slice99.h:459
size_t item_size
The size of each item in the array addressed by ptr.
Definition slice99.h:464
size_t len
The count of items in the array addressed by ptr.
Definition slice99.h:469