このドキュメントは Mozilla コードベースで使われる基本スタイルとパターンを説明するためのものです。 新しいコードはこれらの標準に沿うよう試みるべきです。それは、既存のコード同様にメンテナンスが楽になるためです。 もちろん、どのルールにも例外はあります。しかし、にもかかわらずルールを知ることは重要なのです!
これは、新しく Mozilla コードベースへ向かっている、コードをレビューされるプロセスにある人へ特化して向けられています。 レビューを受ける前に、このドキュメントを読み通して、あなたのコードがここで推奨されている内容に沿っていることを確認してください。
命名とコードのフォーマット
The following norms should be followed for new code, and for Tower of Babel code that needs cleanup. For existing code, use the prevailing style in a file or module, or ask the owner if you are on someone else's turf and it's not clear what style to use.
ホワイトスペース
タブを入れてはいけません。行末にホワイトスペースを入れないでください。
Unix-style linebreaks ('\n'), not Windows-style ('\r\n').
行の長さ
80文字以下 (for laptop side-by-side diffing and two-window tiling; also for Bonsai / hgweb and hardcopy printing).
インデント
ロジックレベルではスペース 2 つ分、Python コードではスペース 4 つ分。
クラスのアクセス修飾子と goto ラベルはロジックレベルには含みませんが、switch case ラベルはロジックレベルに含むことに注意してください。参考例を確認してください。
コントロール構造
Use K&R bracing style: left brace at end of first line, cuddle else on both sides.
Always brace controlled statements, even a single-line consequent of an if else else
. This is redundant typically, but it avoids dangling else bugs, so it's safer at scale than fine-tuning.
Break long conditions after &&
and ||
logical connectives. See below for the rule for other operators.
Examples:
if (...) { } else if (...) { } else { } while (...) { } do { } while (...); for (...; ...; ...) { } switch (...) { case 1: { // When you need to declare a variable in a switch, put the block in braces int var; break; } case 2: ... break; default: break; }
You can achieve the following switch
statement indentation in emacs by setting the "case-label" offset:
(c-set-offset 'case-label '+)
Control keywords if
, for
, while
, and switch
are always followed by a space to distinguish them from function calls which have no trailing space.
C++ namespaces
Mozilla project C++ declarations should be in the "mozilla" namespace. Modules should avoid adding nested namespaces under "mozilla" unless they are meant to contain names which have a high probability of colliding with other names in the code base (e.g., Point
, Path
, etc.). Such symbols can be put under module-specific namespaces under "mozilla", with short all-lowercase names. Other global namespaces besides "mozilla" are not allowed.
No "using" statements are allowed in header files, except inside class definitions or functions. (We don't want to pollute the global scope of compilation units that use the header file.)
using namespace ...;
is only allowed in .cpp
files after all #include
s. Prefer to wrap code in namespace ... { ... };
instead if possible. using namespace ...;
should always specify the fully qualified namespace. That is, to use Foo::Bar
do not write using namespace Foo;
using namespace Bar;
, write using namespace Foo::Bar;
Don't indent code inside namespace ... { ... }
. You can prevent this inside emacs by setting the "innamespace" offset:
(c-set-offset 'innamespace 0)
Anonymous namespaces
We prefer using "static" instead of anonymous C++ namespaces. This may change once there is better debugger support (on Windows especially) for placing breakpoints, etc on code in anonymous namespaces. You may still use anonymous namespaces for things that can't be hidden with 'static' (such as types, or certain objects that need to be passed to template functions).
C++ classes
namespace mozilla { class MyClass : public A { ... }; class MyClass : public X // When deriving from more than one class, put each on its own line. , public Y { public: MyClass(int aVar, int aVar2) : mVar(aVar) , mVar2(aVar2) { ... } // Tiny constructors and destructors can be written on a single line. MyClass() { } // Unless it's a copy or move constructor or you have a specific reason to allow // implicit conversions, mark all single-argument constructors explicit. explicit MyClass(OtherClass aArg) { ... } // This constructor can also take a single argument, so it also needs to be marked // explicit. explicit MyClass(OtherClass aArg, AnotherClass aArg2 = AnotherClass()) { ... } int TinyFunction() { return mVar; } // Tiny functions can be written in a single line. int LargerFunction() { ... ... } private: int mVar; }; } // namespace mozilla
Define classes using the style given above.
Existing classes in the global namespace are named with a short prefix (e.g. "ns") as a pseudo-namespace.
For small functions, constructors, or other braced constructs, it's okay to collapse the definition to one line as shown for TinyFunction
above. For larger ones use something similar to method declarations below.
Methods and functions
C/C++
In C/C++, method names should be capitalized and use CamelCase.
template // Templates on own line. static int // Return type on own line for top-level functions. MyFunction(...) { ... } int MyClass::Method(...) { ... }
Getters that never fail and never return null are named Foo()
, while all other getters use GetFoo()
. Getters can return an object value via a Foo** aResult
outparam (typical for an XPCOM getter) or as an already_AddRefed
(typical for a WebIDL getter, possibly with an ErrorResult& rv
parameter) or occasionally as a Foo*
(typical for an internal getter for an object with a known lifetime). See バグ 223255 for more information.
XPCOM getters always return primitive values via an outparam while other getters normally use a return value.
Method declarations must use at most one of the following keywords: virtual
, override
, or final
. Use virtual
to declare virtual methods which do not override a base class method with the same signature. Use override
to declare virtual methods which do override a base class method with the same signature, but can be further overridden in derived classes. Use final
to declare virtual methods which do override a base class method with the same signature, but cannot be further overridden in the derived classes. This should help the person reading the code understand what the declaration is exactly doing, without needing to examine base classes.
JavaScript
JavaScriptでは、関数は camelCase を使用する必要がありますが頭文字を大文字にしないようにしてください。メゾットは指定された関数式の構文を使わないでください。なぜなら私たちのツールはメゾット名として理解するためです。
doSomething: function (aFoo, aBar) { ... }
In-line functions should have spaces around braces, except before commas or semicolons:
function valueObject(aValue) { return { value: aValue }; }
JavaScript objects
var foo = { prop1: "value1" }; var bar = { prop1: "value1", prop2: "value2" };
Constructors for objects should be capitalized and use CamelCase:
function ObjectConstructor() { this.foo = "bar"; }
モードライン
indent-tabs-mode に nil を指定した Emacs と vim モードラインのコメントをファイルの最初の2行に追加すべきです。新規ファイルの場合、このモードラインを使用してインデントを 2 スペースに指定してください。
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
最初の行の "Mode" には正しく値を設定してください。 JavaScript ファイルに "C++" を使わないください。Python コードの場合、インデントに 4 スペースを使用しないと例外が発生します。
宣言
一般的に、ポインター演算子は変数名ではなく型の横に付けます。
T* p
; // GOOD
T *p; // BAD
T* p, q; // OOPS put these on separate lines
まだいくつかのモジュールでは T *p
のスタイルで書かれているものもあります。
Operators
Overlong expressions not joined by &&
and ||
should break so the operator starts on the second line and starts in the same column as the start of the expression in the first line. This applies to ?:
, binary arithmetic operators including +
, and member-of operators (in particular the .
operator in JavaScript, see the Rationale).
Rationale: operator at the front of the continuation line makes for faster visual scanning, because there is no need to read to end of line. Also there exists a context-sensitive keyword hazard in JavaScript; see バグ 442099, comment 19, which can be avoided by putting . at the start of a continuation line in long member expression.
In JavaScript, ==
is preferred to ===
.
Unary keyword operators, such as typeof
and sizeof
, should have their operand parenthesized; e.g. typeof("foo") == "string"
.
Literals
Double-quoted strings (e.g. "foo"
) are preferred to single-quoted strings (e.g. 'foo'
) in JavaScript, except to avoid escaping of embedded double quotes or when assigning inline event handlers.
Use \uXXXX
unicode escapes for non-ASCII characters. The character set for XUL, DTD, script, and properties files is UTF-8, which is not easily readable.
Prefixes
Follow these naming prefix conventions:
Variable prefixes
- k=constant (e.g.
kNC_child
). Not all code uses this style; some usesALL_CAPS
for constants. - g=global (e.g.
gPrefService
) - a=argument (e.g.
aCount
) - C++ Specific Prefixes
- s=static member (e.g.
sPrefChecked
) - m=member (e.g.
mLength
) - e=enum values (e.g.
enum class Foo { eBar, eBaz }
)
- s=static member (e.g.
- JavaScript Specific Prefixes
- _=member (variable or function) (e.g.
_length
or_setType(aType)
) - k=enumeration value (e.g.
const kDisplayModeNormal = 0
) - on=event handler (e.g.
function onLoad()
) - Convenience constants for interface names should be prefixed with
nsI
:const nsISupports = Components.interfaces.nsISupports; const nsIWBN = Components.interfaces.nsIWebBrowserNavigation;
- _=member (variable or function) (e.g.
Global functions/macros/etc
- Macros begin with
MOZ_
, and are all caps (e.g.MOZ_WOW_GOODNESS
). Note that older code uses theNS_
prefix; while these aren't being changed, you should only useMOZ_
for new macros. The only exception is if you're creating a new macro which is part of a set of related macros that still use the oldNS_
prefix. Then you should be consistent with the existing macros.
Error Variables
- local nsresult result codes should be `rv`. `rv` should not be used for bool or other result types.
- local bool result codes should be `ok`
General practices
- Don't put an
else
right after areturn
. Delete theelse
, it's unnecessary and increases indentation level. - Don't leave debug
printf
s ordump
s lying around. - Use Unix-style carriage returns ("
\n
") rather than Windows/DOS ones ("\r\n
"). You can convert patches with DOS newlines to Unix via the 'dos2unix' utility, or your favorite text editor. - Use two spaces for indentation.
- Use JavaDoc-style comments.
- When fixing a problem, check to see if the problem occurs elsewhere in the same file, and fix it everywhere if possible.
- End the file with a newline (make sure your patches don't contain files with the text "no newline at end of file" in them).
- Declare local variables as near to their use as possible.
- For new files, be sure to use the right license boilerplate per our license policy.
一般的 C/C++ 慣習
- Have you checked for compiler warnings? Warnings often point to real bugs.
- C++ コードでは、nullptr ポインタを利用してください。 C コードでは NULL または
0
が許可されています。 - Don't use
PRBool
andPRPackedBool
in C++, usebool
instead. - ポインタをテストする際、
(
!myPtr
)
または(myPtr)
を使ってください。myPtr !=
nullptr
やmyPtr ==
nullptr
は利用すべきではありません。 - Do not compare
x == true
orx == false
. Use(x)
or(!x)
instead.x == true
, in fact, is different from if(x)
! - In general, initialize variables with
nsFoo aFoo = bFoo
and not nsFoo aFoo(bFoo). - To avoid warnings created by variables used only in debug builds, use the
DebugOnly
helper when declaring them. - You should use the static preference API for working with preferences.
- One-argument constructors that are not copy or move constructors should generally be marked explicit. Exceptions should be annotated with MOZ_IMPLICIT.
- Forward-declare classes in your header files instead of including them whenever possible. For example, if you have an interface with a
void DoSomething(nsIContent* aContent)
function, forward-declare withclass nsIContent;
instead of#include "nsIContent.h"
- Include は 3 つのブロックに分け、各ブロックはアルファベット順にソートしてください。
- メインヘッダー: Foo.cpp の Foo.h
- 標準ライブラリのインクルード:
#include
- Mozilla インクルード:
#include "mozilla/dom/Element.h"
-
Include guards are named by determining the fully-qualified include path, then substituting
_
for/
and.
and-
in it. For example, nsINode.h's guard is nsINode_h, and Element.h's guard is mozilla_dom_Element_h (because its include path is mozilla/dom/Element.h).Use the following exact form for include guards. GCC and clang recognize this idiom and avoid re-reading headers that use it. To avoid confusing GCC's and clang's header optimization, do not include any code before or after the include guards (but comments and whitespace are OK). Do not combine any other preprocessor checks in the #ifndef expression.
#ifndef #define ... All code ... #endif //
JavaScript practices
- Make sure you are aware of the JavaScript Tips.
- Do not compare
x == true
orx == false
. Use(x)
or(!x)
instead.x == true
, in fact, is different from if(x)
! Compare objects tonull
, numbers to0
or strings to""
if there is chance for confusion. - Make sure that your code doesn't generate any strict JavaScript warnings, such as:
- Duplicate variable declaration
- Mixing
return;
withreturn value;
- Undeclared variables or members. If you are unsure if an array value exists, compare the index to the array's length. If you are unsure if an object member exists, use
"name" in aObject
, or if you are expecting a particular type you may usetypeof(aObject.name) == "function"
(or whichever type you are expecting).
- Use
[value1, value2]
to create a JavaScript array in preference to usingnew Array(value1, value2)
which can be confusing, asnew Array(length)
will actually create a physically empty array with the given logical length, while[value]
will always create a 1-element array. You cannot actually guarantee to be able to preallocate memory for an array. - Use
{ member: value, ... }
to create a JavaScript object; a useful advantage overnew Object()
is the ability to create initial properties and use extended JavaScript syntax to define getters and setters. - If having defined a constructor you need to assign default properties it is preferred to assign an object literal to the prototype property.
- Use regular expressions, but use them wisely. For instance, to check that
aString
is not completely whitespace use/\S/.test(aString);
only useaString.search
if you need to know the position of the result, oraString.match
if you need to collect matching substrings (delimited by parentheses in the regular expression). Regular expressions are less useful if the match is unknown in advance, or to extract substrings in known positions in the string. For instance,aString.slice(-1)
returns the last letter inaString
, or the empty string ifaString
is empty.
Java practices
- We use the Java Coding Style. Quick summary:
- FirstLetterUpperCase for class names
- camelCase for method and variable names
- One declaration per line:
int x, y; // this is BAD! int a; // split it over int b; // two lines
- Braces should be placed like so (generally opening braces on same line, closing braces on a new line):
public void func(int arg) { if (arg != 0) { while (arg > 0) { arg--; } } else { arg++; } }
- Places we differ from the Java coding style:
- Start class variable names with 'm' prefix (e.g. mSomeClassVariable) and static variables with 's' prefix (e.g. sSomeStaticVariable)
- import statements:
- Do not use wildcard imports like `import java.util.*;`
- Organize imports by blocks separated by empty line: org.mozilla.*, com.*, net.*, org.*, android.*, then java.*
- Within each import block, alphabetize import names with uppercase before lowercase (so `com.example.Foo` is before `com.example.bar`).
- 4-space indents
- spaces, not tabs
- Don't restrict yourself to 80-character lines. Google's Android style guide suggests 100-character lines. Java code tends to be long horizontally, so use appropriate judgement when wrapping. Avoid deep indents on wrapping. Note that aligning the wrapped part of a line with some previous part of the line (rather than just using a fixed indent) may require shifting the code every time the line changes, resulting in spurious whitespace changes.
- For additional specifics on Firefox for Android, see the Coding Style guide for Firefox on Android.
- The Android Coding Style has some useful guidelines too.
Makefile/moz.build practices
- Changes to makefile and moz.build variables do not require build-config peer review. Any other build system changes such as adding new scripts or rules require review from the build-config team.
- Suffix long
if
/endif
conditionals with #{ & #} so editors can display matching tokens that enclose a block of statements.ifdef CHECK_TYPE #{ ifneq ($(flavor var_type),recursive) #{ $(warning var should be expandable but detected var_type=$(flavor var_type)) endif #} endif #}
- moz.build are python and follow normal Python style
- List assignments should be written with one element per line. Align closing square brace with start of variable assignment. If ordering is not important, variables should be in alphabetical order.
var += [ 'foo', 'bar' ]
- Use CONFIG['CPU_ARCH'] {=arm} to test for generic classes of architecure rather than CONFIG['OS_TEST'] {=armv7} (re: bug 886689)
Python practices
- Install the mozext Mercurial extension and address every issue reported on commit, qrefresh, or the output of
hg critic
. - Follow PEP 8.
- Do not place statements on the same line as
if/elif/else
conditionals to form a one-liner. - Global vars, avoid them at all cost.
- Exclude outer parenthesis from conditionals. Use
if x > 5:
rather thanif (x > 5):
- Use string formatters rather than var + str(val).
var = 'Type %s value is %d' % ('int', 5)
- Utilize tools like
pylint
orpychecker
to screen sources for common problems. - Testing/Unit tests, write them.
- See also Code Like a Pythonista.
SVG practices
Check SVG Guidelines for more details.
COM とポインタと文字列
nsCOMPtr<>
を使ってください
もし、使い方が分からなければ、コードの例を読み始めてください。 NS_RELEASE をタイプすることが、コーディングに際して"ここで私は nsCOMPtr を使うべきだろうか?"と自問をうながす形のシグナルになるという、一般的なルールがあります。 一般的に、 NS_RELEASE の有効な使い方は、あなたが生存期間の長いデータ構造のなかに参照をカウントされたポインタを貯えているときだけです。- Declare new XPCOM interfaces using XPIDL so they will be scriptable.
- Use nsCOMPtr for strong references, and nsWeakPtr for weak references.
- String arguments to functions should be declared as
nsAString
. - Use
EmptyString()
andEmptyCString()
instead ofNS_LITERAL_STRING("")
ornsAutoString empty
;. - Use
str.IsEmpty()
instead ofstr.Length() == 0
. - Use
str.Truncate()
instead ofstr.SetLength(0)
orstr.Assign(EmptyString())
. - Don't use
QueryInterface
directly. UseCallQueryInterface
ordo_QueryInterface
instead. nsresult
should be declared asrv
. Not res, not result, not foo.- For constant strings, use
NS_LITERAL_STRING("...")
instead ofNS_ConvertASCIItoUCS2("...")
,AssignWithConversion("...")
,EqualsWithConversion("...")
, ornsAutoString()
- To compare a string with a literal, use .EqualsLiteral("...").
- Use Contract IDs instead of CIDs with do_CreateInstance/do_GetService.
- Use pointers instead of references for function out parameters, even for primitive types.
IDL
"interCaps"、つまり小文字で始めるルールを使ってください
メソッドや IDL 属性を定義するとき、最初の文字は小文字であるべきです。そして、続くいずれの単語も大文字で始まるべきです。例えば、
long updateStatusBar();
可能なところでは attribute (属性) を使ってください
特に理由もなく単独の値を参照したりセットしたりするときは、attribute (属性) を使ってください。 一つの属性を使うだろうときには二つのメソッドを使わないで下さい。 属性を使うことは、必然的に値の参照や代入につながり、スクリプトされたコードを明確にします。
この例はメソッドが多すぎます:
interface nsIFoo : nsISupports { long getLength(); void setLength(in long length); long getColor(); };
以下のコードはまったく同じ C++ シグネチャを生成するでしょう。しかし、よりスクリプトフレンドリです。
interface nsIFoo : nsISupports { attribute long length; readonly attribute long color; };
Java スタイルの定数を使う
スクリプト可能な定数を IDL の中で定義するとき、名前はすべて大文字にし、単語の間はアンダースコア (_) でつなぐべきです。
const long ERROR_UNDEFINED_VARIABLE = 1;
See also
For details on interface development, as well as more detailed style guides, see the Interface development guide.
エラーのハンドリング
エラーのチェックは早めに、頻繁に
XPCOM 関数への呼び出しをするときはいつでも、エラー状態のチェックをすべきです。 たとえ関数呼び出しが絶対に失敗しないとわかっていても、それをすべきです。なぜ?
- だれかが将来、呼ばれる先を失敗状態を返すように変更するかもしれません。
- 問い合わせのオブジェクトは別のスレッド上や他のプロセス上、ことによると他のマシンに存在するかも知れません。 プロキシはあなたの呼び出しを最初の場所で実際におこなうのに失敗するかも知れません。
予期しないエラーが発生する場合は NS_WARN_IF マクロを使ってください。
NS_WARN_IF マクロは条件文が失敗したときにデバッグの時にワーニングをコンソールに出力することができます。これは、予期しない失敗の時だけに利用でき、通常の Web コンテンツ等に起因するようなものには使えません。
もしメソッドが失敗したときに警告を発行するコードを書きたい場合、NS_WARNING を直接使うか、 NS_WARN_IF マクロのどちらかを使ってください。
if (NS_WARN_IF(somethingthatshouldbetrue)) { return NS_ERROR_INVALID_ARG; } if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
同じ目的で以前まで使われていた NS_ENSURE_* マクロは、リターン文を隠してしまい、新しいコードでは使うべきではありません。(このコーディングスタイルルールは一般的に合意されたものではないため、NS_ENSURE_* の利用も有効です。)
エラーからはすぐにリターンしてください
たいていの場合、あなたの条件反射行動はエラー状態が発生したときに現在の関数からリターンするというのであるべきです。 このようにはしないでください。
rv = foo->Call1(); if (NS_SUCCEEDED(rv)) { rv = foo->Call2(); if (NS_SUCCEEDED(rv)) { rv = foo->Call3(); } } return rv;
かわりに、このようにしてください。
rv = foo->Call1(); if (NS_FAILED(rv)) { return rv; } rv = foo->Call2(); if (NS_FAILED(rv)) { return rv; } rv = foo->Call3(); if (NS_FAILED(rv)) { return rv; }
なぜ? エラーのハンドリングでコードのロジックを混乱させないためです。 最初の例での書き手の意図は、続けざまに3つの呼び出しをすることでした。しかし、 if() 構文をネストして呼び出しをラップすることは、たいていコードの振る舞いをわかりにくくします。
実際にバグの潜んでいるもっと複雑な例を考えてください。
bool val; rv = foo->GetBooleanValue(&val); if (NS_SUCCEEDED(rv) && val) { foo->Call1(); } else { foo->Call2(); }
書き手の意図は val が false の値を取るときにだけ foo->Call2() がよばれるということでしょう。 実は、foo->Call2() は foo->GetBooleanValue(&val) が失敗したときにも呼び出されます。 これが書き手の意図かもしれませんし、そうでないかもしれませんが、このコードからははっきりわかりません。 修正版を示します。
bool val;
rv = foo->GetBooleanValue(&val);
if (NS_FAILED(rv)) {
return rv;
}
if (val) {
foo->Call1();
} else {
foo->Call2();
}
この例では、書き手の意図ははっきりしています。そして、エラー状態では foo->Call1() も foo->Call2() も呼ばれません。
例外 (エクセプション) の可能性:ときおり、呼び出しの失敗は致命的ではありません。 たとえば、もしあなたがイベントが引き起こされたことを一連のオブザーバーに通知しているなら、その通知の一つが失敗していることは重要でないでしょう。
for (size_t i = 0; i < length; ++i) { // we don't care if any individual observer fails observers[i]->Observe(foo, bar, baz); }
他の可能性は、あなたがコンポーネントが存在しているか、もしくはインストールされているかを知らないで、そのコンポーネントがもしなくても、通常通り続けたい場合です。
nsCOMPtr service = do_CreateInstance(NS_MYSERVICE_CID, &rv); // if the service is installed, then we'll use it if (NS_SUCCEEDED(rv)) { // non-fatal if this fails too, ignore this error service->DoSomething(); // this is important, handle this error! rv = service->DoSomethingImportant(); if (NS_FAILED(rv)) { return rv; } } // continue normally whether or not the service exists
C++ strings
ローカル変数として使う文字列の型には Auto
を使ってください
ローカルで、生存期間の短い nsString クラスを宣言するときは、いつでも nsAutoString か nsCAutoString を使ってください。 これらのバージョンは事前に 64 バイトのバッファをスタックにアロケートし、ヒープのフラグメント化を防ぎます。 このようにしないで下さい。
nsresult foo() { nsCString bar; .. }
かわりに
nsresult foo() { nsAutoCString bar; .. }
char* や PRUnichar* を返す XPCOM でない関数からの値のリークを警戒してください
それは、内部ヘルパー関数からのアロケートされた文字列を返すという簡単なトラップで、値を解放することなく、あなたのコードの中でインラインにその関数を使います。 このコードを考えてみてください。
static char* GetStringValue() { .. return resultString.ToNewCString(); } .. WarnUser(GetStringValue());
上の例では、WarnUser は resultString からアロケートされた文字列を得るでしょう。 ToNewCString() し、ポインタを投げます。 結果の値が、解放されることはありません。 そのかわりに、スコープの外に出たときにあなたの文字列が自動的に解放されることを確証するために文字列クラスを使うか、あなたの文字列が解放されている ことを確証してください。
自動クリーンアップ
static void GetStringValue(nsAWritableCString& aResult) { .. aResult.Assign("resulting string"); } .. nsAutoCString warning; GetStringValue(warning); WarnUser(warning.get());
手動文字列解放
static char* GetStringValue() { .. return resultString.ToNewCString(); } .. char* warning = GetStringValue(); WarnUser(warning); nsMemory::Free(warning);
Use MOZ_UTF16() or NS_LITERAL_STRING() to avoid runtime string conversion
It is very common to need to assign the value of a literal string such as "Some String" into a unicode buffer. Instead of using nsString
's AssignLiteral
and AppendLiteral
, use NS_LITERAL_STRING()
instead. On most platforms, this will force the compiler to compile in a raw unicode string, and assign it directly.
Incorrect:
nsAutoString warning; warning.AssignLiteral("danger will robinson!"); ... foo->SetStringValue(warning); ... bar->SetUnicodeValue(warning.get());
Correct:
NS_NAMED_LITERAL_STRING(warning, "danger will robinson!"); ... // if you'll be using the 'warning' string, you can still use it as before: foo->SetStringValue(warning); ... bar->SetUnicodeValue(warning.get()); // alternatively, use the wide string directly: foo->SetStringValue(NS_LITERAL_STRING("danger will robinson!")); ... bar->SetUnicodeValue(MOZ_UTF16("danger will robinson!"));
Note: named literal strings cannot yet be static.
Usage of PR_(MAX|MIN|ABS|ROUNDUP) macro calls
Use the standard-library functions (std::max) instead of PR_(MAX|MIN|ABS|ROUNDUP).
Use mozilla::Abs instead of PR_ABS. All PR_ABS calls in C++ code have been replaced with mozilla::Abs calls in bug 847480. All new code in Firefox/core/toolkit needs to #include "nsAlgorithm.h"
and use the NS_foo variants instead of PR_foo, or #include "mozilla/MathAlgorithms.h"
for mozilla::Abs
.