mbed SDK での C++ コーディングルール

にコーディングルールが書かれていた。

今まで C++ でちゃんとしたコーディングルール上で開発をしたことがなかったので読んでみた。

ルール

  • The mbed SDK code follows K&R style (Reference: K&R style) with at least 2 exceptions which can be found in the list below the code snippet:
static const PinMap PinMap_ADC[] = {
    {PTC2, ADC0_SE4b, 0},
    {NC , NC , 0}
};

uint32_t adc_function(analogin_t *obj, uint32_t options)
{
    uint32_t instance = obj->adc >> ADC_INSTANCE_SHIFT;
    switch (options) {
        case 1:
            timeout = 6;
            break;
        default:
            timeout = 10;
            break;
    }

    while (!adc_hal_is_conversion_completed(instance, 0)) {
        if (timeout == 0) {
            break;
        } else {
            timeout--;
        }
    }

    if (obj->adc == ADC_CHANNEL0) {
        adc_measure_channel(instance);
        adc_stop_channel(instance);
    } else {
        error("channel not available");
    }

#if DEBUG
    for (uint32_t i = 0; i < 10; i++) {
        printf("Loop : %d", i);
    }
#endif
    return adc_hal_get_conversion_value(instance, 0);
}
  • Indentation - 4 spaces. Please do not use tabs!
    • インデントは4スペース。タブは使わないで!
  • Braces - K&R, except for functions where the opening brace is on the new line.
    • {} は K&R。ただし新しい行出だしに { がある関数は除く。(意図がわからなかった…)
  • 1 TBS - use braces for statements if, else, while, for (exception from K&R) Reference: 1TBS).
    • if, else, while, for 式の場合、一行に {} を書く。 (K&Rからの例外)
  • One line per statement.
    • 式は一行に一つ
  • Preprocessor macro starts at the beginning of a new line, the code inside is indented accordingly the code above it.
    • プリプロセッサーのマクロは新しい行のはじめから書く。コードの内部にある時はインデントにあわせて書く。
  • Cases within switch are indented (exception from K&R).
    • switch 内側の case 文はインデントする。 (K&Rからの例外)
  • Space after statements if, while, for, switch, same applies to binary and ternary operators.
  • Each line has preferably at most 120 characters.
    • できれば1行は120文字以内におさめる。
  • For pointers, * is adjacent to a name (analogin_t *obj).
  • Don't leave trailing spaces at the end of lines.
    • 行の最後のスペースの削除を忘れずに
  • Empty lines should have no trailing spaces.
    • 空行にスペースを入れるべきでない
  • Unix line endings are default option for files.
    • ファイル標準の改行コードは Unix (\n) で
  • Use capital letters for macros.
    • マクロは大文字で
  • A file should have an empty line at the end. and:
    • ファイルの最後は空白行で終わるべき。(and: ←これなんだろう)
  • We are not using C++11 yet so do not write code compliant to this standard.
    • まだ C++11 を使えないので、C++11準拠のコードを書かないで。
    • (Kail と GCC_ARM は対応してるけど、IAR が対応してないからかな…)
  • We are not using libraries like BOOST so please so not include any BOOST headers to your code.
    • BOOSTのようなライブラリを使わない、BOOST のヘッダを含めないで
  • C++ & templates: please take under consideration templates are not fully supported by cross-compilers. You may have difficulties compiling template code few cross-compilers so make sure your template code compilers for more than one compiler.
    • 複数のコンパイラでサポートされるかどうかを考慮の上、テンプレートを使って。複数のクロスコンパイラで確認すれば良いよ。
    • (これは mbed が Kail, IAR, GCC_ARM のコンパイラをサポートしてるから)

命名規則

Classes: クラス名

  • Begins with a capital letter, and each word in it begins also with a capital letter (AnalogIn, BusInOut).
    • 大文字で始まり、また単語頭も大文字に (AnalogIn, BusInOut)
  • Methods contain small letters, distinct words separated by underscore.
    • メソッドは小文字で、異なる単語は _ で区切る
  • Private members starts with an underscore.
    • プライベートなメンバ変数は _ で始める。

User defined types (typedef):

  • Structures - suffix _t - to denote it is user defined type
    • 構造体は _t を末尾につける
  • Enumeration - the type name and values name - same naming convention as classes (e.g MyNewEnum)
    • Enum はタイプと値の名前で、クラスメイト同じ規則

Functions: 関数

  • Contain lower case letters (as methods within classes)
    • 小文字で(クラス内のメソッドっぽく)
  • Distinct words separated by underscore (wait_ms, read_u16)
    • 異なる単語は _ で区切る (wait_ms, read_u16)
  • Please make sure that in your module all functions have unique prefix so when your module is compiled with other modules function names (and e.g. extern global variable names) are not in naming conflict.
    • 他のモジュールから参照される(例えば extern でグローバル変数名をつけた)とき、あなたのモジュール名の関数にユニークな接頭語をつけてください。コンフリクトしないように。

サンプルコード

#define ADC_INSTANCE_SHIFT 8

class AnalogIn {
public:
    /** Create an AnalogIn, connected to the specified pin
    *
    * @param pin AnalogIn pin to connect to
    * @param name (optional) A string to identify the object
    */
    AnalogIn(PinName pin) {
        analogin_init(&_adc, pin);
    }

    /** Read the input voltage, represented as a float in the range [0.0, 1.0]
    *
    * @returns
    * A floating-point value representing the current input voltage, measured as a percentage
    */
    uint32_t read() {
        return analogin_read(&_adc, operation);
    }

protected:
    analogin_t _adc;
};

typedef enum {
    ADC0_SE0 = (0 << ADC_INSTANCE_SHIFT) | 0,
} ADCName;

struct analogin_s {
    ADCName adc;
};

typedef struct analogin_s analogin_t;