General Coding Standards


The following standards should be applied to all source code and header files. In most cases, these standards improve readability; where noted, they may also affect performance.



Binary Operators

Use the following format for binary operators (arithmetic operators, logical operators, and so on). Include a single space on either side of the operator.

	b = a + b;
	myObj.getWidth() < 5
	xyz ^ abc


Unary Operators

Use the following format for unary operators (increment, decrement, bit-wise negation, bit-wise inverse, and so on).

	xyz += myVar;
	flags |= ~bitMask
	myCount++;
	++myCount;
if (!abc) { . . . }

Using Casts

When writing a cast, use const_cast<> and reinterpret_cast<> if your compiler supports them. The rules for reinterpret_cast<> are complicated, but it cannot be used in contexts where const_cast<> is appropriate and cannot be used indiscriminately. C++ guarantees very little about the semantics of reinterpret_cast<> except that when casting from one type to another type, and then casting back from the second type to the original, the correct value is preserved. Use of reinterpret_cast<> does not ensure portability, but it is much easier locating uses of reinterpret_cast<> in the code (for examination during porting efforts) than locating uses of C-style casts.

Do not use static_cast*<>. Instead, use the older styles:

Note: When the type cast is a pointer type, there is no space between the base type name and the * or &. However, a single space is used between the pointer type cast operator and its operand.

 . and -> Operators

Use the following format for an object dereference and a pointer dereference. Do not include a space on either side of the dereference operators.

	width = path.getWidth();
	bufLen += string->getLength();


Pointer and Reference Declarations

When declaring pointers and references, place the & and * symbols before the variable name, not after the type. This makes pointer and reference variable types more obvious and easier to recognize.

	// The following code declares a pointer to a string 
	// and a reference to a string, respectively.
	oaString	*oldCellName;                          // There must be at least one space between the type and the 
	const oaString	&cellName = cellView.getCellName();    // pointer or reference symbol. (Typically, four spaces or more.)

	// These are incorrect!
	oaString*	oldLibName;
	const oaString& libName = cellView.getLibName();
	
	// Inside conditional expressions, the spacing in the first example below is preferred, but the second example is allowed.
	while(oaInst *inst ...   // Preferable to have the symbol next to the variable name.
	while(oaInst * inst ...  // One space between the symbol and the variable name is also allowed.
	


Braces

Braces enclose blocks of code to control code execution and limit the scope of variables. Indent all statements inside of braces by one shift-width. (The only exception to this is switch statements.) Place the first statement on the line immediately after the opening brace; place the last statement on the line immediately before the closing brace.

	// This example shows the use of braces even when 
	// the body is quite simple.
	while (abc++ < 10) {
	    myFunct(abc);
	}

	// This block must use braces.
	if (abc < 10) {
	    myFunc(abc);
	    flag = TRUE;
	}

	// Be sure to use braces at every level of code block.
	if (abc < 10) {
	    while (abc < 4) {
	        numCount++;
	    }
	}

If the base class in a class definition is an instantiation of a template, there must be a single space between the closing angle-bracket and the opening brace. The following examples show first incorrect formatting and then the correct formatting.

// This example uses no space between the closing angle bracket
// of the template declaration and the opening brace.
class OA_BASE_DLL_API oaPointArray : public oaArray<oaPoint>{
public:
    oaPointArray(oaUInt4    sizeIn = 0);
    .
    .			
    .
};

// This example uses the correct space between the closing angle bracket
// of the template declaration and the opening brace.
class OA_BASE_DLL_API oaPointArray : public oaArray<oaPoint> {
public:
    oaPointArray(oaUInt4    sizeIn = 0);
    .
    .
    .
};

Position braces consistently. When using braces to enclose the code for a conditional statement (if, for, while, switch, and so on), place the opening brace at the end of the line containing the conditional statement. Place the closing brace for the if clause on the same line as the beginning of the else statement.

	// Putting the braces in the correct place makes it easier to
	// pick out the different clauses.
	if (abc < xyz) {
	    .
	    .
	    .
	} else {
	    .
	    .
	    .
	}

	for (oaUInt4 i = 0; i < 10; i++) {
	    .
	    .
	    .
	}

Do not put the opening braces on their own lines. The following examples show incorrect brace placements.

	// This is wrong because the opening brace is on a separate line and
	// because the following else statement is on a separate line from the 
	// closing brace for the if statement.
	if (abc < xyz)
	{
	    .
	    .
	}
	else {
	    .
	    .
	    .
	}

	// This is wrong because the closing brace is not on its own line and
	// is more difficult to see.
	for (oaUInt4 index = 0; index < maxIndex; index++) {
	    .
	    .
	    .
	    totNum += index;}


	// This is wrong because there no braces and the body of the
	// conditional statement is on the same line as the if.
	If (abc < 10) x = y;


If Statements

Use the following format for if statements. Include a single space between the if and else keywords and the left parenthesis, and a single space between the right parenthesis and the following open brace.

	if (abc < xyz) {
	    .
	    .
	} else if (abc < var) {
	    .
	    .
	} else {
	    .
	    .
	}

While Statements

The format for while statements is similar to if statements. Include a single space between the while keyword and the left parenthesis, and a single space between the right parenthesis and the following open brace.

	// This while statement only contains one line, but still uses braces.
	while (abc < 20) {
	    myFunc(abc++);
	}

	// This while statement uses braces and it encloses multiple lines.
	while (! myFunc(abc++)) {
	    numCount++;
	    flags |= myOtherFunc(xyz);
	}


Switch Statements

switch statements use a somewhat unique structure to avoid requiring too many indentations. Include a single space between the switch keyword and the left parenthesis, and a single space between the right parenthesis and the following open brace.

The case statements are aligned with switch. Optionally, separate the code for each case with one empty line if the case code blocks are long and would otherwise visually run together.

    // The 'case' statements are aligned with 'switch'. The case bodies are  
    // four spaces inside the case statements.
    switch (type) {
    case oacRectType:
        numRects++;
        break;

    case oacPolygonType:
        numPolgyons++;
        break;

    case oacPathType:
        numPaths++;
        break;

    default:
        throw oacInvalidObjectTypeError;
    }

switch statements often require braces around the contents of a particular case because variables are declared in the case and must have local scope within the case only. In this situation, use the indentation shown in the next example. Indent the braces past the case statement just as any other part of a case block of code. Then further indent the code within the braces, because there may be code that is part of the case that is not within the braces.

The braces should enclose the minimum amount of code to limit the scope of local variables within the case.

	switch (type) {
	.
	.
	.
	case oacPolygonType:
	    {
	        oaNet   net;

	        polygon.getNet(net);
	        .
	        .
	        .
	        numBits = net.getNumBits();
	    }

	    totNumBits += numBits;
	    break;
	.
	.
	.
	}


For Loops

Use the following format for a for loop. Include a single space between the for keyword and the left parenthesis, a single space between the right parenthesis and the following open brace, and a single space after each semicolon. Do not include a space before each semicolon or between the end-of-loop clause and the closing parenthesis.

If the loop variables are used only within the loop, declare the variable in the for loop.

	// This is a simple for loop.
	for (oaUInt4 i = 0; i < numBits; i++) {
	   . . .
	}

	// This for loop demonstrates the use of a double index 
	// including initialization.
	for (oaUInt4 i = 0, j = numPoints; i < numPoints; j = i++) {
	}

In some simple cases, a for loop does not have a body because all of the work is done in the for statement itself. In this case, still include the braces, even though they enclose a trivial body. Indent the terminating semicolon and place it on the following line to signify a trivial body for the loop.

	for (char *s = buf; *buf != '\0'; *s++ = *buf++) {
	    ;
	}

Note: Refer to the end of the Pointer and Reference Declarations section for information about formatting pointers inside conditional loops.



Do/While Loops

The format for a do/while loop is similar to a while loop. Include a single space between the right closing brace of the do statement and the while keyword, and include a single space between the while keyword and the left parenthesis.

	// This is a simple do/while loop.
	do {
	    .
	    .
	    .
	} while (index < maxIndex);


Function Calls

Use the following format for a function call. Do not include a space between the function name and the left parenthesis, between the left parenthesis and the first argument, or between the last argument and the right parenthesis.

	myFunc(arg1, arg2, arg3)


Semicolons to Terminate Statements

Do not include a space between a semicolon and the end of the statement it terminates.

	value = funcCal(arg1, arg2);
	x = y;

Always enter only one statement per line. Do not put multiple statements on the same line, even if they are extremely short.

	// Don't do this.
	x1 = 0; y1 = 1;
	x2 = 3; y2 = 7;


Multi-Line Statements

If it is not possible to fit an entire statement on one line, break the statement into multiple lines. None of the lines should exceed 80 characters. Break the statement at the most obvious point, such as at a space, rather than at a spot where there is not already a space. For example:

	// It is easier to read this code when the continuation line is at 
	// a natural break in the statement.
        myObjName->getMyMethodName() = myObjName->getMyOtherMethodName()
                                                 + index;

	// It is more difficult to read this statement because of 
	// the strange break location.
        myObjName->getMyMethodName() = myObjName
                                              ->getMyOtherMethodName() + index;

When breaking up a line around an operator, always place the operator at the beginning of the next line rather than leaving it at the end of the previous line.

	// Putting the '+' at the beginning of the next line makes it more 
	// obvious that the second line is a continuation of the first.
        myObjName->getMyMethodName() = myObjName->getMyOtherMethodName()
                                                 + index;

	// It is not so obvious here that the second line is a continuation or
	// a strange indentation.
	myObjName->getMyMethodName() = myObjName->getMyOtherMethodName() + 
                                            index;

When you must break a line within a portion of a statement that is enclosed in parenthesis, indent the continuing lines to align with the opening parenthesis.

	// Aligning the arguments to this function makes it clear 
	// what the code is doing.
	numThings = myFunc(a, b, c) + myOtherFunc(arg1,
                                                  myarg2,
                                                  myClass->getInfo());

	// This is OK too, and takes fewer lines.
	numThings = myFunc(a, b, c) + myOtherFunc(arg1, myarg2, myarg3, myarg4
                                                  myClass->getInfo(), myarg5);

	// Use the same alignment for conditional statements 
	// such as this if statement.
	if (path.getWidth() > 25 && path.getPathStyle() == oacPathStyleTruncate
	    && path.getNumPoints() > 150) {
	    .
	    .
	    .
	}

	// It is more difficult to read this statement when it is unaligned.
	numThings = myFunc(a, b, c) + myOtherFunc(arg1,
                                  myarg2,
                        myClass->getInfo());


Parentheses

Use parentheses to force associations in logical and arithmetic statements. In general, do not use parentheses when the standard rules of precedence are sufficient and the statement is clear without them.

	// The parentheses here are necessary to force the 
	// summation before the multiplication.
	y = (a + b) * (c + d);
	xyz = (*myObj)->myMethod();

	// Parentheses are not necessary here, because the 
	// precedence rules make the code work as intended. 
	// Do not include the parentheses.
	x = a * b + c * d; 
	abc = *myObj->myMethod();

	// This example uses parentheses even though they are not strictly
	// necessary, because the order of precedence is rather subtle.
	x = (a >> b) ^ xyz->getExp();  
	xyz = &((*abc)->myFunc());

It is important to learn the rules of precedence and only use parentheses when appropriate.

 

Array Initializers

When initializing an array using a list of values, place the assignment operator and the opening brace on the same line as the variable name (if the 80 column limit allows) and place each initializer value on a separate line followed by a comma. The closing brace should align with the type of the array. For example:

const oaString oaDBType::names[] = {
    "Design",
    "Tech",
    "Lib",
    "Wafer",
    "Session",
    "DMData"
}; 

Signed versus Unsigned Declarations

Do not use a signed variable in a situation where the variable can never correctly contain a negative value. In these situations, always use an unsigned variable.

It is better to use unsigned variables because:

A common situation in which an unsigned variable can and should be used is as the index of a loop.



Pointers versus References

Although relatively simple to use, many C programmers have difficulty understanding the value or correct usage of references. Our coding standards dictate that in most situations you should use a reference rather than a pointer.

References and pointers have the following (somewhat subtle) usage differences:

Using references rather than pointers makes it possible to write functions with arguments that can be filled out by the function, without either the caller or the function dealing with the arguments in any special way.

To illustrate, the following two loops perform the same function. The first version uses references, and the second version uses pointers.

	// This loop generates the union of all shape bounding boxes. 
	// Here we assume references to a oaBox have been declared in 
	// the argument list for getBBox() and bBox.or().
	oaBox                           bBox;
	oaIter<oaShape>                 *iter(cellView->getShapes());
	oaShape                         *shape;

	while (shape = iter->getNext()) {
	    oaBox       shapeBBox;

	    //just pass the object; the reference will handle the details 
	    // of creating and dereferencing a pointer to the shapeBBox.
	    shape->getBBox(shapeBBox); 
	    bBox.or(shapeBBox);
	}

	// As above, this loop generates the union of all shape bounding boxes. 
	// Here we assume pointers to a oaBox have been declared in the argument
	// list for getBBox() and bBox.or().
	oaBox                           bBox;
	oaIter<oaShape>                 *iter = new oaIter<oaShape>(cellView->getShapes());
	oaShape                 	*shape;

	while (shape = iter->getNext()) {
	    oaBox       shapeBBox;

	    // We need to use the addressOf operator to pass pointers to shapeBBox.
	    // We will also need to dereference the pointers within getBBox() 
	    // and bBox.or().
	    shape->getBBox(&shapeBBox);
	    bBox.or(&shapeBBox);
	}
	
	delete iter;

Although the difference is relatively minor, you can see that there are several places where the loop using pointers must pass in the address of an object. With references, the same thing is happening, but the compiler does it automatically.

In the functions being called (such as box.or()), the passed in arguments are less likely to be NULL, as long as the calling functions are not dereferencing pointers to generate the references.



Remove Test Code

Do not mix test code with the actual source code. If you add test code during the development process, do not comment it out and leave it in the code. This expands the actual source code and makes it more difficult to read. Test code belongs in the test suite, not in the common source code.

This does not refer to test code that is used during the development. It refers to the completed code.



Compile Time Directives

Avoid using compile time directives where possible. Compile time directives can make the source code difficult to read. A common reason for using #if is to conditionally compile test code. As mentioned in the previous section, do not leave test code in the completed source code.

There are two cases in which compile time directives are necessary and appropriate:

Always use:

    #if defined(...)

instead of:

    #ifdef ...

and use:

    #if !defined(...)

instead of:

    #ifndef ...

The verbose style is necessary to check for multiple symbols on the same line. The following example has no corresponding syntax using the #ifdef form.

    #if defined(WINDOWS) && defined(OA_BASE_DLL_EXPORTS)




Return to top of page