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  * Standard exit codes.
82  *
83  * @note The value follow standardize exit codes of BSD(Berkeley software distribution),
84  * detail in file <sysexits.h>.
85  *
86  * Present exit status of process that is stopped by loss of a service or resource.
87  */
88 //--------------------------------------------------------------------------------------------------
89 #define EXIT_UNAVAILABLE 69
90 
91 
92 //--------------------------------------------------------------------------------------------------
93 /**
94  * ON/OFF type.
95  *
96  */
97 //--------------------------------------------------------------------------------------------------
98 typedef enum
99 {
100  LE_OFF = 0,
101  LE_ON = 1,
102 }
103 le_onoff_t;
104 
105 
106 //--------------------------------------------------------------------------------------------------
107 /** @name Bit Masks
108  *
109  * Single byte bit definitions that can be used for bit masking.
110  * @{
111  */
112 //--------------------------------------------------------------------------------------------------
113 #define BIT0 0x01
114 #define BIT1 0x02
115 #define BIT2 0x04
116 #define BIT3 0x08
117 #define BIT4 0x10
118 #define BIT5 0x20
119 #define BIT6 0x40
120 #define BIT7 0x80
121 // @}
122 
123 //--------------------------------------------------------------------------------------------------
124 /**
125  * Find the address of a containing structure or union, based on the address of one of its members.
126  *
127  * If @c countPtr points to the @c count member of an object type
128  * @c my_class_t, then a pointer to that object should use this:
129  *
130  * @code
131  * my_class_t* myObjPtr = CONTAINER_OF(countPtr, my_class_t, count);
132  * @endcode
133  */
134 //--------------------------------------------------------------------------------------------------
135 #define CONTAINER_OF(memberPtr, type, member) \
136  ((type*)(((uint8_t*)(memberPtr))-((size_t)(&(((type*)0)->member)))))
137 
138 
139 //--------------------------------------------------------------------------------------------------
140 /**
141  * Computes number of members in an array at compile time.
142  *
143  * @warning Does NOT work for pointers to arrays.
144  *
145  * Here's a code sample:
146  *
147  * @code
148  * const char message[] = "Hello world!";
149  *
150  * size_t x = NUM_ARRAY_MEMBERS(message);
151  *
152  * printf("%lu\n", x);
153  * @endcode
154  *
155  * Will print @c 13 on a 32-bit target.
156  *
157  * But this example is @b incorrect:
158  *
159  * @code
160  * const char message[] = "Hello world!";
161  * const char* messagePtr = &message;
162  *
163  * size_t x = NUM_ARRAY_MEMBERS(messagePtr); // NO! BAD PROGRAMMER! BAD!
164  *
165  * printf("%lu\n", x);
166  * @endcode
167  */
168 //--------------------------------------------------------------------------------------------------
169 #define NUM_ARRAY_MEMBERS(array) \
170  (sizeof(array) / sizeof((array)[0]))
171 
172 
173 //--------------------------------------------------------------------------------------------------
174 /**
175  * Computes the index of a member within an array.
176  *
177  * This code sample prints out "The 'w' is at index 6.":
178  *
179  * @code
180  * const char message[] = "Hello world!";
181  * const char* charPtr;
182  * int i;
183  *
184  * for (i = 0; i < sizeof(message); i++)
185  * {
186  * if (message[i] == 'w')
187  * {
188  * charPtr = &message[i];
189  * }
190  * }
191  *
192  * printf("The 'w' is at index %zu.\n", INDEX_OF_ARRAY_MEMBER(message, charPtr));
193  * @endcode
194  **/
195 //--------------------------------------------------------------------------------------------------
196 #define INDEX_OF_ARRAY_MEMBER(array, memberPtr) \
197  ((((size_t)memberPtr) - ((size_t)array)) / sizeof(*(memberPtr)))
198 
199 
200 //--------------------------------------------------------------------------------------------------
201 /**
202  * This function takes the characters as an argument and puts quotes around them.
203  *
204  * Code sample:
205  *
206  * @code
207  * const char name[] = STRINGIZE(foo);
208  * @endcode
209  *
210  * Is seen by the compiler as
211  *
212  * @code
213  * const char name[] = "foo";
214  * @endcode
215  *
216  * The STRINGIZE() macro function passes names like macro definitions
217  * on the compiler's command-line. If the above code were changed to:
218  *
219  * @code
220  * const char name[] = STRINGIZE(NAME);
221  * @endcode
222  *
223  * then compiling it using the following command line makes it equivalent to the
224  * example above:
225  *
226  * @code
227  * $ gcc -c -DNAME=foo file.c
228  * @endcode
229  *
230  * The <c>-DNAME=foo</c> defines a macro called <c>NAME</c> with a value <c>foo</c>.
231  * The C preprocessor then replaces <c>STRINGIZE(NAME)</c> with <c>"foo"</c>.
232  */
233 //--------------------------------------------------------------------------------------------------
234 #define STRINGIZE(x) STRINGIZE_EXPAND(x)
235 
236 //--------------------------------------------------------------------------------------------------
237 /**
238  * Helper macro for @ref STRINGIZE(x).
239  */
240 //--------------------------------------------------------------------------------------------------
241 #define STRINGIZE_EXPAND(x) #x // Needed to expand macros.
242 
243 //--------------------------------------------------------------------------------------------------
244 /**
245  * Macro to help concatenate preprocessor tokens while first allowing macro expansion of those
246  * tokens.
247  *
248  * Original source: https://github.com/pfultz2/Cloak/wiki/C-Preprocessor-tricks,-tips,-and-idioms
249  */
250 //--------------------------------------------------------------------------------------------------
251 #define CAT(a, ...) PRIMITIVE_CAT(a, __VA_ARGS__)
252 
253 //--------------------------------------------------------------------------------------------------
254 /**
255  * Helper macro for @ref STRINGIZE(x).
256  */
257 //--------------------------------------------------------------------------------------------------
258 #define PRIMITIVE_CAT(a, ...) a ## __VA_ARGS__
259 
260 //--------------------------------------------------------------------------------------------------
261 /**
262  * Helper macro for @ref SECOND(...). Always select the second parameter.
263  */
264 //--------------------------------------------------------------------------------------------------
265 #define SECOND(a, b, ...) b
266 
267 //--------------------------------------------------------------------------------------------------
268 /**
269  * If the macro passed as the first parameter is defined in the form ,<value> (note the leading
270  * comma) this evaluates to <value>. If the macro is not defined in this format (or not defined at
271  * all, this evaluates to the second, default parameter.
272  */
273 //--------------------------------------------------------------------------------------------------
274 #define LE_DEFAULT(...) SECOND(__VA_ARGS__)
275 
276 //--------------------------------------------------------------------------------------------------
277 /**
278  * Macro used to declare that a symbol should be shared outside the dynamic shared object in
279  * which it is defined.
280  *
281  * This can be used with either a declaration or a definition.
282  *
283  * E.g., with a declaration (perhaps in a header file):
284  *
285  * @code
286  * LE_SHARED void my_Function();
287  * @endcode
288  *
289  * E.g., with a definition (in a .c file):
290  *
291  * @code
292  * LE_SHARED void my_OtherFunction()
293  * {
294  * LE_INFO("Hello world.");
295  * }
296  * @endcode
297  *
298  **/
299 //--------------------------------------------------------------------------------------------------
300 #define LE_SHARED __attribute__((visibility ("default")))
301 
302 //--------------------------------------------------------------------------------------------------
303 /**
304  * @macro LE_DECLARE_INLINE
305  *
306  * Declare an inline function in a header.
307  *
308  * GNU by default uses a non-standard method of declaring inline functions with the
309  * exact *opposite* meaning of the C99 standard.
310  *
311  * So use LE_DECLARE_INLINE with the function body in a header. Then use LE_DEFINE_INLINE with
312  * just the function prototype in a .c file to tell the compiler to emit the function definition
313  * for cases where the function is not inlined.
314  *
315  * This is preferred over using "static inline" since if a static inline function is not inlined
316  * by gcc, there may be multiple copies of the function included in the output.
317  */
318 /**
319  * @macro LE_DEFINE_INLINE
320  *
321  * Cause a function definition to be emitted for an inline function, in case the compiler
322  * decides not to use the inline definition.
323  *
324  * @see @c LE_DECLARE_INLINE
325  */
326 //--------------------------------------------------------------------------------------------------
327 #ifdef __GNUC_GNU_INLINE__
328 // Using gcc inline semantics
329 # define LE_DECLARE_INLINE extern inline
330 # define LE_DEFINE_INLINE inline
331 #else
332 // Use C99 inline semantics
333 # define LE_DECLARE_INLINE inline
334 # define LE_DEFINE_INLINE extern inline
335 #endif
336 
337 // Clang feature check macros -- define to return sensible defaults if macro is not available.
338 #ifndef __is_identifier
339 # define __is_identifier(x) 1
340 #endif
341 
342 #ifndef __has_warning
343 # define __has_warning(x) 0
344 #endif
345 
346 #ifndef __has_attribute
347 # define __has_attribute(x) 0
348 #endif
349 
350 #if !__is_identifier(_Nonnull)
351 
352 // Nullability information is not complete. Normally clang will warn in that case.
353 # if __has_warning("-Wnullability-completeness")
354 # pragma clang diagnostic ignored "-Wnullability-completeness"
355 # endif
356 
357 //--------------------------------------------------------------------------------------------------
358 /**
359  * Mark a parameter or return value as never NULL.
360  */
361 //--------------------------------------------------------------------------------------------------
362 # define LE_NONNULL _Nonnull
363 
364 //--------------------------------------------------------------------------------------------------
365 /**
366  * Mark a parameter or return value as potentially NULL.
367  */
368 //--------------------------------------------------------------------------------------------------
369 # define LE_NULLABLE _Nullable
370 #else
371 # define LE_NONNULL
372 # define LE_NULLABLE
373 #endif
374 
375 //--------------------------------------------------------------------------------------------------
376 /**
377  * Mark a variable as unused.
378  *
379  * @param v Variable to mark as unused.
380  */
381 //--------------------------------------------------------------------------------------------------
382 #define LE_UNUSED(v) ((void) (v))
383 
384 //--------------------------------------------------------------------------------------------------
385 /**
386  * Format specifiers for size_t
387  */
388 //--------------------------------------------------------------------------------------------------
389 #if (__STDC_VERSION__ >= 199901L) || LE_CONFIG_LINUX
390 # define __PRIS_PREFIX "z"
391 #elif defined(__LP64__) || defined(_LP64)
392 # define __PRIS_PREFIX "ll"
393 #else
394 # define __PRIS_PREFIX "l"
395 #endif
396 
397 #define PRIdS __PRIS_PREFIX "d"
398 #define PRIxS __PRIS_PREFIX "x"
399 #define PRIuS __PRIS_PREFIX "u"
400 #define PRIXS __PRIS_PREFIX "X"
401 #define PRIoS __PRIS_PREFIX "o"
402 
403 
404 #if !defined(static_assert) && !defined(__cplusplus)
405 //--------------------------------------------------------------------------------------------------
406 /**
407  * Provide static_assert if not available.
408  */
409 //--------------------------------------------------------------------------------------------------
410 # if __GNUC__ || __STDC_VERSION__ >= 201112L
411 # define static_assert(cond, msg) _Static_assert((cond), #cond ": " msg)
412 # else
413 # define static_assert(cond, msg) ((void)sizeof(char[1 - 2*!(cond)]))
414 # endif
415 #endif
416 
417 #if __GNUC__
418 // ({ }) is a GNU extension, so only use it if compiler is GCC-compatible
419 # define inline_static_assert(cond, msg) ({ static_assert(cond, msg); })
420 #else
421 # define inline_static_assert(cond, msg) ((void)(0))
422 #endif
423 
424 //--------------------------------------------------------------------------------------------------
425 /**
426  * Test if a KConfig feature is enabled.
427  */
428 //--------------------------------------------------------------------------------------------------
429 #define LE_CONFIG_IS_ENABLED(option) (("" STRINGIZE(option))[0] == '1')
430 
431 #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:98