David Ghandehari | fd76734 | 2017-02-13 12:56:12 -0800 | [diff] [blame] | 1 | # Starboard C and C++ Style Guide |
| 2 | |
| 3 | A description of the coding conventions for Starboard code and API headers. |
| 4 | |
| 5 | **Status:** REVIEWED\ |
| 6 | **Created:** 2016-11-08 |
| 7 | |
| 8 | Starboard generally tries to follow the coding conventions of Cobalt, which |
| 9 | itself mostly follows the conventions of Chromium, which mostly follows the |
| 10 | externally-published Google C++ coding conventions. But, Starboard has some |
| 11 | special requirements due to its unusual constraints, so it must add a few new |
| 12 | conventions and loosen some of the existing style prescriptions. |
| 13 | |
| 14 | ## Background |
| 15 | |
| 16 | Before looking at this document, bear in mind that it is not intending to |
| 17 | completely describe all conventions that apply to Starboard. You probably want |
| 18 | to take some time to familiarize yourself with these documents first, probably |
| 19 | in this order: |
| 20 | |
| 21 | * [Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html) |
| 22 | * [Chromium C++ Style Guide](https://chromium.googlesource.com/chromium/src/+/master/styleguide/c++/c++.md) |
| 23 | * [Cobalt Style Guide](http://cobalt.foo/broken) |
| 24 | |
| 25 | The main additional constraints that Starboard has to deal with are: |
| 26 | |
| 27 | * The Starboard API is defined in straight-C. It must be able to interface |
| 28 | with all possible third-party components, many of which are in C and not |
| 29 | C++. |
| 30 | * Starboard is a public API. Starboard platform implementations and |
| 31 | applications written on top of Starboard will change independently. This |
| 32 | means there are intense requirements for API stability, usage |
| 33 | predictability, searchability, and documentation. |
| 34 | * Note that even though it is presented as a "style guide," the conventions |
| 35 | presented here are required to be approved for check-in unless otherwise |
| 36 | noted. |
| 37 | |
| 38 | |
| 39 | ## Definitions |
| 40 | |
| 41 | ### snake-case |
| 42 | |
| 43 | Words separated with underscores. |
| 44 | |
| 45 | lower_snake_case |
| 46 | ALL_CAPS_SNAKE_CASE |
| 47 | |
| 48 | ### camel-case |
| 49 | |
| 50 | Words separated by letter capitalization. |
| 51 | |
| 52 | camelCase |
| 53 | CapitalizedCamelCase |
| 54 | |
| 55 | ## C++ Guidelines |
| 56 | |
| 57 | What follows are hereby the guidelines for Starboard C and C++ code. Heretofore |
| 58 | the guidelines follow thusly as follows. |
| 59 | |
| 60 | ### API Definitions |
| 61 | |
| 62 | * Starboard API definitions must always be compatible with straight-C99 compilers. |
| 63 | * All public API declarations must be specified in headers in |
| 64 | `src/starboard/*.h`, not in any subdirectories. |
| 65 | * Non-public declarations must NOT be specified in headers in |
| 66 | `src/starboard/*.h`. |
| 67 | * C++ inline helper definitions may be included inside an `#if |
| 68 | defined(__cplusplus)` preprocessor block. They must only provide |
| 69 | convenience, and must NOT be required for any API functionality. |
| 70 | * All public API functions should be exported symbols with the SB_EXPORT |
| 71 | attribute. |
| 72 | * No non-const variables shall be exposed as part of the public API. |
| 73 | * All APIs should be implemented in C++ source files, not straight-C source files. |
| 74 | |
| 75 | ### Modules |
| 76 | |
| 77 | * Each module header must be contained with a single header file. |
| 78 | |
| 79 | * The name of the module must be the singular form of the noun being |
| 80 | interfaced with by the module, without any "sb" or "starboard". |
| 81 | * `file.h` |
| 82 | * `directory.h` |
| 83 | * `window.h` |
| 84 | * Module interfaces should not have circular dependencies. |
| 85 | |
| 86 | ### File Names |
| 87 | |
| 88 | * Like in the other conventions (e.g. Google, Chromium), file names must be in |
| 89 | `lower_snake_case`. |
| 90 | * File names must not contain `sb_` or `starboard_`. |
| 91 | * The name of a module header file must be the `lower_snake_case` form of the |
| 92 | module name. |
| 93 | * `SbConditionVariable` ➡ `starboard/condition_variable.h` |
| 94 | * A header that is intended to be an internal implementation detail of one or |
| 95 | more platform implementations should have the suffix `_internal.h`, and |
| 96 | include the header `starboard/shared/internal_only.h`. |
| 97 | * See "Implementations" for conventions about where to place implementation files. |
| 98 | |
| 99 | ### Types |
| 100 | |
| 101 | * Like in the other conventions, types should be `CapitalizedCamelCase`. |
| 102 | * Every public Starboard type must start with `Sb`. There are no namespaces in |
| 103 | C, so `Sb` is the Starboard namespace. |
| 104 | * Every public Starboard type must be declared by a module, and must have the |
| 105 | name of the module following the `Sb`. |
| 106 | * `file.h` contains `SbFile`, `SbFileInfo`, `SbFileWhence`, etc... |
| 107 | * Every seemingly-allocatable, platform-specific Starboard type should be |
| 108 | defined as an opaque handle to a publically undefined struct with the |
| 109 | `Private` suffix. Follow this pattern for all such type declarations. |
| 110 | * `struct SbFilePrivate` is declared, but not defined in the public header. |
| 111 | * `SbFilePrivate` is `typedef`'d to `struct SbFilePrivate`. This is a C |
| 112 | thing where types are defined as names with the "`struct`" keyword |
| 113 | prepended unless `typedef`'d. |
| 114 | * `SbFile` is defined as a `typedef` of `struct SbFilePrivate*`. |
| 115 | * C structs may be defined internally to have functions and visibility. It is |
| 116 | allowed for such structs to have constructors, destructors, methods, |
| 117 | members, and public members. |
| 118 | * It is also considered idiomatic to never define the private struct but to |
| 119 | just treat it like a handle into some other method of object tracking, |
| 120 | casting the handle back and forth to the pointer type. |
| 121 | * If a word in the name of a type is redundant with the module name, it is |
| 122 | omitted. |
| 123 | * A monotonic time type in the Time module is `SbTimeMonotonic`, not |
| 124 | ~~`SbMonotonicTime`, `SbTimeMonotonicTime`, or |
| 125 | `SbTimeMonotonicSbTime`~~. |
| 126 | |
| 127 | ### Functions |
| 128 | |
| 129 | * Like in the other conventions, functions should be `CapitalizedCamelCase`. |
| 130 | * Every public Starboard function must start with `Sb`. There are no namespaces |
| 131 | in C, so `Sb` is the Starboard namespace. |
| 132 | * Every public Starboard function must be declared by a module, and must have |
| 133 | the name of the module following the `Sb`. |
| 134 | * `system.h` contains `SbSystemGetPath()` |
| 135 | * `file.h` contains `SbFileOpen()` |
| 136 | * After the Starboard and Module prefix, functions should start with an |
| 137 | imperative verb indicating what the function does. |
| 138 | * The Thread module defines `SbThreadCreateLocalKey()` to create a key for |
| 139 | thread local storage. |
| 140 | * If a word in the name of a function is redundant with the module name, it is |
| 141 | omitted. |
| 142 | * The `File` module as the function `SbFileOpen`, not ~~`SbOpenFile`, |
| 143 | `SbFileOpenFile` or `SbFileOpenSbFile`~~. |
| 144 | * If this gets awkward, it may indicate a need to split into a different |
| 145 | module. |
| 146 | |
| 147 | ### Variables, Parameters, Fields |
| 148 | |
| 149 | * Like in the other conventions, variable, function parameter, and field names |
| 150 | must be in `lower_snake_case`. |
| 151 | * Private member fields end in an underscore. |
| 152 | * Public member fields do not end in an underscore. |
| 153 | |
| 154 | ### Namespaces |
| 155 | |
| 156 | Most Starboard API headers are straight-C compatible, so cannot live inside a |
| 157 | namespace. Implementations, since they implement straight-C interface functions, |
| 158 | also cannot live inside a namespace. |
| 159 | |
| 160 | But, in all other cases, Starboard C++ code should follow the inherited |
| 161 | conventions and use a namespace for each directory starting with a "starboard" |
| 162 | namespace at the starboard repository root. |
| 163 | |
| 164 | ### Preprocessor Macros |
| 165 | |
| 166 | * Like in the other conventions, variable, function parameter, and field names |
| 167 | must be in `ALL_CAPS_SNAKE_CASE`. |
| 168 | * Macros may be used as compile-time constants because straight-C does not |
| 169 | have a proper facility for typed constants. This is as opposed to macros |
| 170 | used primarily at preprocessor-time to filter or modify what gets sent to |
| 171 | the compiler. Macros used as compile-time constants and that are not |
| 172 | configuration parameters should be explicitly-typed with a c-style cast, and |
| 173 | should follow the Constants naming conventions. |
| 174 | * Macros must start with `SB_`, and then must further be namespaced with the |
| 175 | module name, with the exception of configuration definitions. |
| 176 | * Configuration definitions should be namespaced with the module name that |
| 177 | they primarily affect, if applicable, or a scope that generally indicates |
| 178 | its domain. |
| 179 | * `SB_FILE_MAX_NAME` |
| 180 | * `SB_MEMORY_PAGE_SIZE` |
| 181 | * Always use `#if defined(MACRO)` over `#ifdef MACRO`. |
| 182 | |
| 183 | ### Constants |
| 184 | |
| 185 | * Constants (including enum entries) are named using the Google constant |
| 186 | naming convention, `CapitalizedCamelCase`d, but starting with a lower-case |
| 187 | `k`. |
| 188 | * After the `k`, all constants have `Sb`, the Starboard namespace. |
| 189 | * `kSb` |
| 190 | * After `kSb`, all constants then have the module name. |
| 191 | * `kSbTime` |
| 192 | * `kSbFile` |
| 193 | * After `kSb<module>` comes the rest of the name of the constant. |
| 194 | * `kSbTimeMillisecond` |
| 195 | * `kSbFileInvalid` |
| 196 | * Enum entries are prefixed with the full name of the enum. |
| 197 | * The enum `SbSystemDeviceType` contains entries like |
| 198 | `kSbSystemDeviceTypeBlueRayDiskPlayer`. |
| 199 | |
| 200 | ### Comments |
| 201 | |
| 202 | * All files must have a license and copyright comment. |
| 203 | * It is expected that the straight-C compiler supports C99 single-line |
| 204 | comments. Block comments should be avoided whenever possible, even in |
| 205 | license and copyright headers. |
| 206 | * Each public API module file should have a Module Overview documentation |
| 207 | comment below the license explaining what the module is for, and how to use |
| 208 | it effectively. |
| 209 | * The Module Overview must be separated by a completely blank line from the |
| 210 | license comment. |
| 211 | * The first line of the Module Overview documentation comment must say |
| 212 | "`Module Overview: Starboard <module-name> module`", followed by a blank |
| 213 | comment line (i.e. a line that contains a `//`, but nothing else). |
| 214 | * The first sentence of a documentation comment describing any entity (module, |
| 215 | type, function, variable, etc...) should assume "This module," "This type," |
| 216 | "This function," or "This variable" at the beginning of the sentence, and |
| 217 | not include it. |
| 218 | * The first sentence of a documentation comment describing any entity should |
| 219 | be a single-sentence summary description of the entire entity. |
| 220 | * The first paragraph of a documentation comment should describe the overall |
| 221 | behavior of the entity. |
| 222 | * Paragraphs in comments should be separated by a blank comment line. |
| 223 | * All public entities must have documentation comments, including enum |
| 224 | entries. |
| 225 | * Documentation comments should be formatted with Markdown. |
| 226 | * Variables, constants, literals, and expressions should be referenced in |
| 227 | comments with pipes around them. |
| 228 | * All comments must be full grammatically-correct English sentences with |
| 229 | proper punctuation. |
| 230 | |
| 231 | ### Implementations |
| 232 | |
| 233 | * Each API implementation should attempt to minimize other platform |
| 234 | assumptions, and should therefore use Starboard APIs to accomplish |
| 235 | platform-specific work unless directly related to the platform functionality |
| 236 | being implemented. |
| 237 | * For example, `SbFile` can use POSIX file I/O, because that what it is |
| 238 | abstracting, but it should use `SbMemoryAllocate` for any memory |
| 239 | allocations, because it might be used with a variety of `SbMemory` |
| 240 | implementations. |
| 241 | * Whenever possible, each shared function implementation should be implemented |
| 242 | in an individual file so as to maximize the chances of reuse between |
| 243 | implementations. |
| 244 | * This does not apply to platform-specific functions that have no chance of |
| 245 | being reusable on other platforms. |
| 246 | * Implementation files that can conceivably be shared between one or more |
| 247 | implementations should be placed in a `starboard/shared/<dependency>/` |
| 248 | directory, where `<dependency>` is the primary platform dependency of that |
| 249 | implementation. (e.g. `libevent`, `posix`, `c++11`, etc.) |
| 250 | * Implementation files that don't have a specific platform dependency, but |
| 251 | whether to use them should be a platform decision should be placed in |
| 252 | `starboard/shared/starboard/`, and must only have dependencies on other |
| 253 | Starboard APIs. |
| 254 | * Implementation files that definitely can be common to ALL implementations |
| 255 | should be placed in `starboard/common/`. |
| 256 | |
| 257 | ### Language Features |
| 258 | |
| 259 | * In public headers, particularly in inline functions and macros, only C-Style |
| 260 | casts may be used, though they are forbidden everywhere else. |
| 261 | * It is expected that the C compiler supports inline functions. They must be |
| 262 | declared `static`, and they must use the `SB_C_INLINE` or |
| 263 | `SB_C_FORCE_INLINE` attribute. In straight-C code, there is no anonymous |
| 264 | namespace, so `static` is allowed and required for inline functions. |
| 265 | * No straight-C ISO or POSIX headers should be assumed to exist. Basic C++03 |
| 266 | headers may be assumed to exist in C++ code. The ISO C standards have grown |
| 267 | up over a long period of time and have historically been implemented with |
| 268 | quirks, missing pieces, and so on. Support for the core C++ standard library |
| 269 | is much more consistent on those platforms that do support it. |
| 270 | * It is idiomatic to include thin C++ inline wrappers inside public API |
| 271 | headers, gated by an `#if defined(cplusplus__)` check. |