1e5c31af7Sopenharmony_ci<html> 2e5c31af7Sopenharmony_ci 3e5c31af7Sopenharmony_ci<head> 4e5c31af7Sopenharmony_ci<title>drawElements Coding Guidelines</title> 5e5c31af7Sopenharmony_ci 6e5c31af7Sopenharmony_ci<style type="text/css"> 7e5c31af7Sopenharmony_ci div.body { 8e5c31af7Sopenharmony_ci width: 800px; 9e5c31af7Sopenharmony_ci margin-top: 50px; 10e5c31af7Sopenharmony_ci margin-left: auto; 11e5c31af7Sopenharmony_ci margin-right: auto; 12e5c31af7Sopenharmony_ci border: 1px solid silver; 13e5c31af7Sopenharmony_ci background-color: #eee; 14e5c31af7Sopenharmony_ci } 15e5c31af7Sopenharmony_ci 16e5c31af7Sopenharmony_ci div.title { 17e5c31af7Sopenharmony_ci text-align: center; 18e5c31af7Sopenharmony_ci font-size: 24pt; 19e5c31af7Sopenharmony_ci margin-top: 1.5em; 20e5c31af7Sopenharmony_ci margin-bottom: 0.5em; 21e5c31af7Sopenharmony_ci } 22e5c31af7Sopenharmony_ci 23e5c31af7Sopenharmony_ci div.quote { 24e5c31af7Sopenharmony_ci font-style: italic; 25e5c31af7Sopenharmony_ci text-align: center; 26e5c31af7Sopenharmony_ci width: 48%; 27e5c31af7Sopenharmony_ci margin-left: auto; 28e5c31af7Sopenharmony_ci margin-right: auto; 29e5c31af7Sopenharmony_ci } 30e5c31af7Sopenharmony_ci 31e5c31af7Sopenharmony_ci div.copyright { 32e5c31af7Sopenharmony_ci font-style: italic; 33e5c31af7Sopenharmony_ci text-align: center; 34e5c31af7Sopenharmony_ci margin-top: 3em; 35e5c31af7Sopenharmony_ci margin-left: auto; 36e5c31af7Sopenharmony_ci margin-right: auto; 37e5c31af7Sopenharmony_ci } 38e5c31af7Sopenharmony_ci 39e5c31af7Sopenharmony_ci div.author { 40e5c31af7Sopenharmony_ci font-style: italic; 41e5c31af7Sopenharmony_ci text-align: center; 42e5c31af7Sopenharmony_ci margin-bottom: 2em; 43e5c31af7Sopenharmony_ci margin-left: auto; 44e5c31af7Sopenharmony_ci margin-right: auto; 45e5c31af7Sopenharmony_ci } 46e5c31af7Sopenharmony_ci 47e5c31af7Sopenharmony_ci /* All heading elements */ 48e5c31af7Sopenharmony_ci ol > li > .heading { 49e5c31af7Sopenharmony_ci font-family: arial; 50e5c31af7Sopenharmony_ci } 51e5c31af7Sopenharmony_ci 52e5c31af7Sopenharmony_ci /* Heading 1 elements */ 53e5c31af7Sopenharmony_ci ol.h1 { 54e5c31af7Sopenharmony_ci font-size: 15pt; 55e5c31af7Sopenharmony_ci margin-top: 1em; 56e5c31af7Sopenharmony_ci padding-left: 1em; 57e5c31af7Sopenharmony_ci list-style: upper-roman; 58e5c31af7Sopenharmony_ci list-style-position: inside; 59e5c31af7Sopenharmony_ci } 60e5c31af7Sopenharmony_ci 61e5c31af7Sopenharmony_ci ol.h1 > li { 62e5c31af7Sopenharmony_ci margin-top: 2.0em; 63e5c31af7Sopenharmony_ci } 64e5c31af7Sopenharmony_ci 65e5c31af7Sopenharmony_ci ol.h1 > li > .heading { 66e5c31af7Sopenharmony_ci } 67e5c31af7Sopenharmony_ci 68e5c31af7Sopenharmony_ci /* Heading 2 elements */ 69e5c31af7Sopenharmony_ci ol.h2 { 70e5c31af7Sopenharmony_ci font-size: 13pt; 71e5c31af7Sopenharmony_ci margin-top: 1.0em; 72e5c31af7Sopenharmony_ci margin-bottom: 0.5em; 73e5c31af7Sopenharmony_ci 74e5c31af7Sopenharmony_ci padding-left: 1em; 75e5c31af7Sopenharmony_ci } 76e5c31af7Sopenharmony_ci 77e5c31af7Sopenharmony_ci ol.h2 > li { 78e5c31af7Sopenharmony_ci margin-top: 1.25em; 79e5c31af7Sopenharmony_ci } 80e5c31af7Sopenharmony_ci 81e5c31af7Sopenharmony_ci ol.h2 > li > .heading { 82e5c31af7Sopenharmony_ci 83e5c31af7Sopenharmony_ci } 84e5c31af7Sopenharmony_ci 85e5c31af7Sopenharmony_ci ul { 86e5c31af7Sopenharmony_ci margin-bottom: 0.5em; 87e5c31af7Sopenharmony_ci } 88e5c31af7Sopenharmony_ci 89e5c31af7Sopenharmony_ci p { 90e5c31af7Sopenharmony_ci font-size: 12pt; 91e5c31af7Sopenharmony_ci margin: 0.6em; 92e5c31af7Sopenharmony_ci margin-left: 1.3em; 93e5c31af7Sopenharmony_ci border: 0px; 94e5c31af7Sopenharmony_ci } 95e5c31af7Sopenharmony_ci 96e5c31af7Sopenharmony_ci table { 97e5c31af7Sopenharmony_ci font-size: 12pt; 98e5c31af7Sopenharmony_ci margin: 0.6em; 99e5c31af7Sopenharmony_ci margin-left: 1.6em; 100e5c31af7Sopenharmony_ci border: 0px; 101e5c31af7Sopenharmony_ci } 102e5c31af7Sopenharmony_ci 103e5c31af7Sopenharmony_ci table td { 104e5c31af7Sopenharmony_ci padding-right: 10px; 105e5c31af7Sopenharmony_ci } 106e5c31af7Sopenharmony_ci 107e5c31af7Sopenharmony_ci .prettyprint { 108e5c31af7Sopenharmony_ci font-size: 10pt; 109e5c31af7Sopenharmony_ci margin: 0px; 110e5c31af7Sopenharmony_ci margin-left: 2.0em; 111e5c31af7Sopenharmony_ci margin-bottom: 1.0em; 112e5c31af7Sopenharmony_ci padding: 0.1em; 113e5c31af7Sopenharmony_ci padding-left: 0.2em; 114e5c31af7Sopenharmony_ci border: 1px solid black; 115e5c31af7Sopenharmony_ci background-color: #ddd; 116e5c31af7Sopenharmony_ci width: 93%; 117e5c31af7Sopenharmony_ci } 118e5c31af7Sopenharmony_ci 119e5c31af7Sopenharmony_ci .codeTitle { 120e5c31af7Sopenharmony_ci font-style: italic; 121e5c31af7Sopenharmony_ci font-size: 11pt; 122e5c31af7Sopenharmony_ci margin-top: 0.5em; 123e5c31af7Sopenharmony_ci margin-left: 2.0em; 124e5c31af7Sopenharmony_ci margin-bottom: 0px; 125e5c31af7Sopenharmony_ci } 126e5c31af7Sopenharmony_ci 127e5c31af7Sopenharmony_ci</style> 128e5c31af7Sopenharmony_ci 129e5c31af7Sopenharmony_ci<!-- \todo embed --> 130e5c31af7Sopenharmony_ci<link href="prettify.css" type="text/css" rel="stylesheet" /> 131e5c31af7Sopenharmony_ci<script type="text/javascript" src="prettify.js"></script> 132e5c31af7Sopenharmony_ci 133e5c31af7Sopenharmony_ci</head> 134e5c31af7Sopenharmony_ci 135e5c31af7Sopenharmony_ci<body onLoad="prettyPrint()"> 136e5c31af7Sopenharmony_ci 137e5c31af7Sopenharmony_ci<div class="body"> 138e5c31af7Sopenharmony_ci 139e5c31af7Sopenharmony_ci<div class="title">drawElements Coding Guidelines</div> 140e5c31af7Sopenharmony_ci<hr width="50%" /> 141e5c31af7Sopenharmony_ci<div class="quote">"Always code as if the person who will maintain your code is a maniac serial killer that knows where you live."</div> 142e5c31af7Sopenharmony_ci 143e5c31af7Sopenharmony_ci<div class="copyright">Copyright © 2014 The Android Open Source Project</div> 144e5c31af7Sopenharmony_ci 145e5c31af7Sopenharmony_ci<ol class="h1"> 146e5c31af7Sopenharmony_ci <li><span class="heading">Table of Contents</span> 147e5c31af7Sopenharmony_ci <ol class="h2"> 148e5c31af7Sopenharmony_ci TODO: fill in, with links (use JavaScript?) 149e5c31af7Sopenharmony_ci </ol> 150e5c31af7Sopenharmony_ci </li> 151e5c31af7Sopenharmony_ci 152e5c31af7Sopenharmony_ci <li><span class="heading">Introduction</span> 153e5c31af7Sopenharmony_ci <ol class="h2"> 154e5c31af7Sopenharmony_ci <li><span class="heading">Goal and philosophy</span> 155e5c31af7Sopenharmony_ci <p>This document describes the drawElements coding style for C and C++ languages.</p> 156e5c31af7Sopenharmony_ci 157e5c31af7Sopenharmony_ci <p>The intention of the drawElements coding guidelines is to allow us to produce code written in a 158e5c31af7Sopenharmony_ci consistent fashion, so that our product line will look similar throughout the line. The guiding 159e5c31af7Sopenharmony_ci philosophy for choosing the described coding style is to avoid bugs when writing code, keep the code 160e5c31af7Sopenharmony_ci maintainable, and also aim to make it beautiful. Some of the decisions are purely a matter of taste, 161e5c31af7Sopenharmony_ci but have been made to keep the code consistent overall (say, camelCasing versus underscore_usage in 162e5c31af7Sopenharmony_ci variable names.</p> 163e5c31af7Sopenharmony_ci 164e5c31af7Sopenharmony_ci <p>There are also many areas which are not covered by this document and there is some room to bring 165e5c31af7Sopenharmony_ci your own style into the soup. Some of the ways of writing code are just purely matters of opinion. 166e5c31af7Sopenharmony_ci The use of whitespace in code is a good example.</p> 167e5c31af7Sopenharmony_ci 168e5c31af7Sopenharmony_ci <p>This document is *not* the law of drawElements. If there is a good reason to deviate from it, you 169e5c31af7Sopenharmony_ci should do that. However, if the reason is purely a matter of taste, then please follow the rules set 170e5c31af7Sopenharmony_ci in here. Also, we want to encourage discussion about these guidelines and contributing to them, in 171e5c31af7Sopenharmony_ci case you disagree or know a way of doing something better. This is meant to be an evolving document 172e5c31af7Sopenharmony_ci that follows us as we learn as a group.</p> 173e5c31af7Sopenharmony_ci 174e5c31af7Sopenharmony_ci <p>A lot of examples are included in this document to make things easily readable and unambiguous. 175e5c31af7Sopenharmony_ci For more source material, feel free to browse the source code of whichever drawElements projects 176e5c31af7Sopenharmony_ci you have visibility to. You should see at least <i>debase</i> and <i>depool</i> libraries, if nothing 177e5c31af7Sopenharmony_ci else.</p> 178e5c31af7Sopenharmony_ci </li> 179e5c31af7Sopenharmony_ci 180e5c31af7Sopenharmony_ci <li><span class="heading">Languages of choice</span> 181e5c31af7Sopenharmony_ci <p>The main languages at drawElements are Ansi C89 and ISO C++ 98. Ansi C is used for developing 182e5c31af7Sopenharmony_ci driver or middleware IP, while C++ can be used for stand-alone applications.</p> 183e5c31af7Sopenharmony_ci 184e5c31af7Sopenharmony_ci <p>The reason for using C for middleware IP development is that we build software for 185e5c31af7Sopenharmony_ci mobile devices and the compilers there are often of dubious quality, especially when it comes to 186e5c31af7Sopenharmony_ci support of C++. In addition C++ runtime library is a non-trivial dependency.</p> 187e5c31af7Sopenharmony_ci 188e5c31af7Sopenharmony_ci <p>Stand-alone userspace applications can be written in ISO C++11.</p> 189e5c31af7Sopenharmony_ci 190e5c31af7Sopenharmony_ci <p>For utility and tool development, other languages may also be used. So far, Python has been used 191e5c31af7Sopenharmony_ci for all such development and is encouraged to be used in future tools as well. If there are strong 192e5c31af7Sopenharmony_ci reasons, other languages may also be considered.</p> 193e5c31af7Sopenharmony_ci </li> 194e5c31af7Sopenharmony_ci 195e5c31af7Sopenharmony_ci <li><span class="heading">C code example</span> 196e5c31af7Sopenharmony_ci 197e5c31af7Sopenharmony_ci <p>Let's get started with some sample drawElements code. The code files below show a simple random 198e5c31af7Sopenharmony_ci "class" implemented in C89. The code is taken from the drawElements base portability library, debase.</p> 199e5c31af7Sopenharmony_ci <div class="codeTitle">deRandom.h: The header file.</div> 200e5c31af7Sopenharmony_ci<pre class="prettyprint"> 201e5c31af7Sopenharmony_ci#ifndef _DERANDOM_H 202e5c31af7Sopenharmony_ci#define _DERANDOM_H 203e5c31af7Sopenharmony_ci/*------------------------------------------------------------------------- 204e5c31af7Sopenharmony_ci * drawElements Base Portability Library 205e5c31af7Sopenharmony_ci * ------------------------------------- 206e5c31af7Sopenharmony_ci * 207e5c31af7Sopenharmony_ci * Copyright 2014 The Android Open Source Project 208e5c31af7Sopenharmony_ci * 209e5c31af7Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 210e5c31af7Sopenharmony_ci * you may not use this file except in compliance with the License. 211e5c31af7Sopenharmony_ci * You may obtain a copy of the License at 212e5c31af7Sopenharmony_ci * 213e5c31af7Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 214e5c31af7Sopenharmony_ci * 215e5c31af7Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 216e5c31af7Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 217e5c31af7Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 218e5c31af7Sopenharmony_ci * See the License for the specific language governing permissions and 219e5c31af7Sopenharmony_ci * limitations under the License. 220e5c31af7Sopenharmony_ci * 221e5c31af7Sopenharmony_ci * Id: $Id$ 222e5c31af7Sopenharmony_ci *//*! 223e5c31af7Sopenharmony_ci * \file 224e5c31af7Sopenharmony_ci * \brief Random number generation. 225e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/ 226e5c31af7Sopenharmony_ci 227e5c31af7Sopenharmony_ci#ifndef _DEDEFS_H 228e5c31af7Sopenharmony_ci# include "deDefs.h" 229e5c31af7Sopenharmony_ci#endif 230e5c31af7Sopenharmony_ci 231e5c31af7Sopenharmony_ciDE_BEGIN_EXTERN_C 232e5c31af7Sopenharmony_ci 233e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*! 234e5c31af7Sopenharmony_ci * \brief Random number generator. 235e5c31af7Sopenharmony_ci * 236e5c31af7Sopenharmony_ci * Uses the Xorshift algorithm for producing pseudo-random numbers. The 237e5c31af7Sopenharmony_ci * values are generated based on an initial seed and the same seed always 238e5c31af7Sopenharmony_ci * produces the same sequence of numbers. 239e5c31af7Sopenharmony_ci * 240e5c31af7Sopenharmony_ci * See: http://en.wikipedia.org/wiki/Xorshift 241e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/ 242e5c31af7Sopenharmony_citypedef struct deRandom_s 243e5c31af7Sopenharmony_ci{ 244e5c31af7Sopenharmony_ci deUint32 x; /*!< Current random state. */ 245e5c31af7Sopenharmony_ci deUint32 y; 246e5c31af7Sopenharmony_ci deUint32 z; 247e5c31af7Sopenharmony_ci deUint32 w; 248e5c31af7Sopenharmony_ci} deRandom; 249e5c31af7Sopenharmony_ci 250e5c31af7Sopenharmony_civoid deRandom_init (deRandom* rnd, deUint32 seed); 251e5c31af7Sopenharmony_cideUint32 deRandom_getUint32 (deRandom* rnd); 252e5c31af7Sopenharmony_cifloat deRandom_getFloat (deRandom* rnd); 253e5c31af7Sopenharmony_cideBool deRandom_getBool (deRandom* rnd); 254e5c31af7Sopenharmony_ci 255e5c31af7Sopenharmony_ciDE_END_EXTERN_C 256e5c31af7Sopenharmony_ci 257e5c31af7Sopenharmony_ci#endif /* _DERANDOM_H */ 258e5c31af7Sopenharmony_ci</pre> 259e5c31af7Sopenharmony_ci <div class="codeTitle">deRandom.c: The implementation file.</div> 260e5c31af7Sopenharmony_ci<pre class="prettyprint"> 261e5c31af7Sopenharmony_ci/*------------------------------------------------------------------------- 262e5c31af7Sopenharmony_ci * drawElements Base Portability Library 263e5c31af7Sopenharmony_ci * ------------------------------------- 264e5c31af7Sopenharmony_ci * 265e5c31af7Sopenharmony_ci * Copyright 2014 The Android Open Source Project 266e5c31af7Sopenharmony_ci * \todo insert legalese here. 267e5c31af7Sopenharmony_ci * 268e5c31af7Sopenharmony_ci * Id: $Id$ 269e5c31af7Sopenharmony_ci *//*! 270e5c31af7Sopenharmony_ci * \file 271e5c31af7Sopenharmony_ci * \brief Random number generation. 272e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/ 273e5c31af7Sopenharmony_ci 274e5c31af7Sopenharmony_ci#include "deRandom.h" 275e5c31af7Sopenharmony_ci 276e5c31af7Sopenharmony_ci#include <float.h> 277e5c31af7Sopenharmony_ci#include <math.h> 278e5c31af7Sopenharmony_ci 279e5c31af7Sopenharmony_ciDE_BEGIN_EXTERN_C 280e5c31af7Sopenharmony_ci 281e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*! 282e5c31af7Sopenharmony_ci * \brief Initialize a random number generator with a given seed. 283e5c31af7Sopenharmony_ci * \param rnd RNG to initialize. 284e5c31af7Sopenharmony_ci * \param seed Seed value used for random values. 285e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/ 286e5c31af7Sopenharmony_civoid deRandom_init (deRandom* rnd, deUint32 seed) 287e5c31af7Sopenharmony_ci{ 288e5c31af7Sopenharmony_ci rnd->x = (deUint32)(-(int)seed ^ 123456789); 289e5c31af7Sopenharmony_ci rnd->y = (deUint32)(362436069 * seed); 290e5c31af7Sopenharmony_ci rnd->z = (deUint32)(521288629 ^ (seed >> 7)); 291e5c31af7Sopenharmony_ci rnd->w = (deUint32)(88675123 ^ (seed << 3)); 292e5c31af7Sopenharmony_ci} 293e5c31af7Sopenharmony_ci 294e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*! 295e5c31af7Sopenharmony_ci * \brief Get a pseudo random uint32. 296e5c31af7Sopenharmony_ci * \param rnd Pointer to RNG. 297e5c31af7Sopenharmony_ci * \return Random uint32 number. 298e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/ 299e5c31af7Sopenharmony_cideUint32 deRandom_getUint32 (deRandom* rnd) 300e5c31af7Sopenharmony_ci{ 301e5c31af7Sopenharmony_ci const deUint32 w = rnd->w; 302e5c31af7Sopenharmony_ci deUint32 t; 303e5c31af7Sopenharmony_ci 304e5c31af7Sopenharmony_ci t = rnd->x ^ (rnd->x << 11); 305e5c31af7Sopenharmony_ci rnd->x = rnd->y; 306e5c31af7Sopenharmony_ci rnd->y = rnd->z; 307e5c31af7Sopenharmony_ci rnd->z = w; 308e5c31af7Sopenharmony_ci rnd->w = w = (w ^ (w >> 19)) ^ (t ^ (t >> 8)); 309e5c31af7Sopenharmony_ci return w; 310e5c31af7Sopenharmony_ci} 311e5c31af7Sopenharmony_ci 312e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*! 313e5c31af7Sopenharmony_ci * \brief Get a pseudo random float in range [0, 1[. 314e5c31af7Sopenharmony_ci * \param rnd Pointer to RNG. 315e5c31af7Sopenharmony_ci * \return Random float number. 316e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/ 317e5c31af7Sopenharmony_cifloat deRandom_getFloat (deRandom* rnd) 318e5c31af7Sopenharmony_ci{ 319e5c31af7Sopenharmony_ci return (deRandom_getUint32(rnd) & 0xFFFFFFFu) / (float)(0xFFFFFFFu+1); 320e5c31af7Sopenharmony_ci} 321e5c31af7Sopenharmony_ci 322e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*! 323e5c31af7Sopenharmony_ci * \brief Get a pseudo random boolean value (DE_FALSE or DE_TRUE). 324e5c31af7Sopenharmony_ci * \param rnd Pointer to RNG. 325e5c31af7Sopenharmony_ci * \return Random float number. 326e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/ 327e5c31af7Sopenharmony_cideBool deRandom_getBool (deRandom* rnd) 328e5c31af7Sopenharmony_ci{ 329e5c31af7Sopenharmony_ci deUint32 val = deRandom_getUint32(rnd); 330e5c31af7Sopenharmony_ci return ((val & 0xFFFFFF) < 0x800000); 331e5c31af7Sopenharmony_ci} 332e5c31af7Sopenharmony_ci 333e5c31af7Sopenharmony_ciDE_END_EXTERN_C 334e5c31af7Sopenharmony_ci</pre> 335e5c31af7Sopenharmony_ci </li> 336e5c31af7Sopenharmony_ci <li><span class="heading">C++ code example</span> 337e5c31af7Sopenharmony_ci 338e5c31af7Sopenharmony_ci <p>The following code, taken from deutil demonstrates how C++ classes should look like.</p> 339e5c31af7Sopenharmony_ci <div class="codeTitle">deUniquePtr.hpp: Unique pointer template.</div> 340e5c31af7Sopenharmony_ci<pre class="prettyprint"> 341e5c31af7Sopenharmony_ci#ifndef _DEUNIQUEPTR_HPP 342e5c31af7Sopenharmony_ci#define _DEUNIQUEPTR_HPP 343e5c31af7Sopenharmony_ci/*------------------------------------------------------------------------- 344e5c31af7Sopenharmony_ci * drawElements C++ Base Library 345e5c31af7Sopenharmony_ci * ----------------------------- 346e5c31af7Sopenharmony_ci * 347e5c31af7Sopenharmony_ci * Copyright 2014 The Android Open Source Project 348e5c31af7Sopenharmony_ci * 349e5c31af7Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 350e5c31af7Sopenharmony_ci * you may not use this file except in compliance with the License. 351e5c31af7Sopenharmony_ci * You may obtain a copy of the License at 352e5c31af7Sopenharmony_ci * 353e5c31af7Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 354e5c31af7Sopenharmony_ci * 355e5c31af7Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 356e5c31af7Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 357e5c31af7Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 358e5c31af7Sopenharmony_ci * See the License for the specific language governing permissions and 359e5c31af7Sopenharmony_ci * limitations under the License. 360e5c31af7Sopenharmony_ci * 361e5c31af7Sopenharmony_ci *//*! 362e5c31af7Sopenharmony_ci * \file 363e5c31af7Sopenharmony_ci * \brief Unique pointer. 364e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/ 365e5c31af7Sopenharmony_ci 366e5c31af7Sopenharmony_ci#ifndef _DEDEFS_HPP 367e5c31af7Sopenharmony_ci# include "deDefs.hpp" 368e5c31af7Sopenharmony_ci#endif 369e5c31af7Sopenharmony_ci 370e5c31af7Sopenharmony_cinamespace de 371e5c31af7Sopenharmony_ci{ 372e5c31af7Sopenharmony_ci 373e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*! 374e5c31af7Sopenharmony_ci * \brief Unique pointer 375e5c31af7Sopenharmony_ci * 376e5c31af7Sopenharmony_ci * UniquePtr is smart pointer that retains sole ownership of a pointer 377e5c31af7Sopenharmony_ci * and destroys it when UniquePtr is destroyed (for example when UniquePtr 378e5c31af7Sopenharmony_ci * goes out of scope). 379e5c31af7Sopenharmony_ci * 380e5c31af7Sopenharmony_ci * UniquePtr is not copyable or assignable. Pointer ownership cannot be 381e5c31af7Sopenharmony_ci * transferred between UniquePtr's. 382e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/ 383e5c31af7Sopenharmony_citemplate<typename T, class Deleter = DefaultDeleter<T> > 384e5c31af7Sopenharmony_ciclass UniquePtr 385e5c31af7Sopenharmony_ci{ 386e5c31af7Sopenharmony_cipublic: 387e5c31af7Sopenharmony_ci explicit UniquePtr (T* const ptr, Deleter deleter = Deleter()); 388e5c31af7Sopenharmony_ci ~UniquePtr (void); 389e5c31af7Sopenharmony_ci 390e5c31af7Sopenharmony_ci T* get (void) const throw() { return m_ptr; } //!< Get stored pointer. 391e5c31af7Sopenharmony_ci T* operator-> (void) const throw() { return m_ptr; } //!< Get stored pointer. 392e5c31af7Sopenharmony_ci T& operator* (void) const throw() { return *m_ptr; } //!< De-reference stored pointer. 393e5c31af7Sopenharmony_ci 394e5c31af7Sopenharmony_ci operator bool (void) const throw() { return !!m_ptr; } 395e5c31af7Sopenharmony_ci 396e5c31af7Sopenharmony_ciprivate: 397e5c31af7Sopenharmony_ci UniquePtr (const UniquePtr<T>& other); // Not allowed! 398e5c31af7Sopenharmony_ci UniquePtr operator= (const UniquePtr<T>& other); // Not allowed! 399e5c31af7Sopenharmony_ci 400e5c31af7Sopenharmony_ci T* const m_ptr; 401e5c31af7Sopenharmony_ci Deleter m_deleter; 402e5c31af7Sopenharmony_ci}; 403e5c31af7Sopenharmony_ci 404e5c31af7Sopenharmony_ci/*--------------------------------------------------------------------*//*! 405e5c31af7Sopenharmony_ci * \brief Construct unique pointer. 406e5c31af7Sopenharmony_ci * \param ptr Pointer to be managed. 407e5c31af7Sopenharmony_ci * 408e5c31af7Sopenharmony_ci * Pointer ownership is transferred to the UniquePtr. 409e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/ 410e5c31af7Sopenharmony_citemplate<typename T, class Deleter> 411e5c31af7Sopenharmony_ciinline UniquePtr<T, Deleter>::UniquePtr (T* const ptr, Deleter deleter) 412e5c31af7Sopenharmony_ci : m_ptr (ptr) 413e5c31af7Sopenharmony_ci , m_deleter (deleter) 414e5c31af7Sopenharmony_ci{ 415e5c31af7Sopenharmony_ci} 416e5c31af7Sopenharmony_ci 417e5c31af7Sopenharmony_citemplate<typename T, class Deleter> 418e5c31af7Sopenharmony_ciinline UniquePtr<T, Deleter>::~UniquePtr (void) 419e5c31af7Sopenharmony_ci{ 420e5c31af7Sopenharmony_ci m_deleter(m_ptr); 421e5c31af7Sopenharmony_ci} 422e5c31af7Sopenharmony_ci 423e5c31af7Sopenharmony_ci} // de 424e5c31af7Sopenharmony_ci 425e5c31af7Sopenharmony_ci#endif // _DEUNIQUEPTR_HPP 426e5c31af7Sopenharmony_ci</pre> 427e5c31af7Sopenharmony_ci </li> 428e5c31af7Sopenharmony_ci </ol> 429e5c31af7Sopenharmony_ci </li> 430e5c31af7Sopenharmony_ci 431e5c31af7Sopenharmony_ci <li><span class="heading">Naming conventions and formatting</span> 432e5c31af7Sopenharmony_ci <ol class="h2"> 433e5c31af7Sopenharmony_ci <li><span class="heading">Basic naming conventions</span> 434e5c31af7Sopenharmony_ci <p>Each project should have a prefix of its own. For drawElements base libraries, 435e5c31af7Sopenharmony_ci the prefix <i>de</i> is used. Other projects should use a different, arbitrary prefix. 436e5c31af7Sopenharmony_ci For instance, the stitcher project uses the <i>xo</i> prefix.</p> 437e5c31af7Sopenharmony_ci 438e5c31af7Sopenharmony_ci <p>Anything which has a reasonable possibility of causing a naming conflict should be 439e5c31af7Sopenharmony_ci prefixed. This includes files, structs, enums, functions (except private ones), macros, etc. 440e5c31af7Sopenharmony_ci In C projects, just about everything in the code needs to be prefixed (files, struct, enums, 441e5c31af7Sopenharmony_ci global functions, etc.), but in C++ code, namespaces remove the need for most prefixing. 442e5c31af7Sopenharmony_ci File names and macros should still be prefixed in C++ code as well. Note that members 443e5c31af7Sopenharmony_ci of classes (either C or C++), or structs or unions do not need to be prefixed with the 444e5c31af7Sopenharmony_ci package prefix.</p> 445e5c31af7Sopenharmony_ci 446e5c31af7Sopenharmony_ci <p>Identifiers are generally typed in camelCase. This applies to file names, structs, 447e5c31af7Sopenharmony_ci enums, local variables, and struct members. In some cases, prefixes are used to clarify 448e5c31af7Sopenharmony_ci the behavior of a variable. Static variables are prefixed with <i>s_</i>, global variables 449e5c31af7Sopenharmony_ci with <i>g_</i>, and C++ class member variables with <i>m_</i>. Macros and enum entries should 450e5c31af7Sopenharmony_ci always be written in UPPER_CASE with underscores separating the words. Members of C classes 451e5c31af7Sopenharmony_ci don't need to be prefixed.</p> 452e5c31af7Sopenharmony_ci 453e5c31af7Sopenharmony_ci <p>When emulating classes in C, the class name itself should be written in CamelCase, but 454e5c31af7Sopenharmony_ci starting with a upper-case letter. Usually the classes are prefixed: <i>xoArmEmu</i>, 455e5c31af7Sopenharmony_ci <i>deRandom</i>, but if the class only exists within a single .c file, the prefix can be 456e5c31af7Sopenharmony_ci omitted: <i>StringBuilder</i>. The member functions of the class should be prefixed with 457e5c31af7Sopenharmony_ci the full class name and an underscore, followed by a camelCased function name: 458e5c31af7Sopenharmony_ci <i>xoArmEmu_emulateCode().</i></p> 459e5c31af7Sopenharmony_ci 460e5c31af7Sopenharmony_ci <p>Examples of correctly named identifiers:</p> 461e5c31af7Sopenharmony_ci <ul> 462e5c31af7Sopenharmony_ci <li><i>dePool.c, dePool.h, deUniquePtr.hpp, deThread.cpp</i> -- file names</li> 463e5c31af7Sopenharmony_ci <li><i>deRandom, xoStitcher</i> -- structs / classes</li> 464e5c31af7Sopenharmony_ci <li><i>deMemPoolFlag, xoConditionCode</i> -- enums</li> 465e5c31af7Sopenharmony_ci <li><i>DE_COMPILER_MSC</i> -- macros</li> 466e5c31af7Sopenharmony_ci <li><i>XO_BACKEND_NEON</i> -- enum entry</li> 467e5c31af7Sopenharmony_ci <li><i>setTableSize()</i> -- local (static) function</li> 468e5c31af7Sopenharmony_ci <li><i>xoArmEmu_emulateCode()</i> -- C class member function</li> 469e5c31af7Sopenharmony_ci <li><i>numVariables</i> -- local variable</li> 470e5c31af7Sopenharmony_ci <li><i>m_itemHash</i> -- member variable in a C++ class</li> 471e5c31af7Sopenharmony_ci <li><i>s_rcpTable</i> -- static variable in a function</li> 472e5c31af7Sopenharmony_ci <li><i>g_debugFlag</i> -- global variable</li> 473e5c31af7Sopenharmony_ci </ul> 474e5c31af7Sopenharmony_ci </li> 475e5c31af7Sopenharmony_ci 476e5c31af7Sopenharmony_ci <li><span class="heading">Choosing good names</span> 477e5c31af7Sopenharmony_ci <p>Naming your variables is somewhat of a black art, but the main goal of giving a name should 478e5c31af7Sopenharmony_ci be clarity. You want to communicate what the contents of the variable mean. The more obscure 479e5c31af7Sopenharmony_ci the purpose of a variable is, the longer (and more descriptive) a name you should invent for it. 480e5c31af7Sopenharmony_ci Also, the longer the life time of a variable is, the longer a name it deserves. For example, a 481e5c31af7Sopenharmony_ci loop counter which is alive for page worth of code should be named something like <i>vertexNdx</i>, 482e5c31af7Sopenharmony_ci whereas a loop counter which lives only a couple of lines can be named simply <i>i</i> or <i>ndx</i>.</p> 483e5c31af7Sopenharmony_ci 484e5c31af7Sopenharmony_ci <p>Most variables should be declared const and never changed (see coding philosophy section). 485e5c31af7Sopenharmony_ci Thus one often successful approach for variable naming is to give name for the value instead. 486e5c31af7Sopenharmony_ci For example when querying first child of node and storing it in variable, that should be named 487e5c31af7Sopenharmony_ci as <i>firstChild</i> instead of <i>node</i>.</p> 488e5c31af7Sopenharmony_ci 489e5c31af7Sopenharmony_ci <p>Consistency is one important factor in naming variables. When a similar kind of name is needed 490e5c31af7Sopenharmony_ci in multiple places, choose a way of devising the name and stick to that. E.g., if you query the 491e5c31af7Sopenharmony_ci number of elements in an array to a local variable in several functions, always use the same name 492e5c31af7Sopenharmony_ci in each of the functions.</p> 493e5c31af7Sopenharmony_ci 494e5c31af7Sopenharmony_ci <p>When dealing with counts or numbers (number of elements in an array, etc.), you should always 495e5c31af7Sopenharmony_ci clearly indicate with the name that this is the case, e.g., <i>numElements</i> (preferred), 496e5c31af7Sopenharmony_ci <i>elementCount</i>, etc. Which ever prefix or postfix you choose to use, stick to it.</p> 497e5c31af7Sopenharmony_ci 498e5c31af7Sopenharmony_ci <p>Function parameters that have an unit of measure (e.g. seconds or bytes) should have the unit 499e5c31af7Sopenharmony_ci as part of the name, for example <i>timeLimitMs</i> and <i>chunkSizeKb</i>.</p> 500e5c31af7Sopenharmony_ci 501e5c31af7Sopenharmony_ci <p>Use American English instead of English English. Choose gray over grey, color over colour, 502e5c31af7Sopenharmony_ci and so forth.</p> 503e5c31af7Sopenharmony_ci </li> 504e5c31af7Sopenharmony_ci <li><span class="heading">Canonical abbreviations</span> 505e5c31af7Sopenharmony_ci <table border="0" cellspacing="0"> 506e5c31af7Sopenharmony_ci <tr><td>buffer </td> <td>buf</td></tr> 507e5c31af7Sopenharmony_ci <tr><td>destination </td> <td>dst</td></tr> 508e5c31af7Sopenharmony_ci <tr><td>index </td> <td>ndx</td></tr> 509e5c31af7Sopenharmony_ci <tr><td>source </td> <td>src</td></tr> 510e5c31af7Sopenharmony_ci <tr><td>variable </td> <td>var</td></tr> 511e5c31af7Sopenharmony_ci </table> 512e5c31af7Sopenharmony_ci </li> 513e5c31af7Sopenharmony_ci 514e5c31af7Sopenharmony_ci <li><span class="heading">Struct and enum typedeffing</span> 515e5c31af7Sopenharmony_ci <p>For enums and structs, the types should always be typedeffed and used without the struct or 516e5c31af7Sopenharmony_ci enum prefix in actual code.</p> 517e5c31af7Sopenharmony_ci 518e5c31af7Sopenharmony_ci <div class="codeTitle">Example.</div> 519e5c31af7Sopenharmony_ci<pre class="prettyprint"> 520e5c31af7Sopenharmony_ci/* Declaration. */ 521e5c31af7Sopenharmony_citypedef enum xoConditionCode_e 522e5c31af7Sopenharmony_ci{ 523e5c31af7Sopenharmony_ci ... 524e5c31af7Sopenharmony_ci} xoConditionCode; 525e5c31af7Sopenharmony_ci 526e5c31af7Sopenharmony_citypedef struct deMempool_s 527e5c31af7Sopenharmony_ci{ 528e5c31af7Sopenharmony_ci ... 529e5c31af7Sopenharmony_ci} deMemPool; 530e5c31af7Sopenharmony_ci 531e5c31af7Sopenharmony_ci/* Usage. */ 532e5c31af7Sopenharmony_cideMemPool* memPool; 533e5c31af7Sopenharmony_cixoConditionCode condCode; 534e5c31af7Sopenharmony_ci</pre> 535e5c31af7Sopenharmony_ci </li> 536e5c31af7Sopenharmony_ci 537e5c31af7Sopenharmony_ci <li><span class="heading">Header files and including</span> 538e5c31af7Sopenharmony_ci <p>All header files should have include guards in them to avoid processing them multiple times 539e5c31af7Sopenharmony_ci in case they are included from multiple places. The style used for the macro is <i>_FILENAME_H</i>, 540e5c31af7Sopenharmony_ci for example: <i>_DEDEFS_H</i>. Whenever including other headers from a header file, you should 541e5c31af7Sopenharmony_ci always use external include guards as well. The external include guards considerably reduce the 542e5c31af7Sopenharmony_ci number of file accesses that the compiler needs to make, resulting in faster compile times.</p> 543e5c31af7Sopenharmony_ci 544e5c31af7Sopenharmony_ci <p>Each implementation file should have matching header file and vice versa. The implementation 545e5c31af7Sopenharmony_ci file must include the corresponding header file first. By doing that, it is guaranteed that the 546e5c31af7Sopenharmony_ci header file includes all of its dependencies.</p> 547e5c31af7Sopenharmony_ci 548e5c31af7Sopenharmony_ci <p>Each header file should first include <i>deDefs.h</i>, or alternatively project-specific 549e5c31af7Sopenharmony_ci <i>xxDefs.h/hpp</i> file that in turn includes deDefs.h. That way all the usual types and macros 550e5c31af7Sopenharmony_ci are always properly defined.</p> 551e5c31af7Sopenharmony_ci 552e5c31af7Sopenharmony_ci <div class="codeTitle">External include guard example.</div> 553e5c31af7Sopenharmony_ci<pre class="prettyprint"> 554e5c31af7Sopenharmony_ci#ifndef _DEDEFS_H 555e5c31af7Sopenharmony_ci# include "deDefs.h" 556e5c31af7Sopenharmony_ci#endif 557e5c31af7Sopenharmony_ci#ifndef _DEINT32_H 558e5c31af7Sopenharmony_ci# include "deInt32.h" 559e5c31af7Sopenharmony_ci#endif 560e5c31af7Sopenharmony_ci#ifndef _DEUNIQUEPTR_HPP 561e5c31af7Sopenharmony_ci# include "deUniquePtr.hpp" 562e5c31af7Sopenharmony_ci#endif 563e5c31af7Sopenharmony_ci</pre> 564e5c31af7Sopenharmony_ci 565e5c31af7Sopenharmony_ci <p>The include order of files should start from <i>debase</i> (esp. <i>deDefs.h</i>), go thru 566e5c31af7Sopenharmony_ci other base libraries, then your own project header files, and lastly the system header files. 567e5c31af7Sopenharmony_ci Also, a <i>.c</i> file must include its own header file first. E.g., <i>deMemPool.c</i> must 568e5c31af7Sopenharmony_ci first include <i>deMemPool.h</i>.</p> 569e5c31af7Sopenharmony_ci 570e5c31af7Sopenharmony_ci <p>Every include path must also end up including <i>deDefs.h</i> before any actual code is processed. 571e5c31af7Sopenharmony_ci This ensures that the basic portability macros (<i>DE_OS</i>, <i>DE_COMPILE</i>, etc.) have been 572e5c31af7Sopenharmony_ci defined.</p> 573e5c31af7Sopenharmony_ci </li> 574e5c31af7Sopenharmony_ci 575e5c31af7Sopenharmony_ci <li><span class="heading">Indenting and whitespace</span> 576e5c31af7Sopenharmony_ci <p>Code should be indented with tabs (instead of spaces) and a tab-width of 4 characters should 577e5c31af7Sopenharmony_ci be used.</p> 578e5c31af7Sopenharmony_ci 579e5c31af7Sopenharmony_ci <p>Always put braces on their own lines. This applies to functions, structs, enums, ifs, loops, 580e5c31af7Sopenharmony_ci everything. The only exception are single-line scopes. For one-statement ifs or loops, braces 581e5c31af7Sopenharmony_ci should not be used. Also, put <i>else</i> and <i>else if</i> on their own lines as well.</p> 582e5c31af7Sopenharmony_ci 583e5c31af7Sopenharmony_ci <div class="codeTitle">Brace usage</div> 584e5c31af7Sopenharmony_ci<pre class="prettyprint"> 585e5c31af7Sopenharmony_civoid main (int argc, const char** argv) 586e5c31af7Sopenharmony_ci{ 587e5c31af7Sopenharmony_ci if (argc > 1) 588e5c31af7Sopenharmony_ci parseArgs(argv[1]); 589e5c31af7Sopenharmony_ci else 590e5c31af7Sopenharmony_ci { 591e5c31af7Sopenharmony_ci printf("Usage:\n"); 592e5c31af7Sopenharmony_ci printf("...\n"); 593e5c31af7Sopenharmony_ci } 594e5c31af7Sopenharmony_ci} 595e5c31af7Sopenharmony_ci</pre> 596e5c31af7Sopenharmony_ci 597e5c31af7Sopenharmony_ci <p>In addition to only indenting your code, things like variable names in a list of 598e5c31af7Sopenharmony_ci declarations or comments at the end of line, should also be aligned such that they start at 599e5c31af7Sopenharmony_ci the same column. Compare the following two examples of the same code, only with differing 600e5c31af7Sopenharmony_ci alignments in the text.</p> 601e5c31af7Sopenharmony_ci 602e5c31af7Sopenharmony_ci <div class="codeTitle">Aligned variable declarations and comments.</div> 603e5c31af7Sopenharmony_ci<pre class="prettyprint"> 604e5c31af7Sopenharmony_cistruct deMemPool_s 605e5c31af7Sopenharmony_ci{ 606e5c31af7Sopenharmony_ci deUint32 flags; /*!< Flags. */ 607e5c31af7Sopenharmony_ci deMemPool* parent; /*!< Pointer to parent (null for root pools). */ 608e5c31af7Sopenharmony_ci deMemPoolUtil* util; /*!< Utilities (callbacks etc.). */ 609e5c31af7Sopenharmony_ci int numChildren; /*!< Number of child pools. */ 610e5c31af7Sopenharmony_ci deMemPool* firstChild; /*!< Pointer to first child pool in linked list. */ 611e5c31af7Sopenharmony_ci deMemPool* prevPool; /*!< Previous pool in parent's linked list. */ 612e5c31af7Sopenharmony_ci deMemPool* nextPool; /*!< Next pool in parent's linked list. */ 613e5c31af7Sopenharmony_ci ... 614e5c31af7Sopenharmony_ci}; 615e5c31af7Sopenharmony_ci</pre> 616e5c31af7Sopenharmony_ci 617e5c31af7Sopenharmony_ci <div class="codeTitle">No alignments used.</div> 618e5c31af7Sopenharmony_ci<pre class="prettyprint"> 619e5c31af7Sopenharmony_cistruct deMemPool_s 620e5c31af7Sopenharmony_ci{ 621e5c31af7Sopenharmony_ci deUint32 flags; /*!< Flags. */ 622e5c31af7Sopenharmony_ci deMemPool* parent; /*!< Pointer to parent (null for root pools). */ 623e5c31af7Sopenharmony_ci deMemPoolUtil* util; /*!< Utilities (callbacks etc.). */ 624e5c31af7Sopenharmony_ci int numChildren; /*!< Number of child pools. */ 625e5c31af7Sopenharmony_ci deMemPool* firstChild; /*!< Pointer to first child pool in linked list. */ 626e5c31af7Sopenharmony_ci deMemPool* prevPool; /*!< Previous pool in parent's linked list. */ 627e5c31af7Sopenharmony_ci deMemPool* nextPool; /*!< Next pool in parent's linked list. */ 628e5c31af7Sopenharmony_ci ... 629e5c31af7Sopenharmony_ci}; 630e5c31af7Sopenharmony_ci</pre> 631e5c31af7Sopenharmony_ci </li> 632e5c31af7Sopenharmony_ci 633e5c31af7Sopenharmony_ci <li><span class="heading">Other formatting</span> 634e5c31af7Sopenharmony_ci 635e5c31af7Sopenharmony_ci <p>Always use C-style comments in C code: /* This is a C comment. */ Only use 636e5c31af7Sopenharmony_ci the C++ // end-of-line comments in C++ code.</p> 637e5c31af7Sopenharmony_ci 638e5c31af7Sopenharmony_ci <div class="codeTitle">Comment styles.</div> 639e5c31af7Sopenharmony_ci<pre class="prettyprint"> 640e5c31af7Sopenharmony_ci/* Use this kind of comments in C code. */ 641e5c31af7Sopenharmony_ci 642e5c31af7Sopenharmony_ci// This kind of comments may only be used in C++ code. 643e5c31af7Sopenharmony_ci</pre> 644e5c31af7Sopenharmony_ci 645e5c31af7Sopenharmony_ci <div class="codeTitle">Pointer and references.</div> 646e5c31af7Sopenharmony_ci<pre class="prettyprint"> 647e5c31af7Sopenharmony_ci// Good: pointers and references are a part of the type 648e5c31af7Sopenharmony_civoid* ptr; 649e5c31af7Sopenharmony_cideInt32* colorBuffer; 650e5c31af7Sopenharmony_cixoArmEmu* armEmu; 651e5c31af7Sopenharmony_ciArray<int>& intArray; 652e5c31af7Sopenharmony_civoid doBlend (deUint32* dst, const deUint32* src); 653e5c31af7Sopenharmony_ci 654e5c31af7Sopenharmony_ci// Bad: pointer symbol should not be a part of the name 655e5c31af7Sopenharmony_civoid *ptr; 656e5c31af7Sopenharmony_civoid doBlend (deUint32 *dst, const deUint32 * src); 657e5c31af7Sopenharmony_ci</pre> 658e5c31af7Sopenharmony_ci 659e5c31af7Sopenharmony_ci <div class="codeTitle">Formatting of function declarations.</div> 660e5c31af7Sopenharmony_ci<pre class="prettyprint"> 661e5c31af7Sopenharmony_ci// Good: void if empty param list, empty space after name, braces on own line 662e5c31af7Sopenharmony_civoid doStuff (void) 663e5c31af7Sopenharmony_ci{ 664e5c31af7Sopenharmony_ci} 665e5c31af7Sopenharmony_ci 666e5c31af7Sopenharmony_ci// Bad: horrible function name! 667e5c31af7Sopenharmony_civoid doStuff() { 668e5c31af7Sopenharmony_ci} 669e5c31af7Sopenharmony_ci 670e5c31af7Sopenharmony_ci// Good: separate arguments with spaces, function name 671e5c31af7Sopenharmony_ciShapeList getIntersectingShapes (float x, float y, float z) 672e5c31af7Sopenharmony_ci{ 673e5c31af7Sopenharmony_ci} 674e5c31af7Sopenharmony_ci 675e5c31af7Sopenharmony_ci// Bad: function name (list of what volumes?), no space after commas in arg list 676e5c31af7Sopenharmony_ciShapeList getShapeList (float x,float y,float z) 677e5c31af7Sopenharmony_ci{ 678e5c31af7Sopenharmony_ci} 679e5c31af7Sopenharmony_ci 680e5c31af7Sopenharmony_ci// Exception: sometimes simple function are best written as one-liners 681e5c31af7Sopenharmony_cifloat deFloatAbs (float f) { return (f < 0.0f) ? -f : f; } 682e5c31af7Sopenharmony_ci 683e5c31af7Sopenharmony_ci</pre> 684e5c31af7Sopenharmony_ci 685e5c31af7Sopenharmony_ci <div class="codeTitle">Formatting of control statements.</div> 686e5c31af7Sopenharmony_ci<pre class="prettyprint"> 687e5c31af7Sopenharmony_ci// Good: no extra braces for one-liner if cases 688e5c31af7Sopenharmony_ciif (a.isZero) 689e5c31af7Sopenharmony_ci result = 0.0f; 690e5c31af7Sopenharmony_cielse 691e5c31af7Sopenharmony_ci result = a.value * (1.0 / 65536.0f); 692e5c31af7Sopenharmony_ci 693e5c31af7Sopenharmony_ci// Bad: extraneous braces, bad whitespace usage 694e5c31af7Sopenharmony_ciif (a.isZero) 695e5c31af7Sopenharmony_ci{ 696e5c31af7Sopenharmony_ci result=0.0f; 697e5c31af7Sopenharmony_ci} 698e5c31af7Sopenharmony_cielse 699e5c31af7Sopenharmony_ci{ 700e5c31af7Sopenharmony_ci result=a.value*(1.0 / 65536.0f); 701e5c31af7Sopenharmony_ci} 702e5c31af7Sopenharmony_ci 703e5c31af7Sopenharmony_ci// Good: expression easy to read 704e5c31af7Sopenharmony_ciif (a.isZero && b.isZero) 705e5c31af7Sopenharmony_ci{ 706e5c31af7Sopenharmony_ci ... 707e5c31af7Sopenharmony_ci} 708e5c31af7Sopenharmony_ci 709e5c31af7Sopenharmony_ci// Bad: missing spaces around && operator, missing space after 'if' 710e5c31af7Sopenharmony_ciif(a.isZero&&b.isZero) 711e5c31af7Sopenharmony_ci{ 712e5c31af7Sopenharmony_ci ... 713e5c31af7Sopenharmony_ci} 714e5c31af7Sopenharmony_ci 715e5c31af7Sopenharmony_ci// Good: else on its own line 716e5c31af7Sopenharmony_ciif (alpha == 0) 717e5c31af7Sopenharmony_ci{ 718e5c31af7Sopenharmony_ci ... 719e5c31af7Sopenharmony_ci} 720e5c31af7Sopenharmony_cielse if (alpha == 255) 721e5c31af7Sopenharmony_ci{ 722e5c31af7Sopenharmony_ci ... 723e5c31af7Sopenharmony_ci} 724e5c31af7Sopenharmony_cielse 725e5c31af7Sopenharmony_ci{ 726e5c31af7Sopenharmony_ci ... 727e5c31af7Sopenharmony_ci} 728e5c31af7Sopenharmony_ci 729e5c31af7Sopenharmony_ci// Bad: else on same line as closing brace 730e5c31af7Sopenharmony_ciif (alpha == 0) 731e5c31af7Sopenharmony_ci{ 732e5c31af7Sopenharmony_ci ... 733e5c31af7Sopenharmony_ci} else if (...) 734e5c31af7Sopenharmony_ci{ 735e5c31af7Sopenharmony_ci ... 736e5c31af7Sopenharmony_ci} else 737e5c31af7Sopenharmony_ci{ 738e5c31af7Sopenharmony_ci ... 739e5c31af7Sopenharmony_ci} 740e5c31af7Sopenharmony_ci 741e5c31af7Sopenharmony_ci// Good: note space after 'while' 742e5c31af7Sopenharmony_ciwhile (numTriangles--) 743e5c31af7Sopenharmony_ci{ 744e5c31af7Sopenharmony_ci ... 745e5c31af7Sopenharmony_ci} 746e5c31af7Sopenharmony_ci 747e5c31af7Sopenharmony_ci// Bad: whitespace usage 748e5c31af7Sopenharmony_ciwhile(numTriangles --) 749e5c31af7Sopenharmony_ci{ 750e5c31af7Sopenharmony_ci ... 751e5c31af7Sopenharmony_ci} 752e5c31af7Sopenharmony_ci 753e5c31af7Sopenharmony_ci// Good: while on same line as closing brace 754e5c31af7Sopenharmony_cido 755e5c31af7Sopenharmony_ci{ 756e5c31af7Sopenharmony_ci ... 757e5c31af7Sopenharmony_ci} while (--numTriangles); 758e5c31af7Sopenharmony_ci 759e5c31af7Sopenharmony_ci// Bad: while on its own line, missing whitespace after 'while' 760e5c31af7Sopenharmony_cido 761e5c31af7Sopenharmony_ci{ 762e5c31af7Sopenharmony_ci ... 763e5c31af7Sopenharmony_ci} 764e5c31af7Sopenharmony_ciwhile(--numTriangles); 765e5c31af7Sopenharmony_ci 766e5c31af7Sopenharmony_ci// Good: easy to read 767e5c31af7Sopenharmony_cifor (ndx = 0; ndx < numTriangles; ndx++) 768e5c31af7Sopenharmony_ci 769e5c31af7Sopenharmony_ci// Bad: missing spaces all over (whitespace should be used to separate expressions) 770e5c31af7Sopenharmony_cifor(ndx=0;ndx<numTriangles;ndx ++) 771e5c31af7Sopenharmony_ci 772e5c31af7Sopenharmony_ci// Good: note missing braces for while, correct usage of whitespace 773e5c31af7Sopenharmony_ciwhile (numTriangles--) 774e5c31af7Sopenharmony_ci area += computeArea(triangle[ndx++]); 775e5c31af7Sopenharmony_ci 776e5c31af7Sopenharmony_ci// Bad: don't put unnecessary braces, avoid extraneous whitespace in expressions 777e5c31af7Sopenharmony_ciwhile (numTriangles--) 778e5c31af7Sopenharmony_ci{ 779e5c31af7Sopenharmony_ci area+=computeArea( triangle [ndx++] ); 780e5c31af7Sopenharmony_ci} 781e5c31af7Sopenharmony_ci</pre> 782e5c31af7Sopenharmony_ci 783e5c31af7Sopenharmony_ci <div class="codeTitle">Formatting switch cases.</div> 784e5c31af7Sopenharmony_ci<pre class="prettyprint"> 785e5c31af7Sopenharmony_ci// Good: case-statements indented, code indented another level (including breaks) 786e5c31af7Sopenharmony_ciswitch (blendMode) 787e5c31af7Sopenharmony_ci{ 788e5c31af7Sopenharmony_ci case XX_BLENDMODE_NORMAL: // no variable declarations 789e5c31af7Sopenharmony_ci ... 790e5c31af7Sopenharmony_ci break; 791e5c31af7Sopenharmony_ci 792e5c31af7Sopenharmony_ci case XX_BLENDMODE_SRC_OVER: // need braces if declaring variables inside 793e5c31af7Sopenharmony_ci { 794e5c31af7Sopenharmony_ci int alpha = ...; 795e5c31af7Sopenharmony_ci break; 796e5c31af7Sopenharmony_ci } 797e5c31af7Sopenharmony_ci 798e5c31af7Sopenharmony_ci case XX_BLENDMODE_XYZ: 799e5c31af7Sopenharmony_ci ... 800e5c31af7Sopenharmony_ci // FALLTHRU! -- make non-breaked cases very explicit! 801e5c31af7Sopenharmony_ci 802e5c31af7Sopenharmony_ci default: // handles the final blendmode (DISABLED) with an assertion! 803e5c31af7Sopenharmony_ci DE_ASSERT(blendMode == XX_BLENDMODE_DISABLED); 804e5c31af7Sopenharmony_ci 805e5c31af7Sopenharmony_ci break; // always put break! 806e5c31af7Sopenharmony_ci} 807e5c31af7Sopenharmony_ci 808e5c31af7Sopenharmony_ci// Bad: 809e5c31af7Sopenharmony_ciswitch(blendMode) 810e5c31af7Sopenharmony_ci{ 811e5c31af7Sopenharmony_cicase XX_BLENDMODE_NORMAL: // always indent case labels 812e5c31af7Sopenharmony_ci ... 813e5c31af7Sopenharmony_cibreak; // put break on same level as indented code! 814e5c31af7Sopenharmony_ci 815e5c31af7Sopenharmony_cicase XX_BLENDMODE_SRC_OVER: 816e5c31af7Sopenharmony_ci { 817e5c31af7Sopenharmony_ci ... 818e5c31af7Sopenharmony_ci break; 819e5c31af7Sopenharmony_ci } 820e5c31af7Sopenharmony_ci 821e5c31af7Sopenharmony_cicase XX_BLENDMODE_XYZ: 822e5c31af7Sopenharmony_ci ... 823e5c31af7Sopenharmony_ci 824e5c31af7Sopenharmony_cicase XX_BLENDMODE_DISABLED: // always comment the case fall-through (like above) 825e5c31af7Sopenharmony_ci ... 826e5c31af7Sopenharmony_ci} // default case missing! always need to handle it (and assert if illegal!) 827e5c31af7Sopenharmony_ci</pre> 828e5c31af7Sopenharmony_ci 829e5c31af7Sopenharmony_ci <div class="codeTitle">Formatting of expressions.</div> 830e5c31af7Sopenharmony_ci<pre class="prettyprint"> 831e5c31af7Sopenharmony_ci// Good: parenthesis or whitespace used to indicate evaluation order 832e5c31af7Sopenharmony_ciarray[(a * b) + c]; 833e5c31af7Sopenharmony_ciarray[a*b + c]; 834e5c31af7Sopenharmony_ci 835e5c31af7Sopenharmony_ci// Bad: order unclear 836e5c31af7Sopenharmony_ciarray[a*b+c]; 837e5c31af7Sopenharmony_ci 838e5c31af7Sopenharmony_ci// Good: parenthesis (or whitespace) makes evaluation order unambiguous 839e5c31af7Sopenharmony_ciarray[(a && b) || (c == 0)] 840e5c31af7Sopenharmony_ciarray[a==0 || b==0 || c==0] // in some cases spaces can be used instead of parenthesis 841e5c31af7Sopenharmony_ci 842e5c31af7Sopenharmony_ci// Bad: unclear evaluation order 843e5c31af7Sopenharmony_ciarray[a&&b || c==0] // does this even work? 844e5c31af7Sopenharmony_ciarray[a == 0 || b == 0 || c == 0] 845e5c31af7Sopenharmony_ci 846e5c31af7Sopenharmony_ci// Good: easy to see different parts of evaluation (whitespace where it matters) 847e5c31af7Sopenharmony_ciarray[triangle->index0 - cache.baseIndex]; 848e5c31af7Sopenharmony_ci 849e5c31af7Sopenharmony_ci// Bad: hard to read (whitespace around brackets doesn't help readability!) 850e5c31af7Sopenharmony_ciarray[ triangle->index0-cache.baseIndex ]; 851e5c31af7Sopenharmony_ciarray [triangle -> index0 - cache.baseIndex]; 852e5c31af7Sopenharmony_ci 853e5c31af7Sopenharmony_ci// Good: easy to see all function arguments 854e5c31af7Sopenharmony_cicomputeArea(vtx0.x, vtx0.y, vtx1.x, vtx1.y, vtx2.x, vtx2.y); 855e5c31af7Sopenharmony_ci 856e5c31af7Sopenharmony_ci// Bad: missing spaces makes it hard to read, no space after function name when calling 857e5c31af7Sopenharmony_cicomputeArea ( vtx0.x,vtx0.y,vtx1.x,vtx1.y,vtx2.x,vtx2.y ); 858e5c31af7Sopenharmony_ci 859e5c31af7Sopenharmony_ci// Good: readable (the code itself is a made-up example and thus incomprehensible) 860e5c31af7Sopenharmony_ci// Consider: would probably make more readable code to use temporary variables here 861e5c31af7Sopenharmony_ciif (sizeArray[a+5] > getSize(getFoo()+2)) 862e5c31af7Sopenharmony_ciif (sizeArray[a + 5] > getSize(getFoo() + 2)) 863e5c31af7Sopenharmony_ci 864e5c31af7Sopenharmony_ci// Bad: whitespace usage confuses rather than helps 865e5c31af7Sopenharmony_ciif(sizeArray[a+5]>getSize(getFoo()+2)) 866e5c31af7Sopenharmony_ciif ( sizeArray [ a + 5 ] > getSize ( getFoo () + 2 ) ) 867e5c31af7Sopenharmony_ci 868e5c31af7Sopenharmony_ci// Bad: unclear (and wrong) evaluation order 869e5c31af7Sopenharmony_ciif (bitMask & (1<<bit) == 0) 870e5c31af7Sopenharmony_ci</pre> 871e5c31af7Sopenharmony_ci 872e5c31af7Sopenharmony_ci <div class="codeTitle">Other formatting.</div> 873e5c31af7Sopenharmony_ci<pre class="prettyprint"> 874e5c31af7Sopenharmony_ci#if defined(DE_DEBUG) // prefer #if defined() to #ifdef 875e5c31af7Sopenharmony_ci ... 876e5c31af7Sopenharmony_ci#endif /* DE_DEBUG */ // only put ending comment if #if is far away 877e5c31af7Sopenharmony_ci 878e5c31af7Sopenharmony_ci</pre> 879e5c31af7Sopenharmony_ci </li> 880e5c31af7Sopenharmony_ci </ol> 881e5c31af7Sopenharmony_ci </li> 882e5c31af7Sopenharmony_ci 883e5c31af7Sopenharmony_ci <li><span class="heading">Base library services</span> 884e5c31af7Sopenharmony_ci <p>TODO: explain all of these</p> 885e5c31af7Sopenharmony_ci 886e5c31af7Sopenharmony_ci <ol class="h2"> 887e5c31af7Sopenharmony_ci <li><span class="heading"><b>debase</b>/deDefs.h</span> 888e5c31af7Sopenharmony_ci <pre> 889e5c31af7Sopenharmony_ci- DE_COMPILER, DE_OS, DE_CPU 890e5c31af7Sopenharmony_ci- basic types (deUint8, deIntptr, deBool==int, ..) 891e5c31af7Sopenharmony_ci- DE_NULL 892e5c31af7Sopenharmony_ci- DE_DEBUG -- #if defined(DE_DEBUG) 893e5c31af7Sopenharmony_ci- DE_INLINE 894e5c31af7Sopenharmony_ci- DE_ASSERT(), DE_VERIFY(), DE_TEST_ASSERT(), DE_STATIC_ASSERT() 895e5c31af7Sopenharmony_ci- DE_BREAKPOINT() 896e5c31af7Sopenharmony_ci- DE_SWAP() 897e5c31af7Sopenharmony_ci- DE_LENGTH_OF_ARRAY() 898e5c31af7Sopenharmony_ci- DE_OFFSET_OF() 899e5c31af7Sopenharmony_ci- DE_UNREF() 900e5c31af7Sopenharmony_ci- DE_BEGIN_EXTERN_C, DE_END_EXTERN_C 901e5c31af7Sopenharmony_ci- DE_NULL_STATEMENT</pre> 902e5c31af7Sopenharmony_ci </li> 903e5c31af7Sopenharmony_ci 904e5c31af7Sopenharmony_ci <li><span class="heading">Other <b>debase</b> headers</span> 905e5c31af7Sopenharmony_ci <pre> 906e5c31af7Sopenharmony_ci- deInt32.h: deInRange32(), deInBounds32(), hashing 907e5c31af7Sopenharmony_ci- deFloat16.h: fp16<->fp32 908e5c31af7Sopenharmony_ci- deMath.h: generic float math 909e5c31af7Sopenharmony_ci- deRandom.h: random number generation 910e5c31af7Sopenharmony_ci- deMemory.h: allocating memory, deMemset(), deMemcpy(), DE_NEW(), DE_DELETE() 911e5c31af7Sopenharmony_ci- deString.h:</pre> 912e5c31af7Sopenharmony_ci </li> 913e5c31af7Sopenharmony_ci 914e5c31af7Sopenharmony_ci <li><span class="heading"><b>depool</b> services</span> 915e5c31af7Sopenharmony_ci <pre> 916e5c31af7Sopenharmony_ci- memory pools (deMemPool) 917e5c31af7Sopenharmony_ci- pooled data structures 918e5c31af7Sopenharmony_ci * Array 919e5c31af7Sopenharmony_ci * Set 920e5c31af7Sopenharmony_ci * Hash 921e5c31af7Sopenharmony_ci * HashArray 922e5c31af7Sopenharmony_ci * HashSet</pre> 923e5c31af7Sopenharmony_ci </li> 924e5c31af7Sopenharmony_ci </ol> 925e5c31af7Sopenharmony_ci </li> 926e5c31af7Sopenharmony_ci 927e5c31af7Sopenharmony_ci <li><span class="heading">Commenting code</span> 928e5c31af7Sopenharmony_ci <ol class="h2"> 929e5c31af7Sopenharmony_ci <li><span class="heading">File comment boxes</span> 930e5c31af7Sopenharmony_ci <p>Each source file should contain the following comment box. In header files the comment is placed after 931e5c31af7Sopenharmony_ci the #ifdef-#endif pair. On implementation files the comment box is placed at the beginning.</p> 932e5c31af7Sopenharmony_ci<pre class="prettyprint"> 933e5c31af7Sopenharmony_ci/*------------------------------------------------------------------------- 934e5c31af7Sopenharmony_ci * Full Module Name 935e5c31af7Sopenharmony_ci * ---------------- 936e5c31af7Sopenharmony_ci * 937e5c31af7Sopenharmony_ci * Copyright 2014 The Android Open Source Project 938e5c31af7Sopenharmony_ci * 939e5c31af7Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 940e5c31af7Sopenharmony_ci * you may not use this file except in compliance with the License. 941e5c31af7Sopenharmony_ci * You may obtain a copy of the License at 942e5c31af7Sopenharmony_ci * 943e5c31af7Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 944e5c31af7Sopenharmony_ci * 945e5c31af7Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 946e5c31af7Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 947e5c31af7Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 948e5c31af7Sopenharmony_ci * See the License for the specific language governing permissions and 949e5c31af7Sopenharmony_ci * limitations under the License. 950e5c31af7Sopenharmony_ci * 951e5c31af7Sopenharmony_ci *//*! 952e5c31af7Sopenharmony_ci * \file 953e5c31af7Sopenharmony_ci * \brief Short description of the contents. 954e5c31af7Sopenharmony_ci * 955e5c31af7Sopenharmony_ci * Followed by longer description if necessary (such as high-level algorithm 956e5c31af7Sopenharmony_ci * description). 957e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/ 958e5c31af7Sopenharmony_ci<pre> 959e5c31af7Sopenharmony_ci </li> 960e5c31af7Sopenharmony_ci 961e5c31af7Sopenharmony_ci <li><span class="heading">Structs/classes/enums comment boxes</span> 962e5c31af7Sopenharmony_ci <p>TODO: </p> 963e5c31af7Sopenharmony_ci </li> 964e5c31af7Sopenharmony_ci 965e5c31af7Sopenharmony_ci <li><span class="heading">Other Doxygen comment boxes (/** ... */ and /*!< ... */)</span> 966e5c31af7Sopenharmony_ci <p>TODO: single-line, multi-line</p> 967e5c31af7Sopenharmony_ci </li> 968e5c31af7Sopenharmony_ci 969e5c31af7Sopenharmony_ci <li><span class="heading">Code comments</span> 970e5c31af7Sopenharmony_ci <p>Below and example of code commenting for C. When doing C++, you can replace C-style comments with C++-comments.</p> 971e5c31af7Sopenharmony_ci <pre class="prettyprint"> 972e5c31af7Sopenharmony_cicallFoo(&a); 973e5c31af7Sopenharmony_ci 974e5c31af7Sopenharmony_ci/* Comment about following block (Note empty line before and after)*/ 975e5c31af7Sopenharmony_ci 976e5c31af7Sopenharmony_cicallBar(&b); 977e5c31af7Sopenharmony_cic = a + b; /* Why we need to do this op */ 978e5c31af7Sopenharmony_cidoItAll(a, b, c); 979e5c31af7Sopenharmony_ci 980e5c31af7Sopenharmony_ci/* Badness starts with this comment */ 981e5c31af7Sopenharmony_cicallBar(&b); 982e5c31af7Sopenharmony_ci/* Why we need to do this op */ 983e5c31af7Sopenharmony_cic = a + b; 984e5c31af7Sopenharmony_cidoItAll(a, b, c); 985e5c31af7Sopenharmony_ci 986e5c31af7Sopenharmony_ci </pre> 987e5c31af7Sopenharmony_ci </li> 988e5c31af7Sopenharmony_ci 989e5c31af7Sopenharmony_ci <li><span class="heading">Tags</span> 990e5c31af7Sopenharmony_ci <p>Todo-comments should use the following syntax:</p> 991e5c31af7Sopenharmony_ci<pre class="prettyprint"> 992e5c31af7Sopenharmony_ci/* \todo [2012-01-26 pyry] Give a longer description of todo-usage in code. */ 993e5c31af7Sopenharmony_ci</pre> 994e5c31af7Sopenharmony_ci <p>If you wish to communicate to fellow developer about some unexpected behavior or corner-case 995e5c31af7Sopenharmony_ci that is not obvious, <i>\note</i> tag can be used.</p> 996e5c31af7Sopenharmony_ci<pre class="prettyprint"> 997e5c31af7Sopenharmony_ci/* \note Tangent may be zero. */ 998e5c31af7Sopenharmony_ci</pre> 999e5c31af7Sopenharmony_ci </li> 1000e5c31af7Sopenharmony_ci </ol> 1001e5c31af7Sopenharmony_ci </li> 1002e5c31af7Sopenharmony_ci 1003e5c31af7Sopenharmony_ci <li><span class="heading">Generic programming</span> 1004e5c31af7Sopenharmony_ci <ol class="h2"> 1005e5c31af7Sopenharmony_ci <li><span class="heading">Classes in C</span> 1006e5c31af7Sopenharmony_ci <p>TODO: explain</p> 1007e5c31af7Sopenharmony_ci </li> 1008e5c31af7Sopenharmony_ci 1009e5c31af7Sopenharmony_ci <li><span class="heading">Const correctness</span> 1010e5c31af7Sopenharmony_ci <p>When declaring function arguments, local variables, or class members, all non-mutable ones 1011e5c31af7Sopenharmony_ci must be declared const. Declaring variable const communicates clearly your intent to not modify 1012e5c31af7Sopenharmony_ci the given value. This is especially important in function argument lists.</p> 1013e5c31af7Sopenharmony_ci 1014e5c31af7Sopenharmony_ci <p>Declaring local variables, or function arguments that are passed by value, const, may be a bit 1015e5c31af7Sopenharmony_ci controversial. There are indeed a lots of existing code that doesn't follow this rule. However, 1016e5c31af7Sopenharmony_ci adding extra constness has proven to improve code readability a quite bit and thus all new code 1017e5c31af7Sopenharmony_ci must use const correctly. The only exception is function arguments passed by value; for those 1018e5c31af7Sopenharmony_ci const keyword can be omitted. By-value function arguments are however considered to be const 1019e5c31af7Sopenharmony_ci for all purposes.</p> 1020e5c31af7Sopenharmony_ci 1021e5c31af7Sopenharmony_ci <div class="codeTitle">Example.</div> 1022e5c31af7Sopenharmony_ci<pre class="prettyprint"> 1023e5c31af7Sopenharmony_ci// Function example. Note const qualifier on maxDepth as well which is passed by value. 1024e5c31af7Sopenharmony_cistatic glu::VarType generateRandomType (const int maxDepth, int& curStructIdx, vector<const StructType*>& structTypesDst, Random& rnd) 1025e5c31af7Sopenharmony_ci{ 1026e5c31af7Sopenharmony_ci const bool isStruct = maxDepth > 0 && rnd.getFloat() < 0.2f; 1027e5c31af7Sopenharmony_ci const bool isArray = rnd.getFloat() < 0.3f; 1028e5c31af7Sopenharmony_ci 1029e5c31af7Sopenharmony_ci ... 1030e5c31af7Sopenharmony_ci} 1031e5c31af7Sopenharmony_ci 1032e5c31af7Sopenharmony_ci// Class members 1033e5c31af7Sopenharmony_ciclass Node 1034e5c31af7Sopenharmony_ci{ 1035e5c31af7Sopenharmony_cipublic: 1036e5c31af7Sopenharmony_ci Node (Node* const parent); 1037e5c31af7Sopenharmony_ci ~Node (void); 1038e5c31af7Sopenharmony_ci 1039e5c31af7Sopenharmony_ci ... 1040e5c31af7Sopenharmony_ciprivate: 1041e5c31af7Sopenharmony_ci Node* const m_parent; 1042e5c31af7Sopenharmony_ci}; 1043e5c31af7Sopenharmony_ci 1044e5c31af7Sopenharmony_ciNode::Node (Node* const parent) 1045e5c31af7Sopenharmony_ci : m_parent(parent) // Const members can be initialized 1046e5c31af7Sopenharmony_ci{ 1047e5c31af7Sopenharmony_ci} 1048e5c31af7Sopenharmony_ci</pre> 1049e5c31af7Sopenharmony_ci </li> 1050e5c31af7Sopenharmony_ci 1051e5c31af7Sopenharmony_ci <li><span class="heading">Declaring variables</span> 1052e5c31af7Sopenharmony_ci <p>All variables should be declared at the beginning of a block. If variables are introduced in 1053e5c31af7Sopenharmony_ci the middle of code, nested block must be used. This is what ANSI C requires, and the same style must 1054e5c31af7Sopenharmony_ci be used in C++ code as well. The only exception for this is loop counters in C++; they may be 1055e5c31af7Sopenharmony_ci declared in loop init expression.</p> 1056e5c31af7Sopenharmony_ci 1057e5c31af7Sopenharmony_ci <p>Having variable declarations always at the beginning of the block makes code easier to read 1058e5c31af7Sopenharmony_ci as no new state is introduced in the middle of code. It also guides towards writing smaller 1059e5c31af7Sopenharmony_ci functions that don't use too many variables.</p> 1060e5c31af7Sopenharmony_ci 1061e5c31af7Sopenharmony_ci <div class="codeTitle">Example.</div> 1062e5c31af7Sopenharmony_ci<pre class="prettyprint"> 1063e5c31af7Sopenharmony_cistatic void logTransformFeedbackVaryings (TestLog& log, const glw::Functions& gl, const deUint32 program) 1064e5c31af7Sopenharmony_ci{ 1065e5c31af7Sopenharmony_ci int numTfVaryngs = 0; 1066e5c31af7Sopenharmony_ci int maxNameLen = 0; 1067e5c31af7Sopenharmony_ci 1068e5c31af7Sopenharmony_ci gl.getProgramiv(program, GL_TRANSFORM_FEEDBACK_VARYINGS, &numTfVaryngs); 1069e5c31af7Sopenharmony_ci gl.getProgramiv(program, GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH, &maxNameLen); 1070e5c31af7Sopenharmony_ci GLU_EXPECT_NO_ERROR(gl.getError(), "Query TF varyings"); 1071e5c31af7Sopenharmony_ci 1072e5c31af7Sopenharmony_ci { 1073e5c31af7Sopenharmony_ci vector<char> nameBuf(maxNameLen+1); 1074e5c31af7Sopenharmony_ci 1075e5c31af7Sopenharmony_ci for (int ndx = 0; ndx < numTfVaryngs; ndx++) 1076e5c31af7Sopenharmony_ci { 1077e5c31af7Sopenharmony_ci ... 1078e5c31af7Sopenharmony_ci</pre> 1079e5c31af7Sopenharmony_ci </li> 1080e5c31af7Sopenharmony_ci 1081e5c31af7Sopenharmony_ci <li><span class="heading">Variable life-time</span> 1082e5c31af7Sopenharmony_ci <p>TODO: minimize life-time of a variable (may sometimes need additional scopes in C)</p> 1083e5c31af7Sopenharmony_ci </li> 1084e5c31af7Sopenharmony_ci 1085e5c31af7Sopenharmony_ci <li><span class="heading">Enumerations</span> 1086e5c31af7Sopenharmony_ci <p>TODO: assign zero to first, let compiler assign others (in typical lists)</p> 1087e5c31af7Sopenharmony_ci <p>TODO: use ENUM_LAST</p> 1088e5c31af7Sopenharmony_ci <p>TODO: mask values</p> 1089e5c31af7Sopenharmony_ci <p>TODO: use instead of #defines</p> 1090e5c31af7Sopenharmony_ci <p>TODO: typedef xxEnumName_e trick (already explained above?)</p> 1091e5c31af7Sopenharmony_ci </li> 1092e5c31af7Sopenharmony_ci 1093e5c31af7Sopenharmony_ci <li><span class="heading">Error handling</span> 1094e5c31af7Sopenharmony_ci <p>There are generally two types of errors that can occur in code; errors that stem from environment 1095e5c31af7Sopenharmony_ci or bad input, and errors that are caused by logic error in the code. Former ones are typically 1096e5c31af7Sopenharmony_ci outside our control (such as running into a network error) and latter are simply programming mistakes.</p> 1097e5c31af7Sopenharmony_ci 1098e5c31af7Sopenharmony_ci <p>External errors must be handled in a graceful way. Depending on the project it may include handling 1099e5c31af7Sopenharmony_ci out-of-memory situations as well (most certainly when doing drivers or middleware). In C function return 1100e5c31af7Sopenharmony_ci value should be used for communicating whether external error was hit. In C++ code exceptions can 1101e5c31af7Sopenharmony_ci be used as well. Assertions must not be used for checking external error conditions.</p> 1102e5c31af7Sopenharmony_ci 1103e5c31af7Sopenharmony_ci <p>Internal logic errors must be checked with assertions. See next section.</p> 1104e5c31af7Sopenharmony_ci </li> 1105e5c31af7Sopenharmony_ci 1106e5c31af7Sopenharmony_ci <li><span class="heading">Assertions</span> 1107e5c31af7Sopenharmony_ci <p>Assertions are a form of code documentation. They explicitly declare what the code expects from 1108e5c31af7Sopenharmony_ci input values or current state. They are tremendously useful when trying to understand how certain 1109e5c31af7Sopenharmony_ci piece of code should be used. In addition they are a very nice debugging aid as they help catch logic 1110e5c31af7Sopenharmony_ci errors early on before those errors get chance to corrupt program state.</p> 1111e5c31af7Sopenharmony_ci 1112e5c31af7Sopenharmony_ci <p>Functions should assert all non-trivial input data and conditions. The one notorious exception is 1113e5c31af7Sopenharmony_ci that pointer validity doesn't need to be asserted if the pointer is dereferenced immediately. 1114e5c31af7Sopenharmony_ci Non-trivial computation results should also be checked with assertions.</p> 1115e5c31af7Sopenharmony_ci 1116e5c31af7Sopenharmony_ci <div class="codeTitle">Example.</div> 1117e5c31af7Sopenharmony_ci<pre class="prettyprint"> 1118e5c31af7Sopenharmony_ci// Examples of good assertions: 1119e5c31af7Sopenharmony_civoid* deMemPool_alignedAlloc (deMemPool* pool, int numBytes, deUint32 alignBytes) 1120e5c31af7Sopenharmony_ci{ 1121e5c31af7Sopenharmony_ci void* ptr; 1122e5c31af7Sopenharmony_ci DE_ASSERT(pool); // Must be asserted since not dereferenced but passed to another function 1123e5c31af7Sopenharmony_ci DE_ASSERT(numBytes > 0); // Assertion on input data condition 1124e5c31af7Sopenharmony_ci DE_ASSERT(deIsPowerOfTwo32((int)alignBytes)); // Non-trivial input condition 1125e5c31af7Sopenharmony_ci ptr = deMemPool_allocInternal(pool, numBytes, alignBytes); 1126e5c31af7Sopenharmony_ci DE_ASSERT(deIsAlignedPtr(ptr, alignBytes)); // Assertion on computation result 1127e5c31af7Sopenharmony_ci return ptr; 1128e5c31af7Sopenharmony_ci} 1129e5c31af7Sopenharmony_ci 1130e5c31af7Sopenharmony_ci// Badness starts here 1131e5c31af7Sopenharmony_ci 1132e5c31af7Sopenharmony_civoid getTextureWidth (const Texture* texture) 1133e5c31af7Sopenharmony_ci{ 1134e5c31af7Sopenharmony_ci DE_ASSERT(texture); // Bad: unnecessary, will crash anyway if texture is null 1135e5c31af7Sopenharmony_ci return texture->width; 1136e5c31af7Sopenharmony_ci} 1137e5c31af7Sopenharmony_ci 1138e5c31af7Sopenharmony_civoid doStuff (void) 1139e5c31af7Sopenharmony_ci{ 1140e5c31af7Sopenharmony_ci int i = 3; 1141e5c31af7Sopenharmony_ci i += 2; 1142e5c31af7Sopenharmony_ci DE_ASSERT(i == 5); // Bad: assertion on trivial computation result 1143e5c31af7Sopenharmony_ci 1144e5c31af7Sopenharmony_ci FILE* f = fopen("myfile.txt", "rb"); 1145e5c31af7Sopenharmony_ci DE_ASSERT(f); // Bad: there are legitimate reasons for failure 1146e5c31af7Sopenharmony_ci} 1147e5c31af7Sopenharmony_ci</pre> 1148e5c31af7Sopenharmony_ci 1149e5c31af7Sopenharmony_ci </li> 1150e5c31af7Sopenharmony_ci 1151e5c31af7Sopenharmony_ci <li><span class="heading">Lookup tables</span> 1152e5c31af7Sopenharmony_ci <p>TODO: DE_STATIC_ASSERT lookup table size - should usually match to ENUM_TYPE_LAST</p> 1153e5c31af7Sopenharmony_ci 1154e5c31af7Sopenharmony_ci<pre class="prettyprint"> 1155e5c31af7Sopenharmony_citypedef enum xxBlendEquation_e 1156e5c31af7Sopenharmony_ci{ 1157e5c31af7Sopenharmony_ci XX_BLEND_EQUATION_ADD = 0, 1158e5c31af7Sopenharmony_ci XX_BLEND_EQUATION_SUBTRACT, 1159e5c31af7Sopenharmony_ci XX_BLEND_EQUATION_REVERSE_SUBTRACT, 1160e5c31af7Sopenharmony_ci 1161e5c31af7Sopenharmony_ci XX_BLEND_EQUATION_LAST 1162e5c31af7Sopenharmony_ci} xxBlendEquation; 1163e5c31af7Sopenharmony_ci 1164e5c31af7Sopenharmony_ci// Note: size is left for compiler to figure out 1165e5c31af7Sopenharmony_cistatic const s_blendModeMap[] = 1166e5c31af7Sopenharmony_ci{ 1167e5c31af7Sopenharmony_ci GL_FUNC_ADD, // XX_BLEND_EQUATION_ADD 1168e5c31af7Sopenharmony_ci GL_FUNC_SUBTRACT, // XX_BLEND_EQUATION_SUBTRACT 1169e5c31af7Sopenharmony_ci GL_FUNC_REVERSE_SUBTRACT // XX_BLEND_EQUATION_REVERSE_SUBTRACT 1170e5c31af7Sopenharmony_ci}; 1171e5c31af7Sopenharmony_ci// This will cause compilation failure lookup table size gets out of date 1172e5c31af7Sopenharmony_ciDE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_blendModeMap) == XX_BLEND_EQUATION_LAST); 1173e5c31af7Sopenharmony_ci</pre> 1174e5c31af7Sopenharmony_ci </li> 1175e5c31af7Sopenharmony_ci 1176e5c31af7Sopenharmony_ci <li><span class="heading">Struct size</span> 1177e5c31af7Sopenharmony_ci <p>TODO: DE_STATIC_ASSERT of struct sizes</p> 1178e5c31af7Sopenharmony_ci <p>TODO: use small datatypes (deUint8 instead of deBool) when size matters.</p> 1179e5c31af7Sopenharmony_ci </li> 1180e5c31af7Sopenharmony_ci 1181e5c31af7Sopenharmony_ci <li><span class="heading">Extraneous code</span> 1182e5c31af7Sopenharmony_ci <p>TODO: avoid too verbose code.</p> 1183e5c31af7Sopenharmony_ci 1184e5c31af7Sopenharmony_ci <div class="codeTitle">Example.</div> 1185e5c31af7Sopenharmony_ci<pre class="prettyprint"> 1186e5c31af7Sopenharmony_ci// Good: compact without sacrificing readability 1187e5c31af7Sopenharmony_cireturn (a < 0.0f) ? -a : a; 1188e5c31af7Sopenharmony_ci 1189e5c31af7Sopenharmony_ci// Bad: waste of space 1190e5c31af7Sopenharmony_cifloat result; 1191e5c31af7Sopenharmony_ciif (a < 0.0f) 1192e5c31af7Sopenharmony_ci{ 1193e5c31af7Sopenharmony_ci result = -a; 1194e5c31af7Sopenharmony_ci} 1195e5c31af7Sopenharmony_cielse 1196e5c31af7Sopenharmony_ci{ 1197e5c31af7Sopenharmony_ci result = a; 1198e5c31af7Sopenharmony_ci} 1199e5c31af7Sopenharmony_cireturn result; 1200e5c31af7Sopenharmony_ci</pre> 1201e5c31af7Sopenharmony_ci 1202e5c31af7Sopenharmony_ci </li> 1203e5c31af7Sopenharmony_ci </ol> 1204e5c31af7Sopenharmony_ci </li> 1205e5c31af7Sopenharmony_ci 1206e5c31af7Sopenharmony_ci <li><span class="heading">C++ topics</span> 1207e5c31af7Sopenharmony_ci <ol class="h2"> 1208e5c31af7Sopenharmony_ci <li><span class="heading">Class declarations</span> 1209e5c31af7Sopenharmony_ci <p>TODO: how declaration looks like (already shown in example..)</p> 1210e5c31af7Sopenharmony_ci <p>TODO: function definitions inside class ok if single-line, other special cases</p> 1211e5c31af7Sopenharmony_ci </li> 1212e5c31af7Sopenharmony_ci 1213e5c31af7Sopenharmony_ci <li><span class="heading">Class boilerplate</span> 1214e5c31af7Sopenharmony_ci <p>TODO: copy ctor, assignment operator</p> 1215e5c31af7Sopenharmony_ci </li> 1216e5c31af7Sopenharmony_ci 1217e5c31af7Sopenharmony_ci <li><span class="heading">Code Formatting</span> 1218e5c31af7Sopenharmony_ci<pre class="prettyprint"> 1219e5c31af7Sopenharmony_ci 1220e5c31af7Sopenharmony_ci// Constructors 1221e5c31af7Sopenharmony_ciFooAtom::FooAtom(int proton, float electron) 1222e5c31af7Sopenharmony_ci : m_proton (proton) // Note aligning member initializers. 1223e5c31af7Sopenharmony_ci , m_electron (electron) 1224e5c31af7Sopenharmony_ci{ 1225e5c31af7Sopenharmony_ci 1226e5c31af7Sopenharmony_ci} 1227e5c31af7Sopenharmony_ci 1228e5c31af7Sopenharmony_ci// Remember to add the name of the namespace at the end of the namespace 1229e5c31af7Sopenharmony_cinamespace foo 1230e5c31af7Sopenharmony_ci{ 1231e5c31af7Sopenharmony_ci 1232e5c31af7Sopenharmony_ci// Namespaces aren't indented 1233e5c31af7Sopenharmony_ciclass Proton; 1234e5c31af7Sopenharmony_ci 1235e5c31af7Sopenharmony_ci... 1236e5c31af7Sopenharmony_ci} // foo 1237e5c31af7Sopenharmony_ci</pre> 1238e5c31af7Sopenharmony_ci </li> 1239e5c31af7Sopenharmony_ci <li><span class="heading">RAII</span> 1240e5c31af7Sopenharmony_ci <p>Everyone should get familiar with RAII. In a nutshell, "resource acquisition is initialization" 1241e5c31af7Sopenharmony_ci means that a class destructor must always release all resources (such as memory or OS handles) 1242e5c31af7Sopenharmony_ci that have been allocated during the whole lifetime of the object.</p> 1243e5c31af7Sopenharmony_ci 1244e5c31af7Sopenharmony_ci <p>RAII is essential for exception-safe code. You should always make sure that if an exception is 1245e5c31af7Sopenharmony_ci thrown, including out-of-memory cases, your code behaves properly and releases all allocated resources.</p> 1246e5c31af7Sopenharmony_ci </li> 1247e5c31af7Sopenharmony_ci 1248e5c31af7Sopenharmony_ci <li><span class="heading">Pointers and references</span> 1249e5c31af7Sopenharmony_ci <p>In C++ references should be generally preferred over pointers. The main difference between pointers 1250e5c31af7Sopenharmony_ci and references is that references can not change, and are not expected to be null. References should be 1251e5c31af7Sopenharmony_ci used instead of pointers for passing objects when both conditions hold; object can not be null nor 1252e5c31af7Sopenharmony_ci reference won't be modified once initialized.</p> 1253e5c31af7Sopenharmony_ci <p>Pointers are used when there is need to change the address, or it can be null for a valid reason. 1254e5c31af7Sopenharmony_ci Additionally, pointers are always used for passing basic type or object arrays.</p> 1255e5c31af7Sopenharmony_ci </li> 1256e5c31af7Sopenharmony_ci 1257e5c31af7Sopenharmony_ci <li><span class="heading">Containers</span> 1258e5c31af7Sopenharmony_ci <p>TODO: describe stl container usage policies</p> 1259e5c31af7Sopenharmony_ci </li> 1260e5c31af7Sopenharmony_ci 1261e5c31af7Sopenharmony_ci <li><span class="heading">Exceptions</span> 1262e5c31af7Sopenharmony_ci <p>TODO: exceptions can be used, custom ones must be based on std::exception</p> 1263e5c31af7Sopenharmony_ci </li> 1264e5c31af7Sopenharmony_ci 1265e5c31af7Sopenharmony_ci <li><span class="heading">Polymorphism</span> 1266e5c31af7Sopenharmony_ci <p>TODO: when to use virtual functions, virtual destructor</p> 1267e5c31af7Sopenharmony_ci </li> 1268e5c31af7Sopenharmony_ci 1269e5c31af7Sopenharmony_ci <li><span class="heading">Namespaces</span> 1270e5c31af7Sopenharmony_ci <p>TODO: namespace naming</p> 1271e5c31af7Sopenharmony_ci <p>TODO: using statement, never using in headers</p> 1272e5c31af7Sopenharmony_ci </li> 1273e5c31af7Sopenharmony_ci 1274e5c31af7Sopenharmony_ci </ol> 1275e5c31af7Sopenharmony_ci </li> 1276e5c31af7Sopenharmony_ci 1277e5c31af7Sopenharmony_ci <li><span class="heading">Tools</span> 1278e5c31af7Sopenharmony_ci <ol class="h2"> 1279e5c31af7Sopenharmony_ci <li><span class="heading">Git</span> 1280e5c31af7Sopenharmony_ci <p>Git is currently the weapon of choice for source control management. Even though it is 1281e5c31af7Sopenharmony_ci not the perfect solution, it gets job done well, or at least better than most other solutions.</p> 1282e5c31af7Sopenharmony_ci 1283e5c31af7Sopenharmony_ci <p>Our repositories are hosted on github.com. You are allowed and encouraged to push any number 1284e5c31af7Sopenharmony_ci of new branches to the github repositories. Remember to clean up the obsolete ones after they 1285e5c31af7Sopenharmony_ci have been merged to master. But never delete a remote branch that hasn't been created by you.</p> 1286e5c31af7Sopenharmony_ci 1287e5c31af7Sopenharmony_ci <p>Before you commit anything, make sure <i>user.name</i> and <i>user.email</i> are properly set up.</p> 1288e5c31af7Sopenharmony_ci<pre class="prettyprint"> 1289e5c31af7Sopenharmony_cigit config --global user.name "Veijo Elements" 1290e5c31af7Sopenharmony_cigit config --global user.email "veijo.elements@drawelements.com" 1291e5c31af7Sopenharmony_ci</pre> 1292e5c31af7Sopenharmony_ci 1293e5c31af7Sopenharmony_ci <p>The standard line ending format for all text files is Unix-style. The best way to handle 1294e5c31af7Sopenharmony_ci line endings on Windows systems is to set <i>core.autocrlf</i> to <i>input</i>. That causes 1295e5c31af7Sopenharmony_ci conversion to Unix-style line endings on commit only (i.e. not in checkout).</p> 1296e5c31af7Sopenharmony_ci<pre class="prettyprint"> 1297e5c31af7Sopenharmony_cigit config --global core.autocrlf input 1298e5c31af7Sopenharmony_ci</pre> 1299e5c31af7Sopenharmony_ci 1300e5c31af7Sopenharmony_ci <p>In order to keep trailing whitespace out of source tree, a standard pre-commit hook must 1301e5c31af7Sopenharmony_ci be placed in each local clone of any source repositories.</p> 1302e5c31af7Sopenharmony_ci<pre class="prettyprint"> 1303e5c31af7Sopenharmony_ci# in repository directory 1304e5c31af7Sopenharmony_cicp ~/Dropbox/drawElements/Misc/git/pre-commit .git/hooks/ 1305e5c31af7Sopenharmony_ci</pre> 1306e5c31af7Sopenharmony_ci </li> 1307e5c31af7Sopenharmony_ci 1308e5c31af7Sopenharmony_ci <li><span class="heading">Build systems and IDEs</span> 1309e5c31af7Sopenharmony_ci <p>CMake is used as an official project file generator. CMake can be used to generate makefiles 1310e5c31af7Sopenharmony_ci or project files for most IDEs. Unless there is a good reason, you should use project files 1311e5c31af7Sopenharmony_ci generated by CMake.</p> 1312e5c31af7Sopenharmony_ci 1313e5c31af7Sopenharmony_ci <p>You are free to choose any IDE or editor you like. At least Visual Studio, vim and 1314e5c31af7Sopenharmony_ci emacs have been successfully used in the past. Good debugger integration is strongly recommended.</p> 1315e5c31af7Sopenharmony_ci </li> 1316e5c31af7Sopenharmony_ci </ol> 1317e5c31af7Sopenharmony_ci </li> 1318e5c31af7Sopenharmony_ci 1319e5c31af7Sopenharmony_ci <li><span class="heading">Coding philosophy</span> 1320e5c31af7Sopenharmony_ci <ol class="h2"> 1321e5c31af7Sopenharmony_ci <li><span class="heading">Designing classes</span> 1322e5c31af7Sopenharmony_ci <p>Each class should have only a single purpose to fulfill, and it should encapsulate that 1323e5c31af7Sopenharmony_ci entirely. All functionality that is secondary and doesn't require access to classes' internal 1324e5c31af7Sopenharmony_ci implementation should not be part of that class. This is called <a href="http://en.wikipedia.org/wiki/Single_responsibility_principle"> 1325e5c31af7Sopenharmony_ci single responsibility principle</a>. It is probably easier to grasp it with an example.</p> 1326e5c31af7Sopenharmony_ci 1327e5c31af7Sopenharmony_ci <p>Consider a <i>Texture2D</i> class that manages 2D-dimensional texture data. Such class is clearly 1328e5c31af7Sopenharmony_ci responsible for managing lifetime of the associated memory, and storing properties such as 1329e5c31af7Sopenharmony_ci size and format. Now, one could need a function for blitting (copying) portion of one texture 1330e5c31af7Sopenharmony_ci to some position in an another texture. This could be added as a method to texture class, but 1331e5c31af7Sopenharmony_ci it most certainly isn't core responsibility of that class. So correct way to implement that 1332e5c31af7Sopenharmony_ci is either as a plain function operating on publicly accessible methods of <i>Texture2D</i> class, 1333e5c31af7Sopenharmony_ci or as a separate <i>Blitter</i> class. Same applies to things such as reading texture from a file, 1334e5c31af7Sopenharmony_ci clearing the texture to a certain color and so forth.</p> 1335e5c31af7Sopenharmony_ci 1336e5c31af7Sopenharmony_ci <div class="codeTitle">Texture class example.</div> 1337e5c31af7Sopenharmony_ci<pre class="prettyprint"> 1338e5c31af7Sopenharmony_ciclass Texture2D 1339e5c31af7Sopenharmony_ci{ 1340e5c31af7Sopenharmony_cipublic: 1341e5c31af7Sopenharmony_ci Texture2D (const TextureFormat format, const int width, const int height); 1342e5c31af7Sopenharmony_ci Texture2D (const char* const filename); // Bad: not core functionality 1343e5c31af7Sopenharmony_ci ~Texture2D (void); 1344e5c31af7Sopenharmony_ci 1345e5c31af7Sopenharmony_ci // Good methods: essential functionality 1346e5c31af7Sopenharmony_ci Vec4 getPixel (const int x, const int y) const; 1347e5c31af7Sopenharmony_ci void setPixel (const int x, const int y, const Vec4& c); 1348e5c31af7Sopenharmony_ci const deUint8* getPixelPtr (void) const; 1349e5c31af7Sopenharmony_ci 1350e5c31af7Sopenharmony_ci // Bad: non-essential 1351e5c31af7Sopenharmony_ci void clear (const Vec4& c); 1352e5c31af7Sopenharmony_ci bool containsColor (const Vec4& c) const; 1353e5c31af7Sopenharmony_ci void setInitialized (void); // Why texture would store bit that belongs outside? 1354e5c31af7Sopenharmony_ci 1355e5c31af7Sopenharmony_ciprivate: 1356e5c31af7Sopenharmony_ci // Good: essential, minimum data set 1357e5c31af7Sopenharmony_ci vector<deUint8> m_pixels; 1358e5c31af7Sopenharmony_ci TextureFormat m_format; 1359e5c31af7Sopenharmony_ci int m_width; 1360e5c31af7Sopenharmony_ci int m_height; 1361e5c31af7Sopenharmony_ci 1362e5c31af7Sopenharmony_ci// deUint8* m_pixels; // Bad: explicit mem. mgmt, not core functionality 1363e5c31af7Sopenharmony_ci bool m_initialized; // Bad: extraneous information 1364e5c31af7Sopenharmony_ci}; 1365e5c31af7Sopenharmony_ci 1366e5c31af7Sopenharmony_ci// Good: independent functions operating on textures 1367e5c31af7Sopenharmony_civoid clearTexture (Texture2D& texture, const Vec4& color); 1368e5c31af7Sopenharmony_ciTexture2D* createFromFile (const char* const filename); 1369e5c31af7Sopenharmony_ci</pre> 1370e5c31af7Sopenharmony_ci <p>One sign of a successful class design is that the interface feels natural to use. Thus when 1371e5c31af7Sopenharmony_ci designing a new class from a scratch, you should start by writing the use cases first. Class 1372e5c31af7Sopenharmony_ci interface can be refined until it suits the most important use cases, and only then the 1373e5c31af7Sopenharmony_ci implementation is filled in. Doing things in reverse order often leads to interfaces that are 1374e5c31af7Sopenharmony_ci later found to be inadequate.</p> 1375e5c31af7Sopenharmony_ci 1376e5c31af7Sopenharmony_ci <p>When writing the internal implementation a lot of thought should be put on maintaining 1377e5c31af7Sopenharmony_ci consistent state, or more formally, <a href="http://en.wikipedia.org/wiki/Class_invariant">class invariant</a>. 1378e5c31af7Sopenharmony_ci Member variables in a class are a form of global state and thus special care must be taken 1379e5c31af7Sopenharmony_ci when manipulating that state. If class requires a lot of state, it can be helpful to group 1380e5c31af7Sopenharmony_ci some of the members into separate state-only classes whose sole responsibility is maintaining 1381e5c31af7Sopenharmony_ci the class invariant for that set of members. Another good pattern is to write a state validation 1382e5c31af7Sopenharmony_ci function that is called in debug builds after each non-trivial state change.</p> 1383e5c31af7Sopenharmony_ci 1384e5c31af7Sopenharmony_ci <p>Only a minimal set of class member variables should ever be used. If some value can be derived 1385e5c31af7Sopenharmony_ci with a relatively little effort from the minimal set of members, it must not be stored as a 1386e5c31af7Sopenharmony_ci member variable. In the <i>Texture2D</i> class example, length of a pixel row or image size can 1387e5c31af7Sopenharmony_ci be derived from size and format and thus member variables must not be used for them.</i> 1388e5c31af7Sopenharmony_ci 1389e5c31af7Sopenharmony_ci <!-- TODO: code example --> 1390e5c31af7Sopenharmony_ci 1391e5c31af7Sopenharmony_ci </li> 1392e5c31af7Sopenharmony_ci 1393e5c31af7Sopenharmony_ci <li><span class="heading">Global state</span> 1394e5c31af7Sopenharmony_ci <p>Pretty much everyone can agree that relying on global state is undesirable. However, what 1395e5c31af7Sopenharmony_ci is not always obvious is what counts as a global state. Global variables are clearly such state, 1396e5c31af7Sopenharmony_ci but many more can be considered as well. For example state encapsulated in shared objects, state 1397e5c31af7Sopenharmony_ci retained in library API, or even state passed in member variables between member functions 1398e5c31af7Sopenharmony_ci could be counted as a form global state. Another way to define global state is that it is anything 1399e5c31af7Sopenharmony_ci that can be passed from one function to another without including it in function call arguments.</p> 1400e5c31af7Sopenharmony_ci 1401e5c31af7Sopenharmony_ci <p>All forms of global state should be used only when necessary. Excluding some very rare cases, 1402e5c31af7Sopenharmony_ci mutable global variables are never necessary. Singletons are really just a fancier version of 1403e5c31af7Sopenharmony_ci global variables. Instead of using for example singleton for application log object, it should be 1404e5c31af7Sopenharmony_ci passed in explicitly to all objects and functions that require logging.</p> 1405e5c31af7Sopenharmony_ci 1406e5c31af7Sopenharmony_ci 1407e5c31af7Sopenharmony_ci </li> 1408e5c31af7Sopenharmony_ci 1409e5c31af7Sopenharmony_ci <li><span class="heading">Variables vs. immutable values</span> 1410e5c31af7Sopenharmony_ci <p>Traditional imperative programming puts emphasis on variables. They are thought of being 1411e5c31af7Sopenharmony_ci limited resource, used for storing immediate computation results for brief periods of time. 1412e5c31af7Sopenharmony_ci In early C days it was even common to declare variable <i>register</i> in order to communicate 1413e5c31af7Sopenharmony_ci the compiler that it should place the variable into a register. Things have changed a lot since 1414e5c31af7Sopenharmony_ci then, and it is no longer necessary to limit use of variables for performance reasons.</p> 1415e5c31af7Sopenharmony_ci 1416e5c31af7Sopenharmony_ci <p>Functional languages declare variables immutable, i.e. they are not really <i>var</i>ying 1417e5c31af7Sopenharmony_ci values, but instead named values. This often greatly improves code clarity and correctness, 1418e5c31af7Sopenharmony_ci as variables can not change unexpectedly. While imperative languages certainly need some amout 1419e5c31af7Sopenharmony_ci of mutability, the concept of immutable values certainly has advantages.</p> 1420e5c31af7Sopenharmony_ci 1421e5c31af7Sopenharmony_ci <p>As discussed in variable naming section, you often should name a single value, not some 1422e5c31af7Sopenharmony_ci storage slot for arbitrary set of values. In such case it makes a lot of sense to treat that 1423e5c31af7Sopenharmony_ci as immutable named value, not mutable varibale. In C and C++ that can be explicitly declared 1424e5c31af7Sopenharmony_ci with use of <i>const</i> qualifier.</p> 1425e5c31af7Sopenharmony_ci 1426e5c31af7Sopenharmony_ci <p>In general the amount of state that is considered mutable in any given context should be 1427e5c31af7Sopenharmony_ci minimized. Understanding code is a much more easier if number of things that can change is 1428e5c31af7Sopenharmony_ci small. This also guides code towards natural separation into smaller functions.</p> 1429e5c31af7Sopenharmony_ci 1430e5c31af7Sopenharmony_ci <p>Limiting number of mutable variables leads to a more functional programming style, where a 1431e5c31af7Sopenharmony_ci lot of computation done in initializer expressions at the beginning of a block. This is not 1432e5c31af7Sopenharmony_ci necessarily a bad thing as it requires separating any non-trivial computation into separate 1433e5c31af7Sopenharmony_ci functions. Most often we only need the result of such computation anyway, and how the 1434e5c31af7Sopenharmony_ci value itself is computed is not important for the problem at hand.</i> 1435e5c31af7Sopenharmony_ci 1436e5c31af7Sopenharmony_ci <div class="codeTitle">Complex code example.</div> 1437e5c31af7Sopenharmony_ci<pre class="prettyprint"> 1438e5c31af7Sopenharmony_cistd::vector<Node*> topologicalSortFromRoot (Node* const root) 1439e5c31af7Sopenharmony_ci{ 1440e5c31af7Sopenharmony_ci // Returning containers is OK if called functions are local and compiler 1441e5c31af7Sopenharmony_ci // can easily do return value optimization. 1442e5c31af7Sopenharmony_ci const std::vector<Node*> allNodes = collectAllNodesFromRoot(root); // Reduce number of mutables by computing outside 1443e5c31af7Sopenharmony_ci std::map<Node*, int> useCounts = computeUseCounts(allNodes); // Uses allNodes value, mutable 1444e5c31af7Sopenharmony_ci std::vector<Node*> liveSet; // Mutable as well 1445e5c31af7Sopenharmony_ci std::vector<Node*> sortedNodes; // Used as return value - only appended to 1446e5c31af7Sopenharmony_ci 1447e5c31af7Sopenharmony_ci // We have multiple mutables here. Invariant is that each node that has zero in useCount 1448e5c31af7Sopenharmony_ci // must be either in liveSet or sortedNodes, but not in both. 1449e5c31af7Sopenharmony_ci 1450e5c31af7Sopenharmony_ci for (std::vector<Node*>::iterator nodeIter = allNodes.begin(); 1451e5c31af7Sopenharmony_ci nodeIter != allNodes.end(); 1452e5c31af7Sopenharmony_ci ++nodeIter) 1453e5c31af7Sopenharmony_ci { 1454e5c31af7Sopenharmony_ci // Note that nodeIter is not considered mutable here - instead it is iteration-specific 1455e5c31af7Sopenharmony_ci // immutable value. 1456e5c31af7Sopenharmony_ci if (useCounts[*nodeIter] == 0) 1457e5c31af7Sopenharmony_ci liveSet.push_back(*nodeIter); // liveSet is used as return value here 1458e5c31af7Sopenharmony_ci } 1459e5c31af7Sopenharmony_ci 1460e5c31af7Sopenharmony_ci while (!liveSet.empty()) 1461e5c31af7Sopenharmony_ci { 1462e5c31af7Sopenharmony_ci Node* const curNode = liveSet.back(); 1463e5c31af7Sopenharmony_ci liveSet.pop_back(); 1464e5c31af7Sopenharmony_ci 1465e5c31af7Sopenharmony_ci sortedNodes.push_back(curNode); 1466e5c31af7Sopenharmony_ci 1467e5c31af7Sopenharmony_ci ... 1468e5c31af7Sopenharmony_ci } 1469e5c31af7Sopenharmony_ci 1470e5c31af7Sopenharmony_ci return sortedNodes; 1471e5c31af7Sopenharmony_ci} 1472e5c31af7Sopenharmony_ci</pre> 1473e5c31af7Sopenharmony_ci </li> 1474e5c31af7Sopenharmony_ci 1475e5c31af7Sopenharmony_ci <li><span class="heading">Pure functions</span> 1476e5c31af7Sopenharmony_ci <p>Pure functions have two properties. Firstly, the result depends only on the input values and 1477e5c31af7Sopenharmony_ci always produces same output value given same set of input values. Secondly, the function does not 1478e5c31af7Sopenharmony_ci cause any observable side effects or changes to global state. For example <i>sin(x)</i> is pure 1479e5c31af7Sopenharmony_ci function as it always returns the same value for same argument value and does not cause any side effects.</p> 1480e5c31af7Sopenharmony_ci 1481e5c31af7Sopenharmony_ci <p>As much of the code as possible should be kept pure. Moving pure parts of logic and computation 1482e5c31af7Sopenharmony_ci into separate functions is recommended. Unit testing those pure functions is then much easier.</p> 1483e5c31af7Sopenharmony_ci 1484e5c31af7Sopenharmony_ci <p>Mutating objects passed in counts as a side effect. Instead pure functions must return a completely 1485e5c31af7Sopenharmony_ci new value. This may not always be feasible and some functions may need to be impure for performance 1486e5c31af7Sopenharmony_ci reasons. One way to work around that while remaining as pure as possible is to use separate output-only 1487e5c31af7Sopenharmony_ci argument for output value. Perhaps the most ubiquitous example of such function is <i>memcpy()</i>.</p> 1488e5c31af7Sopenharmony_ci 1489e5c31af7Sopenharmony_ci <div class="codeTitle">Examples</div> 1490e5c31af7Sopenharmony_ci<pre class="prettyprint"> 1491e5c31af7Sopenharmony_ci// Good: pure function (assuming that it doesn't touch global state) 1492e5c31af7Sopenharmony_civector<int> findUniqueNumbers (const vector<int>& numbers); 1493e5c31af7Sopenharmony_ci 1494e5c31af7Sopenharmony_ci// Good: single output-only parameter 1495e5c31af7Sopenharmony_civoid findUniqueNumbers (vector<int>& dst, const vector<int>& numbers); 1496e5c31af7Sopenharmony_ci 1497e5c31af7Sopenharmony_ci// Bad: copying a lot of data for sake of pureness 1498e5c31af7Sopenharmony_ciLargeStateObject setStateX (const LargeStateObject& state, const int value); 1499e5c31af7Sopenharmony_ci 1500e5c31af7Sopenharmony_ci// Bad: manipulates input for no reason 1501e5c31af7Sopenharmony_civoid removeDuplicates (vector<string>& words); 1502e5c31af7Sopenharmony_ci 1503e5c31af7Sopenharmony_ci</pre> 1504e5c31af7Sopenharmony_ci </li> 1505e5c31af7Sopenharmony_ci </ol> 1506e5c31af7Sopenharmony_ci 1507e5c31af7Sopenharmony_ci<!-- 1508e5c31af7Sopenharmony_ciCoding philosophy TODO: 1509e5c31af7Sopenharmony_ci - composition vs. inheritance 1510e5c31af7Sopenharmony_ci - dependency injection 1511e5c31af7Sopenharmony_ci - function design 1512e5c31af7Sopenharmony_ci - do not duplicate state (local or remote) 1513e5c31af7Sopenharmony_ci 1514e5c31af7Sopenharmony_ciPatterns TODO: 1515e5c31af7Sopenharmony_ci - iterator pattern 1516e5c31af7Sopenharmony_ci - iterate() pattern for long computation 1517e5c31af7Sopenharmony_ci + state machines for interactive processing? 1518e5c31af7Sopenharmony_ci - accessor class pattern 1519e5c31af7Sopenharmony_ci--> 1520e5c31af7Sopenharmony_ci 1521e5c31af7Sopenharmony_ci </li> 1522e5c31af7Sopenharmony_ci 1523e5c31af7Sopenharmony_ci<!--- 1524e5c31af7Sopenharmony_ci <li><span class="heading">Something else</span> 1525e5c31af7Sopenharmony_ci </li> 1526e5c31af7Sopenharmony_ci--> 1527e5c31af7Sopenharmony_ci 1528e5c31af7Sopenharmony_ci</ol> <!-- h1 --> 1529e5c31af7Sopenharmony_ci 1530e5c31af7Sopenharmony_ci</div> <!-- body --> 1531e5c31af7Sopenharmony_ci 1532e5c31af7Sopenharmony_ci</body> 1533e5c31af7Sopenharmony_ci 1534e5c31af7Sopenharmony_ci</html> 1535