This repository was archived by the owner on Nov 10, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
Add LIMIT, ROUNDED_DIV, and SIZEOF macros #14
Open
aiw-google
wants to merge
4
commits into
nestlabs:master
Choose a base branch
from
aiw-google:aiw-google-new-macros
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
1.3.6 | ||
1.3.7 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
/* | ||
* | ||
* Copyright (c) 2012-2018 Nest Labs, Inc. | ||
* Copyright (c) 2012-2019 Nest Labs, Inc. | ||
* All rights reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
|
@@ -37,8 +37,8 @@ | |
|
||
// The #ifndefs in this file are for third-party software that defines its | ||
// own identically-named macros, and for our own software that hasn't yet | ||
// been modified to use this shared set of macros. Eventually, our | ||
// software won't need the #ifndefs. | ||
// been modified to use this shared set of macros. Eventually, our software | ||
// won't need the #ifndefs. | ||
|
||
// Deprecated macros, included for compatibility with legacy code. | ||
#ifndef ROUNDUP | ||
|
@@ -48,19 +48,19 @@ | |
#define MILLISECONDS_PER_SECOND MS_PER_SEC | ||
|
||
// MIN and MAX, as usually written, are the canonical examples of macros that | ||
// fail when passed expressions with side-effects (e.g., "MAX(x++, y++)"). Our | ||
// fail when passed expressions with side-effects (e.g., "MAX(x++, y++)"). Our | ||
// LOG2, CTZ, IS_POW2, and ROUNDDOWN/ROUNDUP macros have similar issues with | ||
// side effects. | ||
// | ||
// For C programs, we solve this problem by using safer macros that require the | ||
// statement-expression and typeof extensions, and the __COUNTER__ predefined | ||
// macro, provided by GCC and Clang. For C++ programs, there's a subtle case | ||
// macro, provided by GCC and Clang. For C++ programs, there's a subtle case | ||
// where those macros will fail (see GCC's statement-expression documentation | ||
// for details), so we use the usual macros; they still have a side-effects | ||
// problem, but at least that one is well-known and therefore easier to debug | ||
// than the obscure problem with statement expressions in C++. | ||
|
||
// We always set BUILD_FEATURE_USE_UNSAFE_MACROS to 1 for C++ programs. If the | ||
// We always set BUILD_FEATURE_USE_UNSAFE_MACROS to 1 for C++ programs. If the | ||
// unsafe versions of the macros are desired for C programs as well, set | ||
// BUILD_FEATURE_USE_UNSAFE_MACROS to 1 on the command line or in the makefile. | ||
|
||
|
@@ -75,11 +75,12 @@ | |
#ifndef MIN | ||
#define MIN(a, b) ((a) < (b) ? (a) : (b)) | ||
#endif | ||
|
||
#ifndef MAX | ||
#define MAX(a, b) ((a) > (b) ? (a) : (b)) | ||
#endif | ||
|
||
#ifndef LIMIT | ||
#define LIMIT(v, low, high) MAX(low, MIN(v, high)) | ||
#endif | ||
#ifndef LOG2 | ||
#define LOG2(x) ((x) != 0 ? 31 - __builtin_clz(x) : -1) | ||
#endif | ||
|
@@ -92,53 +93,68 @@ | |
|
||
// ROUNDDOWN and ROUNDUP_U/ROUNDUP_S actually perform "round toward 0" and | ||
// "round away from 0", respectively (and they only perform it for integral | ||
// types). ROUNDUP_S works with signed parameters; ROUNDUP_U is just ROUNDUP_S | ||
// types). ROUNDUP_S works with signed parameters; ROUNDUP_U is just ROUNDUP_S | ||
// simplified for the usual case in which both parameters are unsigned. | ||
#ifndef ROUNDDOWN | ||
#define ROUNDDOWN(a, b) ((a) / (b) * (b)) | ||
#endif | ||
#define ROUNDUP_S(a, b) ROUNDDOWN((a) + ((((a) < 0) == ((b) < 0)) ? (b) : -(b)) + (((a) < 0) ? 1 : -1), b) | ||
#define ROUNDUP_U(a, b) ROUNDDOWN((a) + (b) - 1, b) | ||
|
||
// ROUNDED_DIV divides a by b, rounding the quotient to the nearest integer. | ||
// A quotient exactly halfway between integers is rounded away from zero. | ||
// | ||
// Note that our test for non-negative is "a == 0 || a > 0" rather than | ||
// "a >= 0", in order to avoid "comparison is always true" warnings with | ||
// unsigned inputs. | ||
#ifndef ROUNDED_DIV | ||
#define ROUNDED_DIV(a, b) (((a) + (((a) == 0 || (a) > 0) != ((b) == 0 || (b) > 0) ? -(b) : (b)) / 2) / (b)) | ||
#endif | ||
|
||
#else // #ifdef BUILD_FEATURE_USE_UNSAFE_MACROS | ||
|
||
// Safer macros. | ||
|
||
// MIN and MAX include static asserts that trigger if their two arguments | ||
// differ in signedness. This prevents, for example, MAX(-1,1U) = -1. | ||
// differ in signedness. This prevents, for example, MAX(-1,1U) = -1. | ||
// | ||
// The test for each argument is "(__typeof__(X))(-1) <= 0"; casting the "-1" | ||
// to the type of X forces it to become unsigned if X is unsigned, so the test | ||
// simplifies to either "-1 <= 0" (true) or "-1U <= 0" (false, because "-1U" | ||
// is a large all-ones positive number). If the two macro arguments have | ||
// is a large all-ones positive number). If the two macro arguments have | ||
// different signedness, the two test results will be different and we'll | ||
// trigger the assert. | ||
// | ||
// Note that the comparison is "<= 0" rather than "< 0" in order to avoid | ||
// "comparison is always false" warnings when X is unsigned. | ||
// | ||
// Note also that we're testing the signedness AS WRITTEN (that is, before | ||
// integer promotion). This means that we will not assert on a comparison | ||
// integer promotion). This means that we will not assert on a comparison | ||
// between uint16_t and uint32_t, and we WILL assert on a comparison between | ||
// uint16_t and int32_t, even though in both cases the compiler will internally | ||
// promote the unsigned uint16_t to a SIGNED int_32_t for the comparison. | ||
// | ||
// Finally, note that the LOG2 and CTZ macros explicitly cast their parameters | ||
// to unsigned int, because that's the argument type of the underlying GCC | ||
// builtin functions. | ||
#ifndef MIN | ||
#define MIN(a, b) MIN_INNER(a, b, __COUNTER__) | ||
#define MIN_INNER(a, b, C) ({ __typeof__(a) _CC(_a, C) = (a); __typeof__(b) _CC(_b, C) = (b); _NLMACROS_ASSERT(((__typeof__(a))(-1) <= 0) == ((__typeof__(b))(-1) <= 0)); (_CC(_a, C) < _CC(_b, C)) ? _CC(_a, C) : _CC(_b, C); }) | ||
#endif | ||
|
||
#ifndef MAX | ||
#define MAX(a, b) MAX_INNER(a, b, __COUNTER__) | ||
#define MAX_INNER(a, b, C) ({ __typeof__(a) _CC(_a, C) = (a); __typeof__(b) _CC(_b, C) = (b); _NLMACROS_ASSERT(((__typeof__(a))(-1) <= 0) == ((__typeof__(b))(-1) <= 0)); (_CC(_a, C) > _CC(_b, C)) ? _CC(_a, C) : _CC(_b, C); }) | ||
#endif | ||
|
||
#ifndef LIMIT | ||
#define LIMIT(v, low, high) MAX(low, MIN(v, high)) | ||
#endif | ||
#ifndef LOG2 | ||
#define LOG2(x) LOG2_INNER(x, __COUNTER__) | ||
#define LOG2_INNER(x, C) ({ __typeof__(x) _CC(_x, C) = (x); (_CC(_x, C) != 0) ? 31 - __builtin_clz(_CC(_x, C)) : -1; }) | ||
#define LOG2_INNER(x, C) ({ unsigned int _CC(_x, C) = (x); (_CC(_x, C) != 0) ? 31 - __builtin_clz(_CC(_x, C)) : -1; }) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This change and the one below on 157 seem unrelated. What was the genesis of these? Regardless, they should probably be in a separate PR if they are unrelated to the addition of LIMIT, ROUNDED_DIV, and SIZEOF. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You're right, these two changes are unrelated to the others. And they're unfinished, too. I'll pull them out into a separate PR. |
||
#endif | ||
#ifndef CTZ | ||
#define CTZ(x) CTZ_INNER(x, __COUNTER__) | ||
#define CTZ_INNER(x, C) ({ __typeof__(x) _CC(_x, C) = (x); (_CC(_x, C) != 0) ? __builtin_ctz(_CC(_x, C)) : -1; }) | ||
#define CTZ_INNER(x, C) ({ unsigned int _CC(_x, C) = (x); (_CC(_x, C) != 0) ? __builtin_ctz(_CC(_x, C)) : -1; }) | ||
#endif | ||
#ifndef IS_POW2 | ||
#define IS_POW2(x) IS_POW2_INNER(x, __COUNTER__) | ||
|
@@ -147,7 +163,7 @@ | |
|
||
// ROUNDDOWN and ROUNDUP_U/ROUNDUP_S actually perform "round toward 0" and | ||
// "round away from 0", respectively (and they only perform it for integral | ||
// types). ROUNDUP_S works with signed or unsigned parameters; ROUNDUP_U is | ||
// types). ROUNDUP_S works with signed or unsigned parameters; ROUNDUP_U is | ||
// just ROUNDUP_S simplified for the usual case in which both parameters are | ||
// unsigned, and it contains a static assert (with a test similar to the one | ||
// described above for MIN and MAX) that triggers if either argument is signed. | ||
|
@@ -160,6 +176,17 @@ | |
#define ROUNDUP_U(a, b) ROUNDUP_U_INNER(a, b, __COUNTER__) | ||
#define ROUNDUP_U_INNER(a, b, C) ({ __typeof__(a) _CC(_a, C) = (a); __typeof__(b) _CC(_b, C) = (b); _NLMACROS_ASSERT(((__typeof__(a))(-1) > 0) && ((__typeof__(b))(-1) > 0)); ROUNDDOWN(_CC(_a, C) + _CC(_b, C) - 1, _CC(_b, C)); }) | ||
|
||
// ROUNDED_DIV divides a by b, rounding the quotient to the nearest integer. | ||
// A quotient exactly halfway between integers is rounded away from zero. | ||
// | ||
// Note that our test for non-negative is "a == 0 || a > 0" rather than | ||
// "a >= 0", in order to avoid "comparison is always true" warnings with | ||
// unsigned inputs. | ||
#ifndef ROUNDED_DIV | ||
#define ROUNDED_DIV(a, b) ROUNDED_DIV_INNER(a, b, __COUNTER__) | ||
#define ROUNDED_DIV_INNER(a, b, C) ({ __typeof__(a) _CC(_a, C) = (a); __typeof__(b) _CC(_b, C) = (b); (_CC(_a, C) + ((_CC(_a, C) == 0 || _CC(_a, C) > 0) != (_CC(_b, C) == 0 || _CC(_b, C) > 0) ? -(_CC(_b, C)) : _CC(_b, C)) / 2) / _CC(_b, C); }) | ||
#endif | ||
|
||
#endif // #ifdef BUILD_FEATURE_USE_UNSAFE_MACROS | ||
|
||
// Each parameter evaluated once | ||
|
@@ -187,9 +214,11 @@ | |
#define ARRAY_LAST(a) (&((a)[ARRAY_SIZE(a) - 1])) | ||
#endif | ||
|
||
// Offset, in bytes, of a structure member from the address of its structure. | ||
// | ||
// In the extraordinarily unlikely event that this code is passed to a pre-C89 | ||
// compiler (or one without a compliant stddef.h that includes "offsetof"), | ||
// we'll use our own OFFSETOF macro. Otherwise, we'll use the one provided by | ||
// we'll use our own OFFSETOF macro. Otherwise, we'll use the one provided by | ||
// the compiler, which is at least no worse than ours and might be better. | ||
#ifndef OFFSETOF | ||
#ifndef offsetof | ||
|
@@ -199,16 +228,25 @@ | |
#endif | ||
#endif | ||
|
||
// Pointer to the structure that contains the member pointed to by 'pointer'. | ||
// | ||
// The "(1 ? (pointer) : &((type *)0)->member)" is functionally equivalent to | ||
// "(pointer)", but it provides type safety by ensuring that "pointer" points | ||
// to a type compatible with "member" (because the conditional operator requires | ||
// pointer operands to be of compatible type). | ||
#ifndef CONTAINEROF | ||
#define CONTAINEROF(pointer, type, member) (nlStaticCast(type *, \ | ||
(nlStaticCast(char *, (1 ? (pointer) : &(nlStaticCast(type *, 0)->member))) - \ | ||
OFFSETOF(type, member)))) | ||
OFFSETOF(type, member)))) | ||
#endif | ||
|
||
// Size, in bytes, of a structure member. | ||
#ifndef SIZEOF | ||
#define SIZEOF(type, member) (nlStaticCast(size_t, sizeof(nlStaticCast(type *, 0)->member))) | ||
#endif | ||
|
||
// Pointer to the smallest `size`-aligned address greater than or equal to | ||
// 'pointer'. 'size' must be a positive integral power of two. | ||
#ifndef ALIGN_POINTER | ||
#define ALIGN_POINTER(pointer, size) (nlStaticCast(uint8_t *, nlStaticCast(uintptr_t, (pointer) + ((size) - 1)) & (~((size) - 1)))) | ||
#endif | ||
|
@@ -232,7 +270,7 @@ | |
#define CONCAT(a, b) a##b | ||
#endif | ||
|
||
// Static assert macro for internal use in this header file only. This macro | ||
// Static assert macro for internal use in this header file only. This macro | ||
// definition is intended to duplicate the _nlSTATIC_ASSERT macro definition | ||
// in nlassert-internal.h, so if this definition is modified, that one should | ||
// be modified to match. | ||
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should add a new "Copyright (c) 2019 Google LLC" line since Nest Labs is no more as a corporate entity.