2
0
mirror of https://github.com/openvswitch/ovs synced 2025-08-28 04:47:49 +00:00

155 lines
6.2 KiB
C
Raw Normal View History

/*
* Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc.
*
* 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:
*
* http://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.
*/
#ifndef OPENVSWITCH_UTIL_H
#define OPENVSWITCH_UTIL_H 1
#include <openvswitch/version.h>
#include <openvswitch/compiler.h>
#ifdef __cplusplus
extern "C" {
#endif
void ovs_set_program_name__(const char *name, const char *version,
const char *date, const char *time);
#define ovs_set_program_name(name, version) \
ovs_set_program_name__(name, version, __DATE__, __TIME__)
const char *ovs_get_program_name(void);
const char *ovs_get_program_version(void);
/* Expands to a string that looks like "<file>:<line>", e.g. "tmp.c:10".
*
* See http://c-faq.com/ansi/stringize.html for an explanation of OVS_STRINGIZE
* and OVS_STRINGIZE2. */
#define OVS_SOURCE_LOCATOR __FILE__ ":" OVS_STRINGIZE(__LINE__)
#define OVS_STRINGIZE(ARG) OVS_STRINGIZE2(ARG)
#define OVS_STRINGIZE2(ARG) #ARG
/* Saturating multiplication of "unsigned int"s: overflow yields UINT_MAX. */
#define OVS_SAT_MUL(X, Y) \
((Y) == 0 ? 0 \
: (X) <= UINT_MAX / (Y) ? (unsigned int) (X) * (unsigned int) (Y) \
: UINT_MAX)
/* Like the standard assert macro, except writes the failure message to the
* log. */
#ifndef NDEBUG
#define ovs_assert(CONDITION) \
if (!OVS_LIKELY(CONDITION)) { \
ovs_assert_failure(OVS_SOURCE_LOCATOR, __func__, #CONDITION); \
}
#else
#define ovs_assert(CONDITION) ((void) (CONDITION))
#endif
OVS_NO_RETURN void ovs_assert_failure(const char *, const char *, const char *);
/* This is a void expression that issues a compiler error if POINTER cannot be
* compared for equality with the given pointer TYPE. This generally means
* that POINTER is a qualified or unqualified TYPE. However,
* BUILD_ASSERT_TYPE(POINTER, void *) will accept any pointer to object type,
* because any pointer to object can be compared for equality with "void *".
*
* POINTER can be any expression. The use of "sizeof" ensures that the
* expression is not actually evaluated, so that any side effects of the
* expression do not occur.
*
* The cast to int is present only to suppress an "expression using sizeof
* bool" warning from "sparse" (see
* http://permalink.gmane.org/gmane.comp.parsers.sparse/2967). */
#define BUILD_ASSERT_TYPE(POINTER, TYPE) \
((void) sizeof ((int) ((POINTER) == (TYPE) (POINTER))))
/* Casts 'pointer' to 'type' and issues a compiler warning if the cast changes
* anything other than an outermost "const" or "volatile" qualifier.
*
* The cast to int is present only to suppress an "expression using sizeof
* bool" warning from "sparse" (see
* http://permalink.gmane.org/gmane.comp.parsers.sparse/2967). */
#define CONST_CAST(TYPE, POINTER) \
(BUILD_ASSERT_TYPE(POINTER, TYPE), \
(TYPE) (POINTER))
/* Given a pointer-typed lvalue OBJECT, expands to a pointer type that may be
* assigned to OBJECT. */
#ifdef __GNUC__
#define OVS_TYPEOF(OBJECT) typeof(OBJECT)
#else
#define OVS_TYPEOF(OBJECT) void *
#endif
/* Given OBJECT of type pointer-to-structure, expands to the offset of MEMBER
* within an instance of the structure.
*
* The GCC-specific version avoids the technicality of undefined behavior if
* OBJECT is null, invalid, or not yet initialized. This makes some static
* checkers (like Coverity) happier. But the non-GCC version does not actually
* dereference any pointer, so it would be surprising for it to cause any
* problems in practice.
*/
#ifdef __GNUC__
#define OBJECT_OFFSETOF(OBJECT, MEMBER) offsetof(typeof(*(OBJECT)), MEMBER)
#else
#define OBJECT_OFFSETOF(OBJECT, MEMBER) \
((char *) &(OBJECT)->MEMBER - (char *) (OBJECT))
#endif
/* Yields the size of MEMBER within STRUCT. */
#define MEMBER_SIZEOF(STRUCT, MEMBER) (sizeof(((STRUCT *) NULL)->MEMBER))
/* Yields the offset of the end of MEMBER within STRUCT. */
#define OFFSETOFEND(STRUCT, MEMBER) \
(offsetof(STRUCT, MEMBER) + MEMBER_SIZEOF(STRUCT, MEMBER))
/* Given POINTER, the address of the given MEMBER in a STRUCT object, returns
the STRUCT object. */
#define CONTAINER_OF(POINTER, STRUCT, MEMBER) \
((STRUCT *) (void *) ((char *) (POINTER) - offsetof (STRUCT, MEMBER)))
/* Given POINTER, the address of the given MEMBER within an object of the type
* that that OBJECT points to, returns OBJECT as an assignment-compatible
* pointer type (either the correct pointer type or "void *"). OBJECT must be
* an lvalue.
*
* This is the same as CONTAINER_OF except that it infers the structure type
* from the type of '*OBJECT'. */
#define OBJECT_CONTAINING(POINTER, OBJECT, MEMBER) \
((OVS_TYPEOF(OBJECT)) (void *) \
((char *) (POINTER) - OBJECT_OFFSETOF(OBJECT, MEMBER)))
/* Given POINTER, the address of the given MEMBER within an object of the type
* that that OBJECT points to, assigns the address of the outer object to
* OBJECT, which must be an lvalue.
*
* Evaluates to (void) 0 as the result is not to be used. */
#define ASSIGN_CONTAINER(OBJECT, POINTER, MEMBER) \
((OBJECT) = OBJECT_CONTAINING(POINTER, OBJECT, MEMBER), (void) 0)
/* As explained in the comment above OBJECT_OFFSETOF(), non-GNUC compilers
* like MSVC will complain about un-initialized variables if OBJECT
* hasn't already been initialized. To prevent such warnings, INIT_CONTAINER()
* can be used as a wrapper around ASSIGN_CONTAINER. */
#define INIT_CONTAINER(OBJECT, POINTER, MEMBER) \
((OBJECT) = NULL, ASSIGN_CONTAINER(OBJECT, POINTER, MEMBER))
#ifdef __cplusplus
}
#endif
#endif