blob: cf08d58e66bd257b4d39e8c7e3700ff2ff036d60 [file] [log] [blame]
// Copyright 2019 The Pigweed Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
#pragma once
// Preprocessor boolean operation macros that evaluate to 0 or 1.
//
// These macros perform boolean operations in the C preprocessor that evaluate
// to a literal 1 or 0. They can be used for a few purposes:
//
// - Generate other macros that evaluate to a 1 or 0, instead of a
// parenthesized boolean expression.
// - Ensure that the operands are defined and evaluate to 1 or 0 themselves.
// - Write macros that conditionally use other macros by token pasting the
// resulting 1 or 0 to form a new macro name.
//
// These macros should not be used outside of macro definitions. Use normal C
// operators (&&, ||, !, ==, !=) instead. For example, to check whether two
// flags are set, the C operators are the best choice:
//
// #if RELEASE && OPTIMIZED
//
// However, there are cases when a literal 0 or 1 is required. For example:
//
// #define SELECT_ALGORITHM() PW_CONCAT(ALGO_, PW_AND(RELEASE, OPTIMIZED))
//
// SELECT_ALGORITHM evaluates to ALGO_0 or ALGO_1, depending on whether RELEASE
// and OPTIMIZED are set to 1.
// Boolean AND of two preprocessor expressions that evaluate to 0 or 1.
#define PW_AND(a, b) _PW_AND(a, b) // Expand the macro an extra time to
#define _PW_AND(a, b) _PW_AND_##a##b() // allow macro substitution to occur.
#define _PW_AND_00() 0
#define _PW_AND_01() 0
#define _PW_AND_10() 0
#define _PW_AND_11() 1
// Boolean OR of two preprocessor expressions that evaluate to 0 or 1.
#define PW_OR(a, b) _PW_OR(a, b)
#define _PW_OR(a, b) _PW_OR_##a##b()
#define _PW_OR_00() 0
#define _PW_OR_01() 1
#define _PW_OR_10() 1
#define _PW_OR_11() 1
// Boolean NOT of a preprocessor expression that evaluates to 0 or 1.
#define PW_NOT(value) _PW_NOT(value)
#define _PW_NOT(value) _PW_NOT_##value()
#define _PW_NOT_0() 1
#define _PW_NOT_1() 0
// Boolean XOR of two preprocessor expressions that evaluate to 0 or 1.
#define PW_XOR(a, b) _PW_XOR(a, b)
#define _PW_XOR(a, b) _PW_XOR_##a##b()
#define _PW_XOR_00() 0
#define _PW_XOR_01() 1
#define _PW_XOR_10() 1
#define _PW_XOR_11() 0
// Boolean NAND, NOR, and XNOR of expressions that evaluate to 0 or 1.
#define PW_NAND(a, b) PW_NOT(PW_AND(a, b))
#define PW_NOR(a, b) PW_NOT(PW_OR(a, b))
#define PW_XNOR(a, b) PW_NOT(PW_XOR(a, b))