le_basics.h

Go to the documentation of this file.
1 /**
2  * @page c_basics Basic Type and Constant Definitions
3  *
4  * Cardinal types and commonly-used constants form the basic
5  * foundation on which everything else is built. These include
6  * error codes, portable integer types, and helpful macros that make things easier to use.
7  *
8  * See @ref le_basics.h for basic cardinal types and commonly-used constants info.
9  *
10  * <HR>
11  *
12  * Copyright (C) Sierra Wireless Inc.
13  */
14 
15 
16 /** @file le_basics.h
17  *
18  * Legato @ref c_basics include file.
19  *
20  * Copyright (C) Sierra Wireless Inc.
21  */
22 
23 #ifndef LEGATO_BASICS_INCLUDE_GUARD
24 #define LEGATO_BASICS_INCLUDE_GUARD
25 
26 //--------------------------------------------------------------------------------------------------
27 /**
28  * If the compiler is armcc, allow anonymous unions, as these are useful and used
29  * quite a bit in Legato
30  */
31 //--------------------------------------------------------------------------------------------------
32 #ifdef __ARMCC_VERSION
33 #pragma anon_unions
34 #endif
35 
36 //--------------------------------------------------------------------------------------------------
37 /**
38  * Standard result codes.
39  *
40  * @note All error codes are negative integers. They allow functions with signed
41  * integers to return non-negative values when successful or standard error codes on failure.
42  * @deprecated the result code LE_NOT_POSSIBLE has been removed and replaced other
43  * error codes that are more clear.
44  */
45 //--------------------------------------------------------------------------------------------------
46 typedef enum
47 {
48  LE_OK = 0, ///< Successful.
49  LE_NOT_FOUND = -1, ///< Referenced item does not exist or could not be found.
50  LE_NOT_POSSIBLE = -2, ///< @deprecated It is not possible to perform the requested action.
51  ///< LE_NOT_POSSIBLE has been removed so attempting to use this error
52  ///< code will result in an error.
53  LE_OUT_OF_RANGE = -3, ///< An index or other value is out of range.
54  LE_NO_MEMORY = -4, ///< Insufficient memory is available.
55  LE_NOT_PERMITTED = -5, ///< Current user does not have permission to perform requested action.
56  LE_FAULT = -6, ///< Unspecified internal error.
57  LE_COMM_ERROR = -7, ///< Communications error.
58  LE_TIMEOUT = -8, ///< A time-out occurred.
59  LE_OVERFLOW = -9, ///< An overflow occurred or would have occurred.
60  LE_UNDERFLOW = -10, ///< An underflow occurred or would have occurred.
61  LE_WOULD_BLOCK = -11, ///< Would have blocked if non-blocking behaviour was not requested.
62  LE_DEADLOCK = -12, ///< Would have caused a deadlock.
63  LE_FORMAT_ERROR = -13, ///< Format error.
64  LE_DUPLICATE = -14, ///< Duplicate entry found or operation already performed.
65  LE_BAD_PARAMETER = -15, ///< Parameter is invalid.
66  LE_CLOSED = -16, ///< The resource is closed.
67  LE_BUSY = -17, ///< The resource is busy.
68  LE_UNSUPPORTED = -18, ///< The underlying resource does not support this operation.
69  LE_IO_ERROR = -19, ///< An IO operation failed.
70  LE_NOT_IMPLEMENTED = -20, ///< Unimplemented functionality.
71  LE_UNAVAILABLE = -21, ///< A transient or temporary loss of a service or resource.
72  LE_TERMINATED = -22, ///< The process, operation, data stream, session, etc. has stopped.
73  LE_IN_PROGRESS = -23, ///< The operation is in progress.
74  LE_SUSPENDED = -24, ///< The operation is suspended.
75 }
77 
78 
79 //--------------------------------------------------------------------------------------------------
80 /**
81  * ON/OFF type.
82  *
83  */
84 //--------------------------------------------------------------------------------------------------
85 typedef enum
86 {
87  LE_OFF = 0,
88  LE_ON = 1,
89 }
91 
92 
93 //--------------------------------------------------------------------------------------------------
94 /** @name Bit Masks
95  *
96  * Single byte bit definitions that can be used for bit masking.
97  * @{
98  */
99 //--------------------------------------------------------------------------------------------------
100 #define BIT0 0x01
101 #define BIT1 0x02
102 #define BIT2 0x04
103 #define BIT3 0x08
104 #define BIT4 0x10
105 #define BIT5 0x20
106 #define BIT6 0x40
107 #define BIT7 0x80
108 // @}
109 
110 //--------------------------------------------------------------------------------------------------
111 /**
112  * Find the address of a containing structure or union, based on the address of one of its members.
113  *
114  * If @c countPtr points to the @c count member of an object type
115  * @c my_class_t, then a pointer to that object should use this:
116  *
117  * @code
118  * my_class_t* myObjPtr = CONTAINER_OF(countPtr, my_class_t, count);
119  * @endcode
120  */
121 //--------------------------------------------------------------------------------------------------
122 #define CONTAINER_OF(memberPtr, type, member) \
123  ((type*)(((uint8_t*)(memberPtr))-((size_t)(&(((type*)0)->member)))))
124 
125 
126 //--------------------------------------------------------------------------------------------------
127 /**
128  * Computes number of members in an array at compile time.
129  *
130  * @warning Does NOT work for pointers to arrays.
131  *
132  * Here's a code sample:
133  *
134  * @code
135  * const char message[] = "Hello world!";
136  *
137  * size_t x = NUM_ARRAY_MEMBERS(message);
138  *
139  * printf("%lu\n", x);
140  * @endcode
141  *
142  * Will print @c 13 on a 32-bit target.
143  *
144  * But this example is @b incorrect:
145  *
146  * @code
147  * const char message[] = "Hello world!";
148  * const char* messagePtr = &message;
149  *
150  * size_t x = NUM_ARRAY_MEMBERS(messagePtr); // NO! BAD PROGRAMMER! BAD!
151  *
152  * printf("%lu\n", x);
153  * @endcode
154  */
155 //--------------------------------------------------------------------------------------------------
156 #define NUM_ARRAY_MEMBERS(array) \
157  (sizeof(array) / sizeof((array)[0]))
158 
159 
160 //--------------------------------------------------------------------------------------------------
161 /**
162  * Computes the index of a member within an array.
163  *
164  * This code sample prints out "The 'w' is at index 6.":
165  *
166  * @code
167  * const char message[] = "Hello world!";
168  * const char* charPtr;
169  * int i;
170  *
171  * for (i = 0; i < sizeof(message); i++)
172  * {
173  * if (message[i] == 'w')
174  * {
175  * charPtr = &message[i];
176  * }
177  * }
178  *
179  * printf("The 'w' is at index %"PRIuS".\n", INDEX_OF_ARRAY_MEMBER(message, charPtr));
180  * @endcode
181  **/
182 //--------------------------------------------------------------------------------------------------
183 #define INDEX_OF_ARRAY_MEMBER(array, memberPtr) \
184  ((((size_t)memberPtr) - ((size_t)array)) / sizeof(*(memberPtr)))
185 
186 
187 //--------------------------------------------------------------------------------------------------
188 /**
189  * This function takes the characters as an argument and puts quotes around them.
190  *
191  * Code sample:
192  *
193  * @code
194  * const char name[] = STRINGIZE(foo);
195  * @endcode
196  *
197  * Is seen by the compiler as
198  *
199  * @code
200  * const char name[] = "foo";
201  * @endcode
202  *
203  * The STRINGIZE() macro function passes names like macro definitions
204  * on the compiler's command-line. If the above code were changed to:
205  *
206  * @code
207  * const char name[] = STRINGIZE(NAME);
208  * @endcode
209  *
210  * then compiling it using the following command line makes it equivalent to the
211  * example above:
212  *
213  * @code
214  * $ gcc -c -DNAME=foo file.c
215  * @endcode
216  *
217  * The <c>-DNAME=foo</c> defines a macro called <c>NAME</c> with a value <c>foo</c>.
218  * The C preprocessor then replaces <c>STRINGIZE(NAME)</c> with <c>"foo"</c>.
219  */
220 //--------------------------------------------------------------------------------------------------
221 #define STRINGIZE(x) STRINGIZE_EXPAND(x)
222 
223 //--------------------------------------------------------------------------------------------------
224 /**
225  * Helper macro for @ref STRINGIZE(x).
226  */
227 //--------------------------------------------------------------------------------------------------
228 #define STRINGIZE_EXPAND(x) #x // Needed to expand macros.
229 
230 //--------------------------------------------------------------------------------------------------
231 /**
232  * Macro to help concatenate preprocessor tokens while first allowing macro expansion of those
233  * tokens.
234  *
235  * Original source: https://github.com/pfultz2/Cloak/wiki/C-Preprocessor-tricks,-tips,-and-idioms
236  */
237 //--------------------------------------------------------------------------------------------------
238 #define CAT(a, ...) PRIMITIVE_CAT(a, __VA_ARGS__)
239 
240 //--------------------------------------------------------------------------------------------------
241 /**
242  * Helper macro for @ref STRINGIZE(x).
243  */
244 //--------------------------------------------------------------------------------------------------
245 #define PRIMITIVE_CAT(a, ...) a ## __VA_ARGS__
246 
247 //--------------------------------------------------------------------------------------------------
248 /**
249  * Helper macro for @ref SECOND(...). Always select the second parameter.
250  */
251 //--------------------------------------------------------------------------------------------------
252 #define SECOND(a, b, ...) b
253 
254 //--------------------------------------------------------------------------------------------------
255 /**
256  * If the macro passed as the first parameter is defined in the form ,<value> (note the leading
257  * comma) this evaluates to <value>. If the macro is not defined in this format (or not defined at
258  * all, this evaluates to the second, default parameter.
259  */
260 //--------------------------------------------------------------------------------------------------
261 #define LE_DEFAULT(...) SECOND(__VA_ARGS__)
262 
263 //--------------------------------------------------------------------------------------------------
264 /**
265  * Macro used to declare that a symbol should be shared outside the dynamic shared object in
266  * which it is defined.
267  *
268  * This can be used with either a declaration or a definition.
269  *
270  * E.g., with a declaration (perhaps in a header file):
271  *
272  * @code
273  * LE_SHARED void my_Function();
274  * @endcode
275  *
276  * E.g., with a definition (in a .c file):
277  *
278  * @code
279  * LE_SHARED void my_OtherFunction()
280  * {
281  * LE_INFO("Hello world.");
282  * }
283  * @endcode
284  *
285  **/
286 //--------------------------------------------------------------------------------------------------
287 #define LE_SHARED __attribute__((visibility ("default")))
288 
289 //--------------------------------------------------------------------------------------------------
290 /**
291  * @macro LE_DECLARE_INLINE
292  *
293  * Declare an inline function in a header.
294  *
295  * GNU by default uses a non-standard method of declaring inline functions with the
296  * exact *opposite* meaning of the C99 standard.
297  *
298  * So use LE_DECLARE_INLINE with the function body in a header. Then use LE_DEFINE_INLINE with
299  * just the function prototype in a .c file to tell the compiler to emit the function definition
300  * for cases where the function is not inlined.
301  *
302  * This is preferred over using "static inline" since if a static inline function is not inlined
303  * by gcc, there may be multiple copies of the function included in the output.
304  */
305 /**
306  * @macro LE_DEFINE_INLINE
307  *
308  * Cause a function definition to be emitted for an inline function, in case the compiler
309  * decides not to use the inline definition.
310  *
311  * @see @c LE_DECLARE_INLINE
312  */
313 //--------------------------------------------------------------------------------------------------
314 #ifdef __GNUC_GNU_INLINE__
315 // Using gcc inline semantics
316 # define LE_DECLARE_INLINE extern inline
317 # define LE_DEFINE_INLINE inline
318 #else
319 // Use C99 inline semantics
320 # define LE_DECLARE_INLINE inline
321 # define LE_DEFINE_INLINE extern inline
322 #endif
323 
324 // Clang feature check macros -- define to return sensible defaults if macro is not available.
325 #ifndef __is_identifier
326 # define __is_identifier(x) 1
327 #endif
328 
329 #ifndef __has_warning
330 # define __has_warning(x) 0
331 #endif
332 
333 #ifndef __has_attribute
334 # define __has_attribute(x) 0
335 #endif
336 
337 #if !__is_identifier(_Nonnull)
338 
339 // Nullability information is not complete. Normally clang will warn in that case.
340 # if __has_warning("-Wnullability-completeness")
341 # pragma clang diagnostic ignored "-Wnullability-completeness"
342 # endif
343 
344 //--------------------------------------------------------------------------------------------------
345 /**
346  * Mark a parameter or return value as never NULL.
347  */
348 //--------------------------------------------------------------------------------------------------
349 # define LE_NONNULL _Nonnull
350 
351 //--------------------------------------------------------------------------------------------------
352 /**
353  * Mark a parameter or return value as potentially NULL.
354  */
355 //--------------------------------------------------------------------------------------------------
356 # define LE_NULLABLE _Nullable
357 #else
358 # define LE_NONNULL
359 # define LE_NULLABLE
360 #endif
361 
362 //--------------------------------------------------------------------------------------------------
363 /**
364  * Mark a variable as unused.
365  *
366  * @param v Variable to mark as unused.
367  */
368 //--------------------------------------------------------------------------------------------------
369 #define LE_UNUSED(v) ((void) (v))
370 
371 //--------------------------------------------------------------------------------------------------
372 /**
373  * Format specifiers for size_t
374  */
375 //--------------------------------------------------------------------------------------------------
376 #if (__STDC_VERSION__ >= 199901L) || LE_CONFIG_LINUX
377 # define __PRIS_PREFIX "z"
378 #elif defined(__LP64__) || defined(_LP64)
379 # define __PRIS_PREFIX "ll"
380 #else
381 # define __PRIS_PREFIX "l"
382 #endif
383 
384 #define PRIdS __PRIS_PREFIX "d"
385 #define PRIxS __PRIS_PREFIX "x"
386 #define PRIuS __PRIS_PREFIX "u"
387 #define PRIXS __PRIS_PREFIX "X"
388 #define PRIoS __PRIS_PREFIX "o"
389 
390 
391 #if !defined(static_assert) && !defined(__cplusplus)
392 //--------------------------------------------------------------------------------------------------
393 /**
394  * Provide static_assert if not available.
395  */
396 //--------------------------------------------------------------------------------------------------
397 # if __GNUC__ || __STDC_VERSION__ >= 201112L
398 # define static_assert(cond, msg) _Static_assert((cond), #cond ": " msg)
399 # else
400 # define static_assert(cond, msg) ((void)sizeof(char[1 - 2*!(cond)]))
401 # endif
402 #endif
403 
404 #if __GNUC__
405 // ({ }) is a GNU extension, so only use it if compiler is GCC-compatible
406 # define inline_static_assert(cond, msg) ({ static_assert(cond, msg); })
407 #else
408 # define inline_static_assert(cond, msg) ((void)(0))
409 #endif
410 
411 //--------------------------------------------------------------------------------------------------
412 /**
413  * Test if a KConfig feature is enabled.
414  */
415 //--------------------------------------------------------------------------------------------------
416 #define LE_CONFIG_IS_ENABLED(option) (("" STRINGIZE(option))[0] == '1')
417 
418 #endif // LEGATO_BASICS_INCLUDE_GUARD
Format error.
Definition: le_basics.h:63
The underlying resource does not support this operation.
Definition: le_basics.h:68
Current user does not have permission to perform requested action.
Definition: le_basics.h:55
Unspecified internal error.
Definition: le_basics.h:56
Duplicate entry found or operation already performed.
Definition: le_basics.h:64
Insufficient memory is available.
Definition: le_basics.h:54
le_result_t
Definition: le_basics.h:46
An IO operation failed.
Definition: le_basics.h:69
Would have caused a deadlock.
Definition: le_basics.h:62
Successful.
Definition: le_basics.h:48
Unimplemented functionality.
Definition: le_basics.h:70
An overflow occurred or would have occurred.
Definition: le_basics.h:59
A time-out occurred.
Definition: le_basics.h:58
An underflow occurred or would have occurred.
Definition: le_basics.h:60
Referenced item does not exist or could not be found.
Definition: le_basics.h:49
The resource is closed.
Definition: le_basics.h:66
A transient or temporary loss of a service or resource.
Definition: le_basics.h:71
Definition: le_basics.h:50
The resource is busy.
Definition: le_basics.h:67
The operation is in progress.
Definition: le_basics.h:73
An index or other value is out of range.
Definition: le_basics.h:53
Parameter is invalid.
Definition: le_basics.h:65
Would have blocked if non-blocking behaviour was not requested.
Definition: le_basics.h:61
The process, operation, data stream, session, etc. has stopped.
Definition: le_basics.h:72
The operation is suspended.
Definition: le_basics.h:74
Communications error.
Definition: le_basics.h:57
le_onoff_t
Definition: le_basics.h:85