RATIONALE ~~~~~~~~~ On breaking API change, the major version number is increased and old applications will not work with the new version of librnd. When a new minor version of librnd is released, it may contain new features and existing applications designed for older minor version of librnd must work without recompilation. In other words, a new minor version may introduce new features (new functions, new variables, new macros, new header files, new plugins) but must not change any existing API. The only area where it is non-trivial to achieve is state/context structs in the API. These structs are typically allocated by the caller, often on stack. If the size of the structure changes (increases) in a new minor version, an old application will still allocate for the old (smaller) size which will lead to invalid memory access when the lib tries to read or write the new fields. This document describes a method to overcome this problem by using spare struct fields. SPARE FIELDS ~~~~~~~~~~~~ To provide binary compatibility when adding new features, the following precaution/mechanism is used in many of the public API structs: 1. The struct has a bunch of fields prefixed with spare_; these fields are of different type and are not used for anything in the current version 2. The user/caller, who allocates the structure, initializes all bytes of the structure to zero, including these spare fields. For the spare fields this is done implicitly, by zeroing the struct (by struct size), not by listing the spare fields. Most typical ways to do this are: - global variable (auto-initialized to 0) - local variable initialized to {0} - dynamically allocated memory via calloc() 3. If a new, _optional_ field is required in the struct, one of the spare field with matching type is renamed. The default, "called did not know/care about this field" value is 0. The size of the structure or the offset of any member do not change. 4. The rename happens in-place, so the new field is under the "spare fields" comment within the struct. 5. Any code dealing with the new field _must_ be prepared for value 0 and _must_ assume that may be due to an older app version that did not yet know about the field or feature associated with the field. 6. A TODO entry needs to be written about the struct->field under the group of entries for the next major version, in doc/TODO. 7. When breaking changes are introduced in the API, bumping the major version of the lib, all new fields created from spares should be moved out from the spare section and the spare field restored for reuse. (This does increase the size of the struct.)