1 #ifndef LIBNONSTD_INTEGRAL_H
2 #define LIBNONSTD_INTEGRAL_H
8 /* C object representation type
10 * Use: access and manipulate the raw bytes of a C object.
14 * Values stored in unsigned bit-fields *and objects of type unsigned char*
15 * shall be represented using a pure binary notation.
17 * Values stored in non-bit-field objects of any other object type consist of n
18 * x CHAR_BIT bits, where n is the size of an object of that type, in bytes.
19 * The value may be copied into an object of type unsigned char [n] (e.g., by
20 * memcpy); the resulting set of bytes is called the object representation of
25 * For unsigned integer types *other than unsigned char,* the bits of the
26 * object representation shall be divided into two groups: value bits and
27 * padding bits (there need not be any of the latter).
30 typedef unsigned char byte;
32 /* Integer bit patterns
34 * Usage: bitwise operations and modular arithmetic, with exact bit widths.
38 * A computation involving unsigned operands can never overflow, because a
39 * result that cannot be represented by the resulting unsigned integer type is
40 * reduced modulo the number that is one greater than the largest value that
41 * can be represented by the resulting type.
49 /* General-purpose (signed) integers
51 * Usage: normal arithmetical operations and measurement, without modular
52 * arithmetic expectations.
54 * Care is required with these types to avoid overflow, which is undefined
57 * Each type "iN" is guaranteed to hold at least N bits, but may be wider if
58 * that would be faster for the processor. The "_trim" variety attempts to save
59 * space for e.g. big arrays.
62 typedef int_fast8_t i8;
63 typedef int_least8_t i8_trim;
65 typedef int_fast16_t i16; // int
66 typedef int_least16_t i16_trim; // short
68 typedef int_fast32_t i32; // long
69 typedef int_least32_t i32_trim;
71 typedef int_fast64_t i64; // long long
72 typedef int_least64_t i64_trim;
74 /* The size of data objects.
76 * This is a numerical quantity, not a bit pattern. Thus it fits into the
77 * signed integer category. This notion conflicts with the definition of
78 * size_t. We provide a signed counterpart, and wrappers for sizeof() and
79 * offsetof() that do bounds checking and conver the result.
81 * My conjecture is that size_t was chosen to be unsigned to wring the most out
82 * of each available bit on e.g. segmented 16-bit memory architectures. A 64K
83 * object size limit was bad enough, and a 32K limit would be intolerable.
87 // get ssize_t from POSIX
88 #include <sys/types.h>
90 // make our best approximation
91 typedef ptrdiff_t ssize_t;
92 #define SSIZE_MAX PTRDIFF_MAX
96 (sizeof(x) <= (size_t)SSIZE_MAX ? (ssize_t)sizeof(x) : -1)
98 #define soffsetof(t, m) \
99 (offsetof((t), (m)) <= (size_t)SSIZE_MAX ? offsetof((t), (m)) : -1)
101 /* Character types -- no extras provided. They are either out of scope for a
102 * base library, or are redundant with the types above. Here are the three uses
105 * 1. Codepoints in a character encoding. The tasks of human language
106 * processing are too broad for a base language library, and the rules
107 * change as languages and locales do. Use a proper library for this, such
108 * as ICU, and its provided data types.
110 * - Storage and transmission of UTF-8 can use b8.
112 * - Pointers to native C string literals should be char*, as the signedness
113 * of char is implementation-defined.
115 * 2. Smallest units of addressible storage. We covered this case already with
118 * 3. Small integers. Already covered with b8, i8, and i8_trim.
121 // Character typedefs intentionally left blank