/*! * \page cfu-coding-guidelines-page crystal-facet-uml coding guidelines * * \image html crystal_facet_uml.png * \image latex crystal_facet_uml.pdf "" width=3cm * * \section cfu-modules Software Modules * * The software consists of several modules. * \n Some are external modules and may therefore not follow the rules listed below. * \n The others belong to the crystal-facet-uml application. * * \subsection cfu-folder-structure Folder Structure * * Each module consists of the following top-level folders: * - include/ * \n contains all public interfaces of the module * \n as well as private interfaces+inline functions on which the public interfaces depend. * - source/ * \n contains all module-internal interfaces, source codes and resources. * - test/ * \n contains test cases for that software module * . * * \subsection cfu-namespaces Namespaces * * Since ANSI-C 99 does not provide namespaces, all file names, functions, types, enumeration-constants shall have a prefix. * \n If a module has sub-modules, these may have different prefixes. * * \subsection cfu-files Files * * - Every compilation unit file (.c) shall have one header file (.h) with the same name. * - Every header file (.h) may have one inline file (.inl) with the same name. * \n This inline file contains inline definitions of functions. * . * * \subsection cfu-coupling Loose Coupling * Independant software modules shall provide loose coupling and depencendy injection. * This is especially important when lower-layer modules broadcast messages to e.g. upper layer modules. * To allow loose coupling, glib signals shall be emitted. * Dependencies between these modules can be injected from outside. * * Within a software module, other ways of messaging is preferred, e.g. listener concepts, * where the compiler can check types of parameters (of function pointers). * * \section cfu-classes Classes and Objects * * All files shall follow object-oriented design patterns in the following way: * - Each header file declares one main type, a struct, with the same name as the file (postfixed by _t). * \n This struct is used like a class. * . * Even functions that do not share a data-object shall declare such a class-like struct. * Besides conformity of style, this guideline makes dependencies between classes explicit. * * \subsection cfu-attributes Attributes * * - All struct elements are private and shall be accessed via "_get_", "_is_" and "_set_" functions. * \n To achieve good runtime-performance, these may be declared as "static inline". * - Attributes that have a shorter lifetime than the parent object shall be prefixed by "temp_". * - Only for constant initialization, attributes may be used directly, e.g. "const point_t pnt = {.x=2, .y=5};" * . * * \subsection cfu-methods Methods * * - All function names are pre-fixed by the main type name. * - The first parameter of each function is a pointer to an instance of the main type. * \n The name of the first parameter is "this_". * \n This first parameter must not be NULL and needs not be checked for NULL. * - Functions that shall not be accessed from outside are in-fixed by "_private_". * - Functions that expose pointers or accessors to internal data shall be post-fixed by "_ptr". * \n If the exposed member is const, "_const" may alternatively be used as postfix. * \n Care needs to be taken when changing internal data from outside * and when reading data from outside while it may be changed from inside. * - All functions may assume (unless explicitly documented) that they are only called * \n after an init call and * \n before a destroy call * . * * \subsection cfu-create-destroy Constructors, Copy-Constructors, Move-Constructors and Destructors * * Similar to classes, at least one constructor and a destructor shall be provided. * - Any constructor starts with the type-name and "_init" as prefix. * \n A constructor shall initialize the struct in a way that all functions can be called without causing harm. * - Any copy/move constructor (if provided) starts with the type-name and "_copy"/"_move" as postfix. * \n If no copy constructor is provided, the assignment "=" and memcpy may be used. * - The destructor starts with the type-name and ends with "_destroy". * \n The destructor shall free any occupied resources (e.g. mutexes) and may set all references to * external objects to NULL. It shall not do more: E.g. zero-ing the memory is not necessary. * - Optionally, a "_reinit" de+constructor may be provided. * \n This constructor shall re-initialize the struct that was already initialized before. * - Optionally, "_replace"/"_replacemove" de+constructors may be provided for copying/moving objects into already initialized ones. * \n This constructor shall re-initialize the struct that was already initialized before the copy/move of the provided object. * - To facilitate static and/or constant initialization, uppercase TYPENAME() macros may map parameters to struct fields. * \n Alternatively a function of name "<type-name>_new" may return a const object (not a pointer). * . * * \subsection cfu-lifecycle Responsabilities for Creation and Destruction * * The general guideline is: who creates the object is responsible for destroying it. * * Special Considerations: * - Functions may return objects only if the assignment via memcpy is a valid move-operation. * The caller is responsible for destroying it. * \n Rationale: The caller will most likely do an assignment like result_object=function(x); * Only result_object can be destroyed by the caller, not the copy on the stack. * - Functions may accept object-parameters (non-pointer) only if the assignment via memcpy is a valid copy-operation. * \n Rationale: The caller will do an assignment like function(object_parameter); which produces a copy. * Note that the caller is still responsible to destroy object_parameter and the callee to destroy the copy. * - Functions may define memory locations for result-objects as "out_"-parameter. The caller shall pre-initialize these. * \n Rationale: This allows to stick to the followin rule: Who creates an object is responsible for destroying it. * - Arrays: Objects in arrays shall be destroyed as all other objects. * - Exceptions shall be documented. * - Avoid using NULL pointers, prefer using pointers to void objects. * \n Rationale: This avoids segmentation faults in case of not checking for NULL, software gets more robust. * . * * \subsection cfu-interfaces Implementing Abstract Interfaces * * How to define an abstract interface, implement it and then pass an instance of the abstract interface to clients, * see universal_output_stream_t. * \see universal_output_stream_t * \see universal_output_stream_if_t * \see universal_file_output_stream_t * \see universal_memory_output_stream_t * * Note: there is also a more typesafe but less nice variant, \see io_element_writer_t . * * \section cfu-error Error Handling * * This section explains the detection of faults and anomalies, the propagation from detection to error handler and * how an error handler shall react. Small anomalies shall be logged but need not be handled. * * \subsection cfu-error-handling Technical Concepts * * The following mechanisms shall be used for detection, propagation and handling of errors: * - assert * \n assert statements shall be used to validate that a function is called under appropriate conditions. * \n assert statements shall be used to validate that a function returns values in the specified range. * \n assert statements shall have no effect in NDEBUG mode, stop the program otherwise. * - logging * \n Faults and anomalies shall be logged when they occur. * - fault injecttion * \n In case a fault condition should be handled but cannot be provoked in the test environment with low efforts, * the U8_FAULT_INJECT_COND() macro shall be inserted to allow unit-testing of the error handling. * - error_codes * \n The return parameter of a function shall be the error code. Futher return values shall be declared as *out_xy parmeter. * \n Exception to this rule are helper and utility functions which do not report errors (only perform asserts) * or where the return value contains the error e.g. by being invalid/void/empty (if such a state exists). * - error handling * \n Errors shall be reported to the user: in GUI mode, a message shall be shown in a window, in console mode, it shall be * shown on std_err. * \n If possible, the program shall continue running. * . * * \section cfu-types Types (Declarations and Operators) * * Avoid implicit type conversions. Perform explicit type conversions instead. * * \subsection cfu-implicit-type-conversions Implicit Type Conversions * * Especially on arrays, one can get confused easily. While implicit type conversions are helpful as long as things are simple, * one gets confused when looking at pointer-to-array-of-pointers and array-of-pointers-to-arrays. * * The term \c ((char*)buf)+len looks simple - but adds value \c len*sizeof(char) to the pointer \c buf and returns a pointer of type \c char*. * These c-magic pointer-to-array conversions get confusing if types are more complicated than a simple char, e.g. \c ((char(*)[][7])buf)+len . * * In crystal-facet-uml, the preferred term is \c &((*((char(*)[])buf))[len]) - which is identical to \c ((char*)buf)+len. * There is no magic: \c buf is cast to pointer-to-array \c char(*)[] . The pointer is dereferenced, the array-element \c len is selected, * the address of that element is determined. * * Hints on C-Pitfalls: * - An array is an array. * \n to get a pointer onto the first element, call \c &(my_array[0]). * \n to get a pointer onto the array, call \c &(my_array). * - A pointer is a pointer. * \n to get an array, cast the pointer-to-base-type to a pointer-to-array-of-base-type and dereference it: \c *((char(*)[])my_ptr) * \n to get a function, dereference the pointer: *(my_func_ptr) * \n avoid the + operator on pointers, dereference the pointer and access the array element instead: \c (*(array_ptr))[n] * - A function is a function. * \n to get a pointer to a function, write \c &(my_func). * - A c-string is a char-array. * \n to pass a c-string to a function, use a pointer on the array: \c &(my_string) of type \c char(*)[]. * . * * \section cfu-external-guidelines External Coding Guidelines * * To ensure high robustness and reproducability of the software, stick to MISRA-C rules wherever possible. * In case you do not have a copy at hand, consider this similar set of rules: * https://www.autosar.org/fileadmin/standards/R22-11/AP/AUTOSAR_RS_CPP14Guidelines.pdf * * \section cfu-coding-guidelines-apx Appendix * \author Copyright 2016-2025 Andreas Warnke; Email-contact: cfu-at-andreaswarnke-dot-de */