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  ((void \
395  *)((char *)SLICE99_MEMCPY((buffer), (ptr), sizeof((ptr)[0]) * (len)) + sizeof((ptr)[0]) * (len)))
396 
397 #ifdef UINT8_MAX
398 
406 #define SLICE99_TO_OCTETS(obj) U8Slice99_new((uint8_t *)&(obj), sizeof(obj))
407 
408 #endif
409 
416 #define Slice99_from_array(...) \
417  Slice99_new((void *)(__VA_ARGS__), sizeof((__VA_ARGS__)[0]), SLICE99_ARRAY_LEN(__VA_ARGS__))
418 
433 #define Slice99_typed_from_array(...) \
434  { .ptr = (__VA_ARGS__), .len = SLICE99_ARRAY_LEN(__VA_ARGS__) }
435 
444 #define Slice99_from_typed_ptr(ptr, len) Slice99_new(ptr, sizeof(*(ptr)), len)
445 
454 typedef struct {
458  void *ptr;
459 
463  size_t item_size;
464 
468  size_t len;
469 } Slice99;
470 
481 inline static SLICE99_WARN_UNUSED_RESULT Slice99
482 Slice99_new(void *ptr, size_t item_size, size_t len) {
483  SLICE99_ASSERT(ptr);
484  SLICE99_ASSERT(item_size > 0);
485 
486  return (Slice99){.ptr = ptr, .item_size = item_size, .len = len};
487 }
488 
496 inline static SLICE99_WARN_UNUSED_RESULT Slice99 Slice99_from_str(char *str) {
497  SLICE99_ASSERT(str);
498 
499  return Slice99_new(str, sizeof(char), SLICE99_STRLEN(str));
500 }
501 
514 inline static SLICE99_WARN_UNUSED_RESULT Slice99
515 Slice99_from_ptrdiff(void *start, void *end, size_t item_size) {
516  SLICE99_ASSERT(start);
517  SLICE99_ASSERT(end);
518 
519  const ptrdiff_t diff = (char *)end - (char *)start;
520 
521  SLICE99_ASSERT(diff >= 0);
522  SLICE99_ASSERT((size_t)diff % item_size == 0);
523 
524  return Slice99_new(start, item_size, (size_t)(diff / (ptrdiff_t)item_size));
525 }
526 
534 inline static SLICE99_WARN_UNUSED_RESULT Slice99 Slice99_empty(size_t item_size) {
535  SLICE99_ASSERT(item_size > 0);
536  return Slice99_new("", item_size, 0);
537 }
538 
545 inline static SLICE99_WARN_UNUSED_RESULT Slice99 Slice99_update_len(Slice99 self, size_t new_len) {
546  return Slice99_new(self.ptr, self.item_size, new_len);
547 }
548 
556 inline static SLICE99_WARN_UNUSED_RESULT SLICE99_CONST bool Slice99_is_empty(Slice99 self) {
557  return self.len == 0;
558 }
559 
565 inline static SLICE99_WARN_UNUSED_RESULT SLICE99_CONST size_t Slice99_size(Slice99 self) {
566  return self.item_size * self.len;
567 }
568 
577 inline static SLICE99_WARN_UNUSED_RESULT SLICE99_CONST void *
578 Slice99_get(Slice99 self, ptrdiff_t i) {
579  return (void *)((char *)self.ptr + i * (ptrdiff_t)self.item_size);
580 }
581 
587 inline static SLICE99_WARN_UNUSED_RESULT SLICE99_CONST void *Slice99_first(Slice99 self) {
588  return Slice99_get(self, 0);
589 }
590 
598 inline static SLICE99_WARN_UNUSED_RESULT SLICE99_CONST void *Slice99_last(Slice99 self) {
599  return Slice99_get(self, (ptrdiff_t)self.len - 1);
600 }
601 
613 inline static SLICE99_WARN_UNUSED_RESULT Slice99
614 Slice99_sub(Slice99 self, ptrdiff_t start_idx, ptrdiff_t end_idx) {
615  SLICE99_ASSERT(start_idx <= end_idx);
616 
617  return Slice99_from_ptrdiff(
618  Slice99_get(self, start_idx), Slice99_get(self, end_idx), self.item_size);
619 }
620 
632 inline static SLICE99_WARN_UNUSED_RESULT Slice99 Slice99_advance(Slice99 self, ptrdiff_t offset) {
633  return Slice99_sub(self, offset, (ptrdiff_t)self.len);
634 }
635 
644 inline static SLICE99_WARN_UNUSED_RESULT bool Slice99_primitive_eq(Slice99 lhs, Slice99 rhs) {
645  return Slice99_size(lhs) != Slice99_size(rhs)
646  ? false
647  : SLICE99_MEMCMP(lhs.ptr, rhs.ptr, Slice99_size(lhs)) == 0;
648 }
649 
664 inline static SLICE99_WARN_UNUSED_RESULT bool
665 Slice99_eq(Slice99 lhs, Slice99 rhs, int (*cmp)(const void *, const void *)) {
666  SLICE99_ASSERT(lhs.item_size == rhs.item_size);
667  SLICE99_ASSERT(cmp);
668 
669  if (lhs.len != rhs.len) {
670  return false;
671  }
672 
673  for (ptrdiff_t i = 0; i < (ptrdiff_t)lhs.len; i++) {
674  if (cmp(Slice99_get(lhs, i), Slice99_get(rhs, i)) != 0) {
675  return false;
676  }
677  }
678 
679  return true;
680 }
681 
692 inline static SLICE99_WARN_UNUSED_RESULT bool
694  return Slice99_size(self) < Slice99_size(prefix)
695  ? false
696  : Slice99_primitive_eq(Slice99_sub(self, 0, (ptrdiff_t)prefix.len), prefix);
697 }
698 
713 inline static SLICE99_WARN_UNUSED_RESULT bool
714 Slice99_starts_with(Slice99 self, Slice99 prefix, int (*cmp)(const void *, const void *)) {
715  SLICE99_ASSERT(self.item_size == prefix.item_size);
716  SLICE99_ASSERT(cmp);
717 
718  return self.len < prefix.len
719  ? false
720  : Slice99_eq(Slice99_sub(self, 0, (ptrdiff_t)prefix.len), prefix, cmp);
721 }
722 
733 inline static SLICE99_WARN_UNUSED_RESULT bool
735  return Slice99_size(self) < Slice99_size(postfix)
736  ? false
738  Slice99_sub(
739  self, (ptrdiff_t)self.len - (ptrdiff_t)postfix.len, (ptrdiff_t)self.len),
740  postfix);
741 }
742 
757 inline static SLICE99_WARN_UNUSED_RESULT bool
758 Slice99_ends_with(Slice99 self, Slice99 postfix, int (*cmp)(const void *, const void *)) {
759  SLICE99_ASSERT(self.item_size == postfix.item_size);
760  SLICE99_ASSERT(cmp);
761 
762  return self.len < postfix.len
763  ? false
764  : Slice99_eq(
765  Slice99_sub(
766  self, (ptrdiff_t)self.len - (ptrdiff_t)postfix.len, (ptrdiff_t)self.len),
767  postfix, cmp);
768 }
769 
776 inline static void Slice99_copy(Slice99 self, Slice99 other) {
777  SLICE99_MEMMOVE(self.ptr, other.ptr, Slice99_size(other));
778 }
779 
785 inline static void Slice99_copy_non_overlapping(Slice99 self, Slice99 other) {
786  SLICE99_MEMCPY(self.ptr, other.ptr, Slice99_size(other));
787 }
788 
801 inline static void Slice99_swap(Slice99 self, ptrdiff_t lhs, ptrdiff_t rhs, void *restrict backup) {
802  SLICE99_ASSERT(backup);
803 
804  SLICE99_MEMCPY((backup), Slice99_get(self, lhs), (self).item_size);
805  SLICE99_MEMCPY(Slice99_get(self, lhs), Slice99_get(self, rhs), (self).item_size);
806  SLICE99_MEMCPY(Slice99_get(self, rhs), (backup), (self).item_size);
807 }
808 
822 inline static void Slice99_swap_with_slice(Slice99 self, Slice99 other, void *restrict backup) {
823  SLICE99_ASSERT(self.len == other.len);
824  SLICE99_ASSERT(self.item_size == other.item_size);
825 
826  for (ptrdiff_t i = 0; i < (ptrdiff_t)self.len; i++) {
827  SLICE99_MEMCPY(backup, Slice99_get(self, i), self.item_size);
828  SLICE99_MEMCPY(Slice99_get(self, i), Slice99_get(other, i), self.item_size);
829  SLICE99_MEMCPY(Slice99_get(other, i), backup, self.item_size);
830  }
831 }
832 
842 inline static void Slice99_reverse(Slice99 self, void *restrict backup) {
843  SLICE99_ASSERT(backup);
844 
845  for (ptrdiff_t i = 0; i < (ptrdiff_t)self.len / 2; i++) {
846  Slice99_swap(self, i, (ptrdiff_t)self.len - i - 1, backup);
847  }
848 }
849 
863 inline static void
864 Slice99_split_at(Slice99 self, size_t i, Slice99 *restrict lhs, Slice99 *restrict rhs) {
865  SLICE99_ASSERT(i <= self.len);
866  SLICE99_ASSERT(lhs);
867  SLICE99_ASSERT(rhs);
868 
869  *lhs = Slice99_sub(self, 0, (ptrdiff_t)i);
870  *rhs = Slice99_sub(self, (ptrdiff_t)i, (ptrdiff_t)self.len);
871 }
872 
884 inline static char *Slice99_c_str(Slice99 self, char out[restrict]) {
885  SLICE99_ASSERT(out);
886 
887  SLICE99_MEMCPY(out, self.ptr, Slice99_size(self));
888  out[Slice99_size(self)] = '\0';
889  return out;
890 }
891 
892 SLICE99_DEF_TYPED(CharSlice99, char);
893 SLICE99_DEF_TYPED(SCharSlice99, signed char);
894 SLICE99_DEF_TYPED(UCharSlice99, unsigned char);
895 
896 SLICE99_DEF_TYPED(ShortSlice99, short);
897 SLICE99_DEF_TYPED(UShortSlice99, unsigned short);
898 
899 SLICE99_DEF_TYPED(IntSlice99, int);
900 SLICE99_DEF_TYPED(UIntSlice99, unsigned int);
901 
902 SLICE99_DEF_TYPED(LongSlice99, long);
903 SLICE99_DEF_TYPED(ULongSlice99, unsigned long);
904 SLICE99_DEF_TYPED(LongLongSlice99, long long);
905 SLICE99_DEF_TYPED(ULongLongSlice99, unsigned long long);
906 
907 SLICE99_DEF_TYPED(FloatSlice99, float);
908 SLICE99_DEF_TYPED(DoubleSlice99, double);
909 SLICE99_DEF_TYPED(LongDoubleSlice99, long double);
910 
911 SLICE99_DEF_TYPED(BoolSlice99, _Bool);
912 
913 // Unsigned integers {
914 #ifdef UINT8_MAX
915 SLICE99_DEF_TYPED(U8Slice99, uint8_t);
916 #endif
917 
918 #ifdef UINT16_MAX
919 SLICE99_DEF_TYPED(U16Slice99, uint16_t);
920 #endif
921 
922 #ifdef UINT32_MAX
923 SLICE99_DEF_TYPED(U32Slice99, uint32_t);
924 #endif
925 
926 #ifdef UINT64_MAX
927 SLICE99_DEF_TYPED(U64Slice99, uint64_t);
928 #endif
929 // } (Unsigned integers)
930 
931 // Signed integers {
932 #ifdef INT8_MAX
933 SLICE99_DEF_TYPED(I8Slice99, int8_t);
934 #endif
935 
936 #ifdef INT16_MAX
937 SLICE99_DEF_TYPED(I16Slice99, int16_t);
938 #endif
939 
940 #ifdef INT32_MAX
941 SLICE99_DEF_TYPED(I32Slice99, int32_t);
942 #endif
943 
944 #ifdef INT64_MAX
945 SLICE99_DEF_TYPED(I64Slice99, int64_t);
946 #endif
947 // } (Signed integers)
948 
952 inline static SLICE99_WARN_UNUSED_RESULT CharSlice99 CharSlice99_from_str(char *str) {
953  return (CharSlice99)SLICE99_TO_TYPED(Slice99_from_str(str));
954 }
955 
959 inline static char *CharSlice99_c_str(CharSlice99 self, char out[restrict]) {
960  return Slice99_c_str(SLICE99_TO_UNTYPED(self), out);
961 }
962 
969 #define CharSlice99_alloca_c_str(self) CharSlice99_c_str((self), alloca((self).len + 1))
970 
971 #ifndef SLICE99_DISABLE_STDIO
972 
973 #ifndef SLICE99_VSPRINTF
974 #include <stdio.h>
977 #define SLICE99_VSPRINTF vsprintf
978 #endif
979 
980 #ifndef SLICE99_VSNPRINTF
981 #include <stdio.h>
984 #define SLICE99_VSNPRINTF vsnprintf
985 #endif
986 
987 #ifndef SLICE99_SNPRINTF
988 #include <stdio.h>
991 #define SLICE99_SNPRINTF snprintf
992 #endif
993 
994 #ifndef DOXYGEN_IGNORE
995 
996 // Doxygen fails to parse function declarations with function-like macro invocations.
997 
998 #define SLICE99_FORMAT_HINT_2_0 SLICE99_FORMAT_HINT(printf, 2, 0)
999 #define SLICE99_FORMAT_HINT_2_3 SLICE99_FORMAT_HINT(printf, 2, 3)
1000 #define SLICE99_FORMAT_HINT_3_0 SLICE99_FORMAT_HINT(printf, 3, 0)
1001 #define SLICE99_FORMAT_HINT_3_4 SLICE99_FORMAT_HINT(printf, 3, 4)
1002 
1003 #endif // DOXYGEN_IGNORE
1004 
1020 inline static SLICE99_WARN_UNUSED_RESULT SLICE99_FORMAT_HINT_2_0 CharSlice99
1021 CharSlice99_vfmt(char out[restrict], const char *restrict fmt, va_list list) {
1022  SLICE99_ASSERT(out);
1023  SLICE99_ASSERT(fmt);
1024 
1025  SLICE99_VSPRINTF(out, fmt, list);
1026  return CharSlice99_from_str(out);
1027 }
1028 
1034 inline static SLICE99_WARN_UNUSED_RESULT SLICE99_FORMAT_HINT_2_3 CharSlice99
1035 CharSlice99_fmt(char out[restrict], const char *restrict fmt, ...) {
1036  va_list ap;
1037  va_start(ap, fmt);
1038  const CharSlice99 result = CharSlice99_vfmt(out, fmt, ap);
1039  va_end(ap);
1040  return result;
1041 }
1042 
1048 inline static SLICE99_WARN_UNUSED_RESULT SLICE99_FORMAT_HINT_3_0 CharSlice99
1049 CharSlice99_vnfmt(char out[restrict], size_t bufsz, const char *restrict fmt, va_list list) {
1050  SLICE99_VSNPRINTF(out, bufsz, fmt, list);
1051  return CharSlice99_from_str(out);
1052 }
1053 
1059 inline static SLICE99_WARN_UNUSED_RESULT SLICE99_FORMAT_HINT_3_4 CharSlice99
1060 CharSlice99_nfmt(char out[restrict], size_t bufsz, const char *restrict fmt, ...) {
1061  va_list ap;
1062  va_start(ap, fmt);
1063  const CharSlice99 result = CharSlice99_vnfmt(out, bufsz, fmt, ap);
1064  va_end(ap);
1065  return result;
1066 }
1067 
1068 #ifndef DOXYGEN_IGNORE
1069 
1070 #undef SLICE99_FORMAT_HINT_2_0
1071 #undef SLICE99_FORMAT_HINT_2_3
1072 #undef SLICE99_FORMAT_HINT_3_0
1073 #undef SLICE99_FORMAT_HINT_3_4
1074 
1075 #endif // DOXYGEN_IGNORE
1076 
1085 #define CharSlice99_alloca_fmt(fmt, ...) \
1086  CharSlice99_fmt(alloca(SLICE99_SNPRINTF(NULL, 0, (fmt), __VA_ARGS__) + 1), (fmt), __VA_ARGS__)
1087 
1088 #endif // SLICE99_DISABLE_STDIO
1089 
1090 #endif // SLICE99_H
#define SLICE99_VSPRINTF
Like vsprintf.
Definition: slice99.h:977
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:1035
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:545
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:801
static SLICE99_WARN_UNUSED_RESULT SLICE99_CONST void * Slice99_last(Slice99 self)
Computes a pointer to the last item.
Definition: slice99.h:598
static SLICE99_WARN_UNUSED_RESULT CharSlice99 CharSlice99_from_str(char *str)
The same as Slice99_from_str.
Definition: slice99.h:952
static void Slice99_split_at(Slice99 self, size_t i, Slice99 *restrict lhs, Slice99 *restrict rhs)
Splits self into two parts.
Definition: slice99.h:864
#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:565
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:758
#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:482
#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:693
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:1021
static void Slice99_reverse(Slice99 self, void *restrict backup)
Reverses the order of items in self.
Definition: slice99.h:842
#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:822
#define SLICE99_VSNPRINTF
Like vsnprintf.
Definition: slice99.h:984
#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:644
static char * CharSlice99_c_str(CharSlice99 self, char out[restrict])
The same as Slice99_c_str.
Definition: slice99.h:959
static SLICE99_WARN_UNUSED_RESULT Slice99 Slice99_from_str(char *str)
Constructs a slice from str.
Definition: slice99.h:496
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:578
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:1049
#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:665
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:714
static SLICE99_WARN_UNUSED_RESULT Slice99 Slice99_advance(Slice99 self, ptrdiff_t offset)
Advances self by offset items.
Definition: slice99.h:632
static SLICE99_WARN_UNUSED_RESULT SLICE99_CONST void * Slice99_first(Slice99 self)
Computes a pointer to the first item.
Definition: slice99.h:587
static char * Slice99_c_str(Slice99 self, char out[restrict])
Copies self to out and appends '\0' to the end.
Definition: slice99.h:884
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:785
static SLICE99_WARN_UNUSED_RESULT Slice99 Slice99_empty(size_t item_size)
Constructs an empty slice.
Definition: slice99.h:534
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:734
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:1060
static SLICE99_WARN_UNUSED_RESULT SLICE99_CONST bool Slice99_is_empty(Slice99 self)
Checks whether self is empty or not.
Definition: slice99.h:556
static void Slice99_copy(Slice99 self, Slice99 other)
Copies other to the beginning of self, byte-by-byte.
Definition: slice99.h:776
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:515
#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:614
A slice of some array.
Definition: slice99.h:454
void * ptr
The pointer to data.
Definition: slice99.h:458
size_t item_size
The size of each item in the array addressed by ptr.
Definition: slice99.h:463
size_t len
The count of items in the array addressed by ptr.
Definition: slice99.h:468