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