Slice99  0.7.7
Memory slices for C99
slice99.h
Go to the documentation of this file.
1 /*
2 MIT License
3 
4 Copyright (c) 2020-2024 hirrolot
5 
6 Permission is hereby granted, free of charge, to any person obtaining a copy
7 of this software and associated documentation files (the "Software"), to deal
8 in the Software without restriction, including without limitation the rights
9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 copies of the Software, and to permit persons to whom the Software is
11 furnished to do so, subject to the following conditions:
12 
13 The above copyright notice and this permission notice shall be included in all
14 copies or substantial portions of the Software.
15 
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 SOFTWARE.
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 7
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 
455 typedef struct {
459  void *ptr;
460 
464  size_t item_size;
465 
469  size_t len;
470 } Slice99;
471 
482 inline static SLICE99_WARN_UNUSED_RESULT Slice99
483 Slice99_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 
497 inline 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 
515 inline static SLICE99_WARN_UNUSED_RESULT Slice99
516 Slice99_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 
535 inline 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 
546 inline 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 
557 inline static SLICE99_WARN_UNUSED_RESULT SLICE99_CONST bool Slice99_is_empty(Slice99 self) {
558  return self.len == 0;
559 }
560 
566 inline static SLICE99_WARN_UNUSED_RESULT SLICE99_CONST size_t Slice99_size(Slice99 self) {
567  return self.item_size * self.len;
568 }
569 
578 inline static SLICE99_WARN_UNUSED_RESULT SLICE99_CONST void *
579 Slice99_get(Slice99 self, ptrdiff_t i) {
580  return (void *)((char *)self.ptr + i * (ptrdiff_t)self.item_size);
581 }
582 
588 inline static SLICE99_WARN_UNUSED_RESULT SLICE99_CONST void *Slice99_first(Slice99 self) {
589  return Slice99_get(self, 0);
590 }
591 
599 inline static SLICE99_WARN_UNUSED_RESULT SLICE99_CONST void *Slice99_last(Slice99 self) {
600  return Slice99_get(self, (ptrdiff_t)self.len - 1);
601 }
602 
614 inline static SLICE99_WARN_UNUSED_RESULT Slice99
615 Slice99_sub(Slice99 self, ptrdiff_t start_idx, ptrdiff_t end_idx) {
616  SLICE99_ASSERT(start_idx <= end_idx);
617 
618  return Slice99_from_ptrdiff(
619  Slice99_get(self, start_idx), Slice99_get(self, end_idx), self.item_size);
620 }
621 
633 inline 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 
645 inline 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 
665 inline static SLICE99_WARN_UNUSED_RESULT bool
666 Slice99_eq(Slice99 lhs, Slice99 rhs, int (*cmp)(const void *, const void *)) {
667  SLICE99_ASSERT(lhs.item_size == rhs.item_size);
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 
693 inline 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 
714 inline static SLICE99_WARN_UNUSED_RESULT bool
715 Slice99_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 
734 inline static SLICE99_WARN_UNUSED_RESULT bool
736  return Slice99_size(self) < Slice99_size(postfix)
737  ? false
739  Slice99_sub(
740  self, (ptrdiff_t)self.len - (ptrdiff_t)postfix.len, (ptrdiff_t)self.len),
741  postfix);
742 }
743 
758 inline static SLICE99_WARN_UNUSED_RESULT bool
759 Slice99_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(
766  Slice99_sub(
767  self, (ptrdiff_t)self.len - (ptrdiff_t)postfix.len, (ptrdiff_t)self.len),
768  postfix, cmp);
769 }
770 
777 inline static void Slice99_copy(Slice99 self, Slice99 other) {
778  SLICE99_MEMMOVE(self.ptr, other.ptr, Slice99_size(other));
779 }
780 
786 inline static void Slice99_copy_non_overlapping(Slice99 self, Slice99 other) {
787  SLICE99_MEMCPY(self.ptr, other.ptr, Slice99_size(other));
788 }
789 
802 inline 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 
823 inline 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 
843 inline 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 
864 inline static void
865 Slice99_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 
885 inline 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 
893 SLICE99_DEF_TYPED(CharSlice99, char);
894 SLICE99_DEF_TYPED(SCharSlice99, signed char);
895 SLICE99_DEF_TYPED(UCharSlice99, unsigned char);
896 
897 SLICE99_DEF_TYPED(ShortSlice99, short);
898 SLICE99_DEF_TYPED(UShortSlice99, unsigned short);
899 
900 SLICE99_DEF_TYPED(IntSlice99, int);
901 SLICE99_DEF_TYPED(UIntSlice99, unsigned int);
902 
903 SLICE99_DEF_TYPED(LongSlice99, long);
904 SLICE99_DEF_TYPED(ULongSlice99, unsigned long);
905 SLICE99_DEF_TYPED(LongLongSlice99, long long);
906 SLICE99_DEF_TYPED(ULongLongSlice99, unsigned long long);
907 
908 SLICE99_DEF_TYPED(FloatSlice99, float);
909 SLICE99_DEF_TYPED(DoubleSlice99, double);
910 SLICE99_DEF_TYPED(LongDoubleSlice99, long double);
911 
912 SLICE99_DEF_TYPED(BoolSlice99, _Bool);
913 
914 // Unsigned integers {
915 #ifdef UINT8_MAX
916 SLICE99_DEF_TYPED(U8Slice99, uint8_t);
917 #endif
918 
919 #ifdef UINT16_MAX
920 SLICE99_DEF_TYPED(U16Slice99, uint16_t);
921 #endif
922 
923 #ifdef UINT32_MAX
924 SLICE99_DEF_TYPED(U32Slice99, uint32_t);
925 #endif
926 
927 #ifdef UINT64_MAX
928 SLICE99_DEF_TYPED(U64Slice99, uint64_t);
929 #endif
930 // } (Unsigned integers)
931 
932 // Signed integers {
933 #ifdef INT8_MAX
934 SLICE99_DEF_TYPED(I8Slice99, int8_t);
935 #endif
936 
937 #ifdef INT16_MAX
938 SLICE99_DEF_TYPED(I16Slice99, int16_t);
939 #endif
940 
941 #ifdef INT32_MAX
942 SLICE99_DEF_TYPED(I32Slice99, int32_t);
943 #endif
944 
945 #ifdef INT64_MAX
946 SLICE99_DEF_TYPED(I64Slice99, int64_t);
947 #endif
948 // } (Signed integers)
949 
953 inline static SLICE99_WARN_UNUSED_RESULT CharSlice99 CharSlice99_from_str(char *str) {
954  return (CharSlice99)SLICE99_TO_TYPED(Slice99_from_str(str));
955 }
956 
960 inline 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 
1021 inline static SLICE99_WARN_UNUSED_RESULT SLICE99_FORMAT_HINT_2_0 CharSlice99
1022 CharSlice99_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 
1035 inline static SLICE99_WARN_UNUSED_RESULT SLICE99_FORMAT_HINT_2_3 CharSlice99
1036 CharSlice99_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 
1049 inline static SLICE99_WARN_UNUSED_RESULT SLICE99_FORMAT_HINT_3_0 CharSlice99
1050 CharSlice99_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 
1060 inline static SLICE99_WARN_UNUSED_RESULT SLICE99_FORMAT_HINT_3_4 CharSlice99
1061 CharSlice99_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 SLICE99_CONST void * Slice99_last(Slice99 self)
Computes a pointer to the last item.
Definition: slice99.h:599
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 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 char * CharSlice99_c_str(CharSlice99 self, char out[restrict])
The same as Slice99_c_str.
Definition: slice99.h:960
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_CONST void * Slice99_get(Slice99 self, ptrdiff_t i)
Computes a pointer to the i -indexed item.
Definition: slice99.h:579
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 Slice99_advance(Slice99 self, ptrdiff_t offset)
Advances self by offset items.
Definition: slice99.h:633
static SLICE99_WARN_UNUSED_RESULT SLICE99_CONST void * Slice99_first(Slice99 self)
Computes a pointer to the first item.
Definition: slice99.h:588
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 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 bool Slice99_is_empty(Slice99 self)
Checks whether self is empty or not.
Definition: slice99.h:557
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