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_EMPTY \
85  (az_span) \
86  { \
87  ._internal = {.ptr = NULL, .size = 0 } \
88  }
89 
90 // Returns the size (in bytes) of a literal string.
91 // Note: Concatenating "" to S produces a compiler error if S is not a literal string
92 // The stored string's length does not include the \0 terminator.
93 #define _az_STRING_LITERAL_LEN(S) (sizeof(S "") - 1)
94 
105 #define AZ_SPAN_LITERAL_FROM_STR(STRING_LITERAL) \
106  { \
107  ._internal = { \
108  .ptr = (uint8_t*)(STRING_LITERAL), \
109  .size = _az_STRING_LITERAL_LEN(STRING_LITERAL), \
110  }, \
111  }
112 
125 #define AZ_SPAN_FROM_STR(STRING_LITERAL) (az_span) AZ_SPAN_LITERAL_FROM_STR(STRING_LITERAL)
126 
127 // Returns 1 if the address of the array is equal to the address of its 1st element.
128 // Returns 0 for anything that is not an array (for example any arbitrary pointer).
129 #define _az_IS_ARRAY(array) (((void*)&(array)) == ((void*)(&(array)[0])))
130 
131 // Returns 1 if the element size of the array is 1 (which is only true for byte arrays such as
132 // uint8_t[] and char[]).
133 // Returns 0 for any other element size (for example int32_t[]).
134 #define _az_IS_BYTE_ARRAY(array) ((sizeof((array)[0]) == 1) && _az_IS_ARRAY(array))
135 
148 // Force a division by 0 that gets detected by compilers for anything that isn't a byte array.
149 #define AZ_SPAN_FROM_BUFFER(BYTE_BUFFER) \
150  az_span_create( \
151  (uint8_t*)(BYTE_BUFFER), (sizeof(BYTE_BUFFER) / (_az_IS_BYTE_ARRAY(BYTE_BUFFER) ? 1 : 0)))
152 
161 AZ_NODISCARD az_span az_span_create_from_str(char* str);
162 
163 /****************************** SPAN MANIPULATION */
164 
177 AZ_NODISCARD az_span az_span_slice(az_span span, int32_t start_index, int32_t end_index);
178 
189 AZ_NODISCARD az_span az_span_slice_to_end(az_span span, int32_t start_index);
190 
200 AZ_NODISCARD AZ_INLINE bool az_span_is_content_equal(az_span span1, az_span span2)
201 {
202  int32_t span1_size = az_span_size(span1);
203  int32_t span2_size = az_span_size(span2);
204 
205  // Make sure to avoid passing a null pointer to memcmp, which is considered undefined.
206  // We assume that if the size is non-zero, then the pointer can't be null.
207  if (span1_size == 0)
208  {
209  // Two empty spans are considered equal, even if their pointers are different.
210  return span2_size == 0;
211  }
212 
213  // If span2_size == 0, then the first condition which compares sizes will be false, since we
214  // checked the size of span1 above. And due to short-circuiting we won't be calling memcmp anyway.
215  // Therefore, we don't need to check for that explicitly.
216  return span1_size == span2_size
217  && memcmp(az_span_ptr(span1), az_span_ptr(span2), (size_t)span1_size) == 0;
218 }
219 
232 
247 void az_span_to_str(char* destination, int32_t destination_max_size, az_span source);
248 
262 AZ_NODISCARD int32_t az_span_find(az_span source, az_span target);
263 
264 /****************************** SPAN COPYING */
265 
282 az_span az_span_copy(az_span destination, az_span source);
283 
296 az_span az_span_copy_u8(az_span destination, uint8_t byte);
297 
304 AZ_INLINE void az_span_fill(az_span destination, uint8_t value)
305 {
306  // NOLINTNEXTLINE(clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling)
307  memset(az_span_ptr(destination), value, (size_t)az_span_size(destination));
308 }
309 
310 /****************************** SPAN PARSING AND FORMATTING */
311 
323 AZ_NODISCARD az_result az_span_atou64(az_span source, uint64_t* out_number);
324 
336 AZ_NODISCARD az_result az_span_atoi64(az_span source, int64_t* out_number);
337 
349 AZ_NODISCARD az_result az_span_atou32(az_span source, uint32_t* out_number);
350 
362 AZ_NODISCARD az_result az_span_atoi32(az_span source, int32_t* out_number);
363 
378 AZ_NODISCARD az_result az_span_atod(az_span source, double* out_number);
379 
395 AZ_NODISCARD az_result az_span_i32toa(az_span destination, int32_t source, az_span* out_span);
396 
412 AZ_NODISCARD az_result az_span_u32toa(az_span destination, uint32_t source, az_span* out_span);
413 
429 AZ_NODISCARD az_result az_span_i64toa(az_span destination, int64_t source, az_span* out_span);
430 
446 AZ_NODISCARD az_result az_span_u64toa(az_span destination, uint64_t source, az_span* out_span);
447 
476 AZ_NODISCARD az_result
477 az_span_dtoa(az_span destination, double source, int32_t fractional_digits, az_span* out_span);
478 
479 /****************************** NON-CONTIGUOUS SPAN */
480 
486 typedef struct
487 {
491 
494  int32_t bytes_used;
495 
500 
525  az_span_allocator_context* allocator_context,
526  az_span* out_next_destination);
527 
528 #include <azure/core/_az_cfg_suffix.h>
529 
530 #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:490
az_span_allocator_context::minimum_required_size
int32_t minimum_required_size
Definition: az_span.h:498
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:45
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:304
az_span_allocator_context::bytes_used
int32_t bytes_used
Definition: az_span.h:494
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:524
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:487
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:200