Azure SDK for Embedded C
az_span.h
Go to the documentation of this file.
1 // Copyright (c) Microsoft Corporation. All rights reserved.
2 // SPDX-License-Identifier: MIT
3 
16 #ifndef _az_SPAN_H
17 #define _az_SPAN_H
18 
19 #include <azure/core/az_result.h>
20 
21 #include <stdbool.h>
22 #include <stddef.h>
23 #include <stdint.h>
24 #include <string.h>
25 
26 #include <azure/core/_az_cfg_prefix.h>
27 
32 typedef struct
33 {
34  struct
35  {
36  uint8_t* ptr;
37  int32_t size; // size must be >= 0
38  } _internal;
39 } az_span;
40 
41 /******************************** SPAN GETTERS */
42 
48 AZ_NODISCARD AZ_INLINE uint8_t* az_span_ptr(az_span span) { return span._internal.ptr; }
49 
55 AZ_NODISCARD AZ_INLINE int32_t az_span_size(az_span span) { return span._internal.size; }
56 
57 /******************************** CONSTRUCTORS */
58 
67 // Note: If you are modifying this function, make sure to modify the non-inline version in the
68 // az_span.c file as well, and the _az_ version right below.
69 #ifdef AZ_NO_PRECONDITION_CHECKING
70 AZ_NODISCARD AZ_INLINE az_span az_span_create(uint8_t* ptr, int32_t size)
71 {
72  return (az_span){ ._internal = { .ptr = ptr, .size = size } };
73 }
74 #else
75 AZ_NODISCARD az_span az_span_create(uint8_t* ptr, int32_t size);
76 #endif // AZ_NO_PRECONDITION_CHECKING
77 
84 #define AZ_SPAN_LITERAL_EMPTY \
85  { \
86  ._internal = {.ptr = NULL, .size = 0 } \
87  }
88 
95 #define AZ_SPAN_EMPTY (az_span) AZ_SPAN_LITERAL_EMPTY
96 
97 // Returns the size (in bytes) of a literal string.
98 // Note: Concatenating "" to S produces a compiler error if S is not a literal string
99 // The stored string's length does not include the \0 terminator.
100 #define _az_STRING_LITERAL_LEN(S) (sizeof(S "") - 1)
101 
112 #define AZ_SPAN_LITERAL_FROM_STR(STRING_LITERAL) \
113  { \
114  ._internal = { \
115  .ptr = (uint8_t*)(STRING_LITERAL), \
116  .size = _az_STRING_LITERAL_LEN(STRING_LITERAL), \
117  }, \
118  }
119 
132 #define AZ_SPAN_FROM_STR(STRING_LITERAL) (az_span) AZ_SPAN_LITERAL_FROM_STR(STRING_LITERAL)
133 
134 // Returns 1 if the address of the array is equal to the address of its 1st element.
135 // Returns 0 for anything that is not an array (for example any arbitrary pointer).
136 #define _az_IS_ARRAY(array) (((void*)&(array)) == ((void*)(&(array)[0])))
137 
138 // Returns 1 if the element size of the array is 1 (which is only true for byte arrays such as
139 // uint8_t[] and char[]).
140 // Returns 0 for any other element size (for example int32_t[]).
141 #define _az_IS_BYTE_ARRAY(array) ((sizeof((array)[0]) == 1) && _az_IS_ARRAY(array))
142 
155 // Force a division by 0 that gets detected by compilers for anything that isn't a byte array.
156 #define AZ_SPAN_FROM_BUFFER(BYTE_BUFFER) \
157  az_span_create( \
158  (uint8_t*)(BYTE_BUFFER), (sizeof(BYTE_BUFFER) / (_az_IS_BYTE_ARRAY(BYTE_BUFFER) ? 1 : 0)))
159 
168 AZ_NODISCARD az_span az_span_create_from_str(char* str);
169 
170 /****************************** SPAN MANIPULATION */
171 
184 AZ_NODISCARD az_span az_span_slice(az_span span, int32_t start_index, int32_t end_index);
185 
196 AZ_NODISCARD az_span az_span_slice_to_end(az_span span, int32_t start_index);
197 
207 AZ_NODISCARD AZ_INLINE bool az_span_is_content_equal(az_span span1, az_span span2)
208 {
209  int32_t span1_size = az_span_size(span1);
210  int32_t span2_size = az_span_size(span2);
211 
212  // Make sure to avoid passing a null pointer to memcmp, which is considered undefined.
213  // We assume that if the size is non-zero, then the pointer can't be null.
214  if (span1_size == 0)
215  {
216  // Two empty spans are considered equal, even if their pointers are different.
217  return span2_size == 0;
218  }
219 
220  // If span2_size == 0, then the first condition which compares sizes will be false, since we
221  // checked the size of span1 above. And due to short-circuiting we won't be calling memcmp anyway.
222  // Therefore, we don't need to check for that explicitly.
223  return span1_size == span2_size
224  && memcmp(az_span_ptr(span1), az_span_ptr(span2), (size_t)span1_size) == 0;
225 }
226 
239 
254 void az_span_to_str(char* destination, int32_t destination_max_size, az_span source);
255 
269 AZ_NODISCARD int32_t az_span_find(az_span source, az_span target);
270 
271 /****************************** SPAN COPYING */
272 
289 az_span az_span_copy(az_span destination, az_span source);
290 
303 az_span az_span_copy_u8(az_span destination, uint8_t byte);
304 
311 AZ_INLINE void az_span_fill(az_span destination, uint8_t value)
312 {
313  // NOLINTNEXTLINE(clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling)
314  memset(az_span_ptr(destination), value, (size_t)az_span_size(destination));
315 }
316 
317 /****************************** SPAN PARSING AND FORMATTING */
318 
330 AZ_NODISCARD az_result az_span_atou64(az_span source, uint64_t* out_number);
331 
343 AZ_NODISCARD az_result az_span_atoi64(az_span source, int64_t* out_number);
344 
356 AZ_NODISCARD az_result az_span_atou32(az_span source, uint32_t* out_number);
357 
369 AZ_NODISCARD az_result az_span_atoi32(az_span source, int32_t* out_number);
370 
385 AZ_NODISCARD az_result az_span_atod(az_span source, double* out_number);
386 
402 AZ_NODISCARD az_result az_span_i32toa(az_span destination, int32_t source, az_span* out_span);
403 
419 AZ_NODISCARD az_result az_span_u32toa(az_span destination, uint32_t source, az_span* out_span);
420 
436 AZ_NODISCARD az_result az_span_i64toa(az_span destination, int64_t source, az_span* out_span);
437 
453 AZ_NODISCARD az_result az_span_u64toa(az_span destination, uint64_t source, az_span* out_span);
454 
483 AZ_NODISCARD az_result
484 az_span_dtoa(az_span destination, double source, int32_t fractional_digits, az_span* out_span);
485 
486 /****************************** NON-CONTIGUOUS SPAN */
487 
493 typedef struct
494 {
498 
501  int32_t bytes_used;
502 
507 
532  az_span_allocator_context* allocator_context,
533  az_span* out_next_destination);
534 
535 #include <azure/core/_az_cfg_suffix.h>
536 
537 #endif // _az_SPAN_H
az_result.h
Definition of az_result and helper functions.
az_span_allocator_context::user_context
void * user_context
Definition: az_span.h:497
az_span_allocator_context::minimum_required_size
int32_t minimum_required_size
Definition: az_span.h:505
az_span_create_from_str
AZ_NODISCARD az_span az_span_create_from_str(char *str)
Returns an az_span from a 0-terminated array of bytes (chars).
az_span_atoi32
AZ_NODISCARD az_result az_span_atoi32(az_span source, int32_t *out_number)
Parses an az_span containing ASCII digits into an int32_t number.
az_span_create
AZ_NODISCARD az_span az_span_create(uint8_t *ptr, int32_t size)
Returns an az_span over a byte buffer.
az_result
int32_t az_result
The type represents the various success and error conditions.
Definition: az_result.h:46
az_span_fill
AZ_INLINE void az_span_fill(az_span destination, uint8_t value)
Fills all the bytes of the destination az_span with the specified value.
Definition: az_span.h:311
az_span_allocator_context::bytes_used
int32_t bytes_used
Definition: az_span.h:501
az_span_slice_to_end
AZ_NODISCARD az_span az_span_slice_to_end(az_span span, int32_t start_index)
Returns a new az_span which is a sub-span of the specified span.
az_span_copy
az_span az_span_copy(az_span destination, az_span source)
Copies the content of the source az_span to the destination az_span.
az_span_ptr
AZ_NODISCARD AZ_INLINE uint8_t * az_span_ptr(az_span span)
Returns the az_span byte buffer's starting memory address.
Definition: az_span.h:48
az_span_u32toa
AZ_NODISCARD az_result az_span_u32toa(az_span destination, uint32_t source, az_span *out_span)
Converts an uint32_t into its digit characters (base 10) and copies them to the destination az_span s...
az_span_allocator_fn
az_result(* az_span_allocator_fn)(az_span_allocator_context *allocator_context, az_span *out_next_destination)
Defines the signature of the callback function that the caller must implement to provide the potentia...
Definition: az_span.h:531
az_span_i32toa
AZ_NODISCARD az_result az_span_i32toa(az_span destination, int32_t source, az_span *out_span)
Converts an int32_t into its digit characters (base 10) and copies them to the destination az_span st...
az_span_slice
AZ_NODISCARD az_span az_span_slice(az_span span, int32_t start_index, int32_t end_index)
Returns a new az_span which is a sub-span of the specified span.
az_span_find
AZ_NODISCARD int32_t az_span_find(az_span source, az_span target)
Searches for target in source, returning an az_span within source if it finds it.
az_span_atou32
AZ_NODISCARD az_result az_span_atou32(az_span source, uint32_t *out_number)
Parses an az_span containing ASCII digits into a uint32_t number.
az_span_allocator_context
Defines a container of required and user-defined fields that provide the necessary information and pa...
Definition: az_span.h:494
az_span_to_str
void az_span_to_str(char *destination, int32_t destination_max_size, az_span source)
Copies a source az_span containing a string (that is not 0-terminated) to a destination char buffer a...
az_span_dtoa
AZ_NODISCARD az_result az_span_dtoa(az_span destination, double source, int32_t fractional_digits, az_span *out_span)
Converts a double into its digit characters (base 10 decimal notation) and copies them to the destina...
az_span_is_content_equal_ignoring_case
AZ_NODISCARD bool az_span_is_content_equal_ignoring_case(az_span span1, az_span span2)
Determines whether two spans are equal by comparing their characters, except for casing.
az_span_atod
AZ_NODISCARD az_result az_span_atod(az_span source, double *out_number)
Parses an az_span containing ASCII digits into a double number.
az_span_u64toa
AZ_NODISCARD az_result az_span_u64toa(az_span destination, uint64_t source, az_span *out_span)
Converts a uint64_t into its digit characters (base 10) and copies them to the destination az_span st...
az_span_atou64
AZ_NODISCARD az_result az_span_atou64(az_span source, uint64_t *out_number)
Parses an az_span containing ASCII digits into a uint64_t number.
az_span_size
AZ_NODISCARD AZ_INLINE int32_t az_span_size(az_span span)
Returns the number of bytes within the az_span.
Definition: az_span.h:55
az_span_atoi64
AZ_NODISCARD az_result az_span_atoi64(az_span source, int64_t *out_number)
Parses an az_span containing ASCII digits into an int64_t number.
az_span_i64toa
AZ_NODISCARD az_result az_span_i64toa(az_span destination, int64_t source, az_span *out_span)
Converts an int64_t into its digit characters (base 10) and copies them to the destination az_span st...
az_span_copy_u8
az_span az_span_copy_u8(az_span destination, uint8_t byte)
Copies the uint8_t byte to the destination at its 0-th index.
az_span
Represents a "view" over a byte buffer that represents a contiguous region of memory....
Definition: az_span.h:33
az_span_is_content_equal
AZ_NODISCARD AZ_INLINE bool az_span_is_content_equal(az_span span1, az_span span2)
Determines whether two spans are equal by comparing their bytes.
Definition: az_span.h:207