/*- * Copyright (c) 2019 Taylor R. Campbell * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef CONTAINER_OF_H #define CONTAINER_OF_H #include /* offsetof */ /* * container_of(P, T, F) * const_container_of(P, T, F) * * If P is a pointer to the member F of a structure type T, return * a pointer to the enclosing structure of type T. For example: * * struct foo { * int x; * char y; * }; * * struct foo f = {...}; * char *yp = &f.y; * * From yp, we can recover &f by: * * struct foo *fp = container_of(yp, struct foo, y); * assert(fp == &f); * * const_container_of is similar, but allows P to be a const * pointer and returns a pointer to const T. * * Technical details of how we detect type mistakes: * * - The expression 0 ? (PTR) : ... causes the compiler to warn if the * type of *fp does not match the type of struct bar::b_foo. Used to * use (PTR) - ..., but that doesn't work if the member is an empty * aggregate type. * * - The further expression container_of_nonconst(0 ? (PTR) : ...) * causes the compiler to warn if PTR is const-qualified, so that * container_of doesn't serve to accidentally upgrade a const pointer * to a non-const pointer. This works because container_of_nonconst * is declared to be a function that takes a non-const pointer. * * - Surrounding it all in sizeof(container_of_nonconst(...)) avoids * actually evaluating the subexpression, so it is limited to a * compile-time constant, and we need not actually furnish a * definition of container_of_nonconst. * * - Multiplying it by zero, 0*sizeof(...), gives us an expression that * has constant value zero, so we can add it to a pointer without * changing the result. * * In contrast, for instance, using the comma operator, (sizeof(...), * rest), might lead the compiler to warn about an unused result of * comma operand without side effects. */ #define container_of(PTR, TYPE, FIELD) \ ((TYPE *)(((char *)(PTR)) - offsetof(TYPE, FIELD)) \ + 0*sizeof(container_of_nonconst(0 ? (PTR) : \ &((TYPE *)(((char *)(PTR)) - \ offsetof(TYPE, FIELD)))->FIELD))) #define const_container_of(PTR, TYPE, FIELD) \ ((const TYPE *)(((const char *)(PTR)) - offsetof(TYPE, FIELD)) \ + 0*sizeof(0 ? (PTR) : \ &((const TYPE *)(((const char *)(PTR)) - \ offsetof(TYPE, FIELD)))->FIELD)) /* Useless symbol that serves only to flag const pointers. */ void container_of_nonconst(void *); #endif /* CONTAINER_OF_H */