Commit 74bf54b9 authored by Kenton Varda's avatar Kenton Varda

Define new KJ constants for min/max integer values and inf/nan, then remove all…

Define new KJ constants for min/max integer values and inf/nan, then remove all use of numeric_limits.
parent 4878663f
...@@ -364,8 +364,7 @@ private: ...@@ -364,8 +364,7 @@ private:
// ======================================================================================= // =======================================================================================
inline ReadLimiter::ReadLimiter() inline ReadLimiter::ReadLimiter()
// I didn't want to #include <limits> just for this one lousy constant. : limit(kj::maxValue) {}
: limit(0x7fffffffffffffffllu) {}
inline ReadLimiter::ReadLimiter(WordCount64 limit): limit(limit / WORDS) {} inline ReadLimiter::ReadLimiter(WordCount64 limit): limit(limit / WORDS) {}
......
...@@ -41,7 +41,6 @@ ...@@ -41,7 +41,6 @@
#include <sys/wait.h> #include <sys/wait.h>
#include <capnp/serialize.h> #include <capnp/serialize.h>
#include <capnp/serialize-packed.h> #include <capnp/serialize-packed.h>
#include <limits>
#include <errno.h> #include <errno.h>
#include <stdlib.h> #include <stdlib.h>
...@@ -608,9 +607,8 @@ private: ...@@ -608,9 +607,8 @@ private:
// Since this is a debug tool, lift the usual security limits. Worse case is the process // Since this is a debug tool, lift the usual security limits. Worse case is the process
// crashes or has to be killed. // crashes or has to be killed.
ReaderOptions options; ReaderOptions options;
options.nestingLimit = std::numeric_limits<decltype(options.nestingLimit)>::max() >> 1; options.nestingLimit = kj::maxValue;
options.traversalLimitInWords = options.traversalLimitInWords = kj::maxValue;
std::numeric_limits<decltype(options.traversalLimitInWords)>::max();
MessageReaderType reader(input, options); MessageReaderType reader(input, options);
kj::String text; kj::String text;
......
...@@ -27,7 +27,6 @@ ...@@ -27,7 +27,6 @@
#include <kj/arena.h> #include <kj/arena.h>
#include <set> #include <set>
#include <map> #include <map>
#include <limits>
namespace capnp { namespace capnp {
namespace compiler { namespace compiler {
...@@ -440,7 +439,7 @@ public: ...@@ -440,7 +439,7 @@ public:
uint addData(uint lgSize) override { uint addData(uint lgSize) override {
addVoid(); addVoid();
uint bestSize = std::numeric_limits<uint>::max(); uint bestSize = kj::maxValue;
kj::Maybe<uint> bestLocation = nullptr; kj::Maybe<uint> bestLocation = nullptr;
for (uint i = 0; i < parent.dataLocations.size(); i++) { for (uint i = 0; i < parent.dataLocations.size(); i++) {
...@@ -1661,19 +1660,19 @@ kj::Maybe<Orphan<DynamicValue>> ValueTranslator::compileValue( ...@@ -1661,19 +1660,19 @@ kj::Maybe<Orphan<DynamicValue>> ValueTranslator::compileValue(
if (value < 0) { if (value < 0) {
int64_t minValue = 1; int64_t minValue = 1;
switch (type.which()) { switch (type.which()) {
case schema::Type::INT8: minValue = std::numeric_limits<int8_t>::min(); break; case schema::Type::INT8: minValue = (int8_t)kj::minValue; break;
case schema::Type::INT16: minValue = std::numeric_limits<int16_t>::min(); break; case schema::Type::INT16: minValue = (int16_t)kj::minValue; break;
case schema::Type::INT32: minValue = std::numeric_limits<int32_t>::min(); break; case schema::Type::INT32: minValue = (int32_t)kj::minValue; break;
case schema::Type::INT64: minValue = std::numeric_limits<int64_t>::min(); break; case schema::Type::INT64: minValue = (int64_t)kj::minValue; break;
case schema::Type::UINT8: minValue = std::numeric_limits<uint8_t>::min(); break; case schema::Type::UINT8: minValue = (uint8_t)kj::minValue; break;
case schema::Type::UINT16: minValue = std::numeric_limits<uint16_t>::min(); break; case schema::Type::UINT16: minValue = (uint16_t)kj::minValue; break;
case schema::Type::UINT32: minValue = std::numeric_limits<uint32_t>::min(); break; case schema::Type::UINT32: minValue = (uint32_t)kj::minValue; break;
case schema::Type::UINT64: minValue = std::numeric_limits<uint64_t>::min(); break; case schema::Type::UINT64: minValue = (uint64_t)kj::minValue; break;
case schema::Type::FLOAT32: case schema::Type::FLOAT32:
case schema::Type::FLOAT64: case schema::Type::FLOAT64:
// Any integer is acceptable. // Any integer is acceptable.
minValue = std::numeric_limits<int64_t>::min(); minValue = (int64_t)kj::minValue;
break; break;
default: break; default: break;
...@@ -1693,19 +1692,19 @@ kj::Maybe<Orphan<DynamicValue>> ValueTranslator::compileValue( ...@@ -1693,19 +1692,19 @@ kj::Maybe<Orphan<DynamicValue>> ValueTranslator::compileValue(
case DynamicValue::UINT: { case DynamicValue::UINT: {
uint64_t maxValue = 0; uint64_t maxValue = 0;
switch (type.which()) { switch (type.which()) {
case schema::Type::INT8: maxValue = std::numeric_limits<int8_t>::max(); break; case schema::Type::INT8: maxValue = (int8_t)kj::maxValue; break;
case schema::Type::INT16: maxValue = std::numeric_limits<int16_t>::max(); break; case schema::Type::INT16: maxValue = (int16_t)kj::maxValue; break;
case schema::Type::INT32: maxValue = std::numeric_limits<int32_t>::max(); break; case schema::Type::INT32: maxValue = (int32_t)kj::maxValue; break;
case schema::Type::INT64: maxValue = std::numeric_limits<int64_t>::max(); break; case schema::Type::INT64: maxValue = (int64_t)kj::maxValue; break;
case schema::Type::UINT8: maxValue = std::numeric_limits<uint8_t>::max(); break; case schema::Type::UINT8: maxValue = (uint8_t)kj::maxValue; break;
case schema::Type::UINT16: maxValue = std::numeric_limits<uint16_t>::max(); break; case schema::Type::UINT16: maxValue = (uint16_t)kj::maxValue; break;
case schema::Type::UINT32: maxValue = std::numeric_limits<uint32_t>::max(); break; case schema::Type::UINT32: maxValue = (uint32_t)kj::maxValue; break;
case schema::Type::UINT64: maxValue = std::numeric_limits<uint64_t>::max(); break; case schema::Type::UINT64: maxValue = (uint64_t)kj::maxValue; break;
case schema::Type::FLOAT32: case schema::Type::FLOAT32:
case schema::Type::FLOAT64: case schema::Type::FLOAT64:
// Any integer is acceptable. // Any integer is acceptable.
maxValue = std::numeric_limits<uint64_t>::max(); maxValue = (uint64_t)kj::maxValue;
break; break;
default: break; default: break;
...@@ -1813,9 +1812,9 @@ Orphan<DynamicValue> ValueTranslator::compileValueInner( ...@@ -1813,9 +1812,9 @@ Orphan<DynamicValue> ValueTranslator::compileValueInner(
} else if (id == "false") { } else if (id == "false") {
return false; return false;
} else if (id == "nan") { } else if (id == "nan") {
return std::numeric_limits<double>::quiet_NaN(); return kj::nan();
} else if (id == "inf") { } else if (id == "inf") {
return std::numeric_limits<double>::infinity(); return kj::inf();
} }
} }
} }
...@@ -1833,7 +1832,7 @@ Orphan<DynamicValue> ValueTranslator::compileValueInner( ...@@ -1833,7 +1832,7 @@ Orphan<DynamicValue> ValueTranslator::compileValueInner(
case ValueExpression::NEGATIVE_INT: { case ValueExpression::NEGATIVE_INT: {
uint64_t nValue = src.getNegativeInt(); uint64_t nValue = src.getNegativeInt();
if (nValue > (std::numeric_limits<uint64_t>::max() >> 1) + 1) { if (nValue > ((uint64_t)kj::maxValue >> 1) + 1) {
errorReporter.addErrorOn(src, "Integer is too big to be negative."); errorReporter.addErrorOn(src, "Integer is too big to be negative.");
return nullptr; return nullptr;
} else { } else {
......
...@@ -29,7 +29,6 @@ ...@@ -29,7 +29,6 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <fcntl.h> #include <fcntl.h>
#include <limits>
namespace capnp { namespace capnp {
namespace compiler { namespace compiler {
...@@ -544,7 +543,7 @@ CapnpParser::CapnpParser(Orphanage orphanageParam, const ErrorReporter& errorRep ...@@ -544,7 +543,7 @@ CapnpParser::CapnpParser(Orphanage orphanageParam, const ErrorReporter& errorRep
-> Orphan<ValueExpression> { -> Orphan<ValueExpression> {
auto result = orphanage.newOrphan<ValueExpression>(); auto result = orphanage.newOrphan<ValueExpression>();
auto builder = result.get(); auto builder = result.get();
builder.setFloat(-std::numeric_limits<double>::infinity()); builder.setFloat(-kj::inf());
initLocation(location, builder); initLocation(location, builder);
return result; return result;
}), }),
......
...@@ -1661,16 +1661,16 @@ TEST(Encoding, Constants) { ...@@ -1661,16 +1661,16 @@ TEST(Encoding, Constants) {
List<float>::Reader listReader = test::TestConstants::FLOAT32_LIST_CONST; List<float>::Reader listReader = test::TestConstants::FLOAT32_LIST_CONST;
ASSERT_EQ(4u, listReader.size()); ASSERT_EQ(4u, listReader.size());
EXPECT_EQ(5555.5f, listReader[0]); EXPECT_EQ(5555.5f, listReader[0]);
EXPECT_EQ(std::numeric_limits<float>::infinity(), listReader[1]); EXPECT_EQ(kj::inf(), listReader[1]);
EXPECT_EQ(-std::numeric_limits<float>::infinity(), listReader[2]); EXPECT_EQ(-kj::inf(), listReader[2]);
EXPECT_TRUE(listReader[3] != listReader[3]); EXPECT_TRUE(listReader[3] != listReader[3]);
} }
{ {
List<double>::Reader listReader = test::TestConstants::FLOAT64_LIST_CONST; List<double>::Reader listReader = test::TestConstants::FLOAT64_LIST_CONST;
ASSERT_EQ(4u, listReader.size()); ASSERT_EQ(4u, listReader.size());
EXPECT_EQ(7777.75, listReader[0]); EXPECT_EQ(7777.75, listReader[0]);
EXPECT_EQ(std::numeric_limits<double>::infinity(), listReader[1]); EXPECT_EQ(kj::inf(), listReader[1]);
EXPECT_EQ(-std::numeric_limits<double>::infinity(), listReader[2]); EXPECT_EQ(-kj::inf(), listReader[2]);
EXPECT_TRUE(listReader[3] != listReader[3]); EXPECT_TRUE(listReader[3] != listReader[3]);
} }
checkList(*test::TestConstants::TEXT_LIST_CONST, {"plugh", "xyzzy", "thud"}); checkList(*test::TestConstants::TEXT_LIST_CONST, {"plugh", "xyzzy", "thud"});
......
...@@ -27,7 +27,6 @@ ...@@ -27,7 +27,6 @@
#include "arena.h" #include "arena.h"
#include "capability.h" #include "capability.h"
#include <string.h> #include <string.h>
#include <limits>
#include <stdlib.h> #include <stdlib.h>
namespace capnp { namespace capnp {
...@@ -462,7 +461,7 @@ struct WireHelpers { ...@@ -462,7 +461,7 @@ struct WireHelpers {
reinterpret_cast<const WirePointer*>(ptr + tag->structRef.dataSize.get()), reinterpret_cast<const WirePointer*>(ptr + tag->structRef.dataSize.get()),
tag->structRef.dataSize.get() * BITS_PER_WORD, tag->structRef.dataSize.get() * BITS_PER_WORD,
tag->structRef.ptrCount.get(), tag->structRef.ptrCount.get(),
0 * BITS, std::numeric_limits<int>::max())); 0 * BITS, kj::maxValue));
// no break: treat like struct pointer // no break: treat like struct pointer
case WirePointer::STRUCT: { case WirePointer::STRUCT: {
...@@ -548,7 +547,7 @@ struct WireHelpers { ...@@ -548,7 +547,7 @@ struct WireHelpers {
// ----------------------------------------------------------------- // -----------------------------------------------------------------
static WordCount64 totalSize(SegmentReader* segment, const WirePointer* ref, uint nestingLimit) { static WordCount64 totalSize(SegmentReader* segment, const WirePointer* ref, int nestingLimit) {
// Compute the total size of the object pointed to, not counting far pointer overhead. // Compute the total size of the object pointed to, not counting far pointer overhead.
if (ref->isNull()) { if (ref->isNull()) {
...@@ -2173,7 +2172,7 @@ void PointerBuilder::setList(const ListReader& value) { ...@@ -2173,7 +2172,7 @@ void PointerBuilder::setList(const ListReader& value) {
kj::Own<const ClientHook> PointerBuilder::getCapability() { kj::Own<const ClientHook> PointerBuilder::getCapability() {
return WireHelpers::readCapabilityPointer( return WireHelpers::readCapabilityPointer(
segment, pointer, std::numeric_limits<int>::max()); segment, pointer, kj::maxValue);
} }
void PointerBuilder::setCapability(kj::Own<const ClientHook>&& cap) { void PointerBuilder::setCapability(kj::Own<const ClientHook>&& cap) {
...@@ -2206,7 +2205,7 @@ void PointerBuilder::copyFrom(PointerReader other) { ...@@ -2206,7 +2205,7 @@ void PointerBuilder::copyFrom(PointerReader other) {
} }
PointerReader PointerBuilder::asReader() const { PointerReader PointerBuilder::asReader() const {
return PointerReader(segment, pointer, std::numeric_limits<int>::max()); return PointerReader(segment, pointer, kj::maxValue);
} }
BuilderArena* PointerBuilder::getArena() const { BuilderArena* PointerBuilder::getArena() const {
...@@ -2373,7 +2372,7 @@ void StructBuilder::copyContentFrom(StructReader other) { ...@@ -2373,7 +2372,7 @@ void StructBuilder::copyContentFrom(StructReader other) {
StructReader StructBuilder::asReader() const { StructReader StructBuilder::asReader() const {
return StructReader(segment, data, pointers, return StructReader(segment, data, pointers,
dataSize, pointerCount, bit0Offset, std::numeric_limits<int>::max()); dataSize, pointerCount, bit0Offset, kj::maxValue);
} }
BuilderArena* StructBuilder::getArena() { BuilderArena* StructBuilder::getArena() {
...@@ -2451,7 +2450,7 @@ StructBuilder ListBuilder::getStructElement(ElementCount index) { ...@@ -2451,7 +2450,7 @@ StructBuilder ListBuilder::getStructElement(ElementCount index) {
ListReader ListBuilder::asReader() const { ListReader ListBuilder::asReader() const {
return ListReader(segment, ptr, elementCount, step, structDataSize, structPointerCount, return ListReader(segment, ptr, elementCount, step, structDataSize, structPointerCount,
std::numeric_limits<int>::max()); kj::maxValue);
} }
BuilderArena* ListBuilder::getArena() { BuilderArena* ListBuilder::getArena() {
...@@ -2668,19 +2667,19 @@ Data::Builder OrphanBuilder::asData() { ...@@ -2668,19 +2667,19 @@ Data::Builder OrphanBuilder::asData() {
StructReader OrphanBuilder::asStructReader(StructSize size) const { StructReader OrphanBuilder::asStructReader(StructSize size) const {
KJ_DASSERT(tagAsPtr()->isNull() == (location == nullptr)); KJ_DASSERT(tagAsPtr()->isNull() == (location == nullptr));
return WireHelpers::readStructPointer( return WireHelpers::readStructPointer(
segment, tagAsPtr(), location, nullptr, std::numeric_limits<int>::max()); segment, tagAsPtr(), location, nullptr, kj::maxValue);
} }
ListReader OrphanBuilder::asListReader(FieldSize elementSize) const { ListReader OrphanBuilder::asListReader(FieldSize elementSize) const {
KJ_DASSERT(tagAsPtr()->isNull() == (location == nullptr)); KJ_DASSERT(tagAsPtr()->isNull() == (location == nullptr));
return WireHelpers::readListPointer( return WireHelpers::readListPointer(
segment, tagAsPtr(), location, nullptr, elementSize, std::numeric_limits<int>::max()); segment, tagAsPtr(), location, nullptr, elementSize, kj::maxValue);
} }
kj::Own<const ClientHook> OrphanBuilder::asCapability() const { kj::Own<const ClientHook> OrphanBuilder::asCapability() const {
KJ_DASSERT(tagAsPtr()->isNull() == (location == nullptr)); KJ_DASSERT(tagAsPtr()->isNull() == (location == nullptr));
return WireHelpers::readCapabilityPointer( return WireHelpers::readCapabilityPointer(
segment, tagAsPtr(), location, std::numeric_limits<int>::max()); segment, tagAsPtr(), location, kj::maxValue);
} }
Text::Reader OrphanBuilder::asTextReader() const { Text::Reader OrphanBuilder::asTextReader() const {
......
...@@ -69,7 +69,7 @@ struct ReaderOptions { ...@@ -69,7 +69,7 @@ struct ReaderOptions {
// but probably at least prevents easy exploitation while also avoiding causing problems in most // but probably at least prevents easy exploitation while also avoiding causing problems in most
// typical cases. // typical cases.
uint nestingLimit = 64; int nestingLimit = 64;
// Limits how deeply-nested a message structure can be, e.g. structs containing other structs or // Limits how deeply-nested a message structure can be, e.g. structs containing other structs or
// lists of structs. // lists of structs.
// //
......
...@@ -35,13 +35,13 @@ namespace { ...@@ -35,13 +35,13 @@ namespace {
class TestPipe: public kj::BufferedInputStream, public kj::OutputStream { class TestPipe: public kj::BufferedInputStream, public kj::OutputStream {
public: public:
TestPipe() TestPipe()
: preferredReadSize(std::numeric_limits<size_t>::max()), readPos(0) {} : preferredReadSize(kj::maxValue), readPos(0) {}
explicit TestPipe(size_t preferredReadSize) explicit TestPipe(size_t preferredReadSize)
: preferredReadSize(preferredReadSize), readPos(0) {} : preferredReadSize(preferredReadSize), readPos(0) {}
~TestPipe() {} ~TestPipe() {}
const std::string& getData() { return data; } const std::string& getData() { return data; }
void resetRead(size_t preferredReadSize = std::numeric_limits<size_t>::max()) { void resetRead(size_t preferredReadSize = kj::maxValue) {
readPos = 0; readPos = 0;
this->preferredReadSize = preferredReadSize; this->preferredReadSize = preferredReadSize;
} }
...@@ -50,7 +50,7 @@ public: ...@@ -50,7 +50,7 @@ public:
return readPos == data.size(); return readPos == data.size();
} }
void clear(size_t preferredReadSize = std::numeric_limits<size_t>::max()) { void clear(size_t preferredReadSize = kj::maxValue) {
resetRead(preferredReadSize); resetRead(preferredReadSize);
data.clear(); data.clear();
} }
......
...@@ -67,7 +67,7 @@ private: ...@@ -67,7 +67,7 @@ private:
class TestPipe: public kj::BufferedInputStream, public kj::OutputStream { class TestPipe: public kj::BufferedInputStream, public kj::OutputStream {
public: public:
TestPipe() TestPipe()
: preferredReadSize(std::numeric_limits<size_t>::max()), readPos(0) {} : preferredReadSize(kj::maxValue), readPos(0) {}
explicit TestPipe(size_t preferredReadSize) explicit TestPipe(size_t preferredReadSize)
: preferredReadSize(preferredReadSize), readPos(0) {} : preferredReadSize(preferredReadSize), readPos(0) {}
~TestPipe() {} ~TestPipe() {}
...@@ -76,7 +76,7 @@ public: ...@@ -76,7 +76,7 @@ public:
std::string getUnreadData() { return data.substr(readPos); } std::string getUnreadData() { return data.substr(readPos); }
std::string::size_type getReadPos() { return readPos; } std::string::size_type getReadPos() { return readPos; }
void resetRead(size_t preferredReadSize = std::numeric_limits<size_t>::max()) { void resetRead(size_t preferredReadSize = kj::maxValue) {
readPos = 0; readPos = 0;
this->preferredReadSize = preferredReadSize; this->preferredReadSize = preferredReadSize;
} }
...@@ -85,7 +85,7 @@ public: ...@@ -85,7 +85,7 @@ public:
return readPos == data.size(); return readPos == data.size();
} }
void clear(size_t preferredReadSize = std::numeric_limits<size_t>::max()) { void clear(size_t preferredReadSize = kj::maxValue) {
resetRead(preferredReadSize); resetRead(preferredReadSize);
data.clear(); data.clear();
} }
......
...@@ -103,14 +103,8 @@ void genericInitTestMessage(Builder builder) { ...@@ -103,14 +103,8 @@ void genericInitTestMessage(Builder builder) {
builder.setUInt16List({33333u, 44444u}); builder.setUInt16List({33333u, 44444u});
builder.setUInt32List({3333333333u}); builder.setUInt32List({3333333333u});
builder.setUInt64List({11111111111111111111ull}); builder.setUInt64List({11111111111111111111ull});
builder.setFloat32List({5555.5, builder.setFloat32List({5555.5, kj::inf(), -kj::inf(), kj::nan()});
std::numeric_limits<float>::infinity(), builder.setFloat64List({7777.75, kj::inf(), -kj::inf(), kj::nan()});
-std::numeric_limits<float>::infinity(),
std::numeric_limits<float>::quiet_NaN()});
builder.setFloat64List({7777.75,
std::numeric_limits<double>::infinity(),
-std::numeric_limits<double>::infinity(),
std::numeric_limits<double>::quiet_NaN()});
builder.setTextList({"plugh", "xyzzy", "thud"}); builder.setTextList({"plugh", "xyzzy", "thud"});
builder.setDataList({data("oops"), data("exhausted"), data("rfc3092")}); builder.setDataList({data("oops"), data("exhausted"), data("rfc3092")});
{ {
...@@ -195,14 +189,8 @@ void dynamicInitTestMessage(DynamicStruct::Builder builder) { ...@@ -195,14 +189,8 @@ void dynamicInitTestMessage(DynamicStruct::Builder builder) {
builder.set("uInt16List", {33333u, 44444u}); builder.set("uInt16List", {33333u, 44444u});
builder.set("uInt32List", {3333333333u}); builder.set("uInt32List", {3333333333u});
builder.set("uInt64List", {11111111111111111111ull}); builder.set("uInt64List", {11111111111111111111ull});
builder.set("float32List", {5555.5, builder.set("float32List", {5555.5, kj::inf(), -kj::inf(), kj::nan()});
std::numeric_limits<float>::infinity(), builder.set("float64List", {7777.75, kj::inf(), -kj::inf(), kj::nan()});
-std::numeric_limits<float>::infinity(),
std::numeric_limits<float>::quiet_NaN()});
builder.set("float64List", {7777.75,
std::numeric_limits<double>::infinity(),
-std::numeric_limits<double>::infinity(),
std::numeric_limits<double>::quiet_NaN()});
builder.set("textList", {"plugh", "xyzzy", "thud"}); builder.set("textList", {"plugh", "xyzzy", "thud"});
builder.set("dataList", {data("oops"), data("exhausted"), data("rfc3092")}); builder.set("dataList", {data("oops"), data("exhausted"), data("rfc3092")});
{ {
...@@ -296,16 +284,16 @@ void genericCheckTestMessage(Reader reader) { ...@@ -296,16 +284,16 @@ void genericCheckTestMessage(Reader reader) {
auto listReader = reader.getFloat32List(); auto listReader = reader.getFloat32List();
ASSERT_EQ(4u, listReader.size()); ASSERT_EQ(4u, listReader.size());
EXPECT_EQ(5555.5f, listReader[0]); EXPECT_EQ(5555.5f, listReader[0]);
EXPECT_EQ(std::numeric_limits<float>::infinity(), listReader[1]); EXPECT_EQ(kj::inf(), listReader[1]);
EXPECT_EQ(-std::numeric_limits<float>::infinity(), listReader[2]); EXPECT_EQ(-kj::inf(), listReader[2]);
EXPECT_TRUE(isNaN(listReader[3])); EXPECT_TRUE(isNaN(listReader[3]));
} }
{ {
auto listReader = reader.getFloat64List(); auto listReader = reader.getFloat64List();
ASSERT_EQ(4u, listReader.size()); ASSERT_EQ(4u, listReader.size());
EXPECT_EQ(7777.75, listReader[0]); EXPECT_EQ(7777.75, listReader[0]);
EXPECT_EQ(std::numeric_limits<double>::infinity(), listReader[1]); EXPECT_EQ(kj::inf(), listReader[1]);
EXPECT_EQ(-std::numeric_limits<double>::infinity(), listReader[2]); EXPECT_EQ(-kj::inf(), listReader[2]);
EXPECT_TRUE(isNaN(listReader[3])); EXPECT_TRUE(isNaN(listReader[3]));
} }
checkList(reader.getTextList(), {"plugh", "xyzzy", "thud"}); checkList(reader.getTextList(), {"plugh", "xyzzy", "thud"});
...@@ -420,16 +408,16 @@ void dynamicCheckTestMessage(Reader reader) { ...@@ -420,16 +408,16 @@ void dynamicCheckTestMessage(Reader reader) {
auto listReader = reader.get("float32List").as<DynamicList>(); auto listReader = reader.get("float32List").as<DynamicList>();
ASSERT_EQ(4u, listReader.size()); ASSERT_EQ(4u, listReader.size());
EXPECT_EQ(5555.5f, listReader[0].as<float>()); EXPECT_EQ(5555.5f, listReader[0].as<float>());
EXPECT_EQ(std::numeric_limits<float>::infinity(), listReader[1].as<float>()); EXPECT_EQ(kj::inf(), listReader[1].as<float>());
EXPECT_EQ(-std::numeric_limits<float>::infinity(), listReader[2].as<float>()); EXPECT_EQ(-kj::inf(), listReader[2].as<float>());
EXPECT_TRUE(isNaN(listReader[3].as<float>())); EXPECT_TRUE(isNaN(listReader[3].as<float>()));
} }
{ {
auto listReader = reader.get("float64List").as<DynamicList>(); auto listReader = reader.get("float64List").as<DynamicList>();
ASSERT_EQ(4u, listReader.size()); ASSERT_EQ(4u, listReader.size());
EXPECT_EQ(7777.75, listReader[0].as<double>()); EXPECT_EQ(7777.75, listReader[0].as<double>());
EXPECT_EQ(std::numeric_limits<double>::infinity(), listReader[1].as<double>()); EXPECT_EQ(kj::inf(), listReader[1].as<double>());
EXPECT_EQ(-std::numeric_limits<double>::infinity(), listReader[2].as<double>()); EXPECT_EQ(-kj::inf(), listReader[2].as<double>());
EXPECT_TRUE(isNaN(listReader[3].as<double>())); EXPECT_TRUE(isNaN(listReader[3].as<double>()));
} }
checkList<Text>(reader.get("textList"), {"plugh", "xyzzy", "thud"}); checkList<Text>(reader.get("textList"), {"plugh", "xyzzy", "thud"});
......
...@@ -25,7 +25,6 @@ ...@@ -25,7 +25,6 @@
#include "debug.h" #include "debug.h"
#include <setjmp.h> #include <setjmp.h>
#include <errno.h> #include <errno.h>
#include <limits>
namespace kj { namespace kj {
...@@ -169,7 +168,7 @@ public: ...@@ -169,7 +168,7 @@ public:
} }
} }
void cleanup(uint count = std::numeric_limits<uint>::max()) { void cleanup(uint count = maxValue) {
// Goes through the list (up to a max of `count` items) and removes any that are no longer // Goes through the list (up to a max of `count` items) and removes any that are no longer
// relevant. // relevant.
......
...@@ -262,6 +262,32 @@ TEST(Common, MinMax) { ...@@ -262,6 +262,32 @@ TEST(Common, MinMax) {
EXPECT_EQ(1234567890123456789ll, kj::max('a', 1234567890123456789ll)); EXPECT_EQ(1234567890123456789ll, kj::max('a', 1234567890123456789ll));
} }
TEST(Common, MinMaxValue) {
EXPECT_EQ(0x7f, int8_t(maxValue));
EXPECT_EQ(0xffu, uint8_t(maxValue));
EXPECT_EQ(0x7fff, int16_t(maxValue));
EXPECT_EQ(0xffffu, uint16_t(maxValue));
EXPECT_EQ(0x7fffffff, int32_t(maxValue));
EXPECT_EQ(0xffffffffu, uint32_t(maxValue));
EXPECT_EQ(0x7fffffffffffffffll, int64_t(maxValue));
EXPECT_EQ(0xffffffffffffffffull, uint64_t(maxValue));
EXPECT_EQ(-0x80, int8_t(minValue));
EXPECT_EQ(0, uint8_t(minValue));
EXPECT_EQ(-0x8000, int16_t(minValue));
EXPECT_EQ(0, uint16_t(minValue));
EXPECT_EQ(-0x80000000, int32_t(minValue));
EXPECT_EQ(0, uint32_t(minValue));
EXPECT_EQ(-0x8000000000000000ll, int64_t(minValue));
EXPECT_EQ(0, uint64_t(minValue));
double f = inf();
EXPECT_TRUE(f * 2 == f);
f = nan();
EXPECT_FALSE(f == f);
}
TEST(Common, Defer) { TEST(Common, Defer) {
uint i = 0; uint i = 0;
uint j = 1; uint j = 1;
......
...@@ -369,6 +369,69 @@ inline constexpr size_t size(T&& arr) { return arr.size(); } ...@@ -369,6 +369,69 @@ inline constexpr size_t size(T&& arr) { return arr.size(); }
// Returns the size of the parameter, whether the parameter is a regular C array or a container // Returns the size of the parameter, whether the parameter is a regular C array or a container
// with a `.size()` method. // with a `.size()` method.
class MaxValue_ {
private:
template <typename T>
inline constexpr T maxSigned() const {
return (1ull << (sizeof(T) * 8 - 1)) - 1;
}
template <typename T>
inline constexpr T maxUnsigned() const {
return ~static_cast<T>(0u);
}
public:
#define _kJ_HANDLE_TYPE(T) \
inline constexpr operator signed T() const { return MaxValue_::maxSigned < signed T>(); } \
inline constexpr operator unsigned T() const { return MaxValue_::maxUnsigned<unsigned T>(); }
_kJ_HANDLE_TYPE(char)
_kJ_HANDLE_TYPE(short)
_kJ_HANDLE_TYPE(int)
_kJ_HANDLE_TYPE(long)
_kJ_HANDLE_TYPE(long long)
#undef _kJ_HANDLE_TYPE
};
class MinValue_ {
private:
template <typename T>
inline constexpr T minSigned() const {
return 1ull << (sizeof(T) * 8 - 1);
}
template <typename T>
inline constexpr T minUnsigned() const {
return 0u;
}
public:
#define _kJ_HANDLE_TYPE(T) \
inline constexpr operator signed T() const { return MinValue_::minSigned < signed T>(); } \
inline constexpr operator unsigned T() const { return MinValue_::minUnsigned<unsigned T>(); }
_kJ_HANDLE_TYPE(char)
_kJ_HANDLE_TYPE(short)
_kJ_HANDLE_TYPE(int)
_kJ_HANDLE_TYPE(long)
_kJ_HANDLE_TYPE(long long)
#undef _kJ_HANDLE_TYPE
};
static constexpr MaxValue_ maxValue = MaxValue_();
// A special constant which, when cast to an integer type, takes on the maximum possible value of
// that type. This is useful to use as e.g. a parameter to a function because it will be robust
// in the face of changes to the parameter's type.
//
// `char` is not supported, but `signed char` and `unsigned char` are.
static constexpr MinValue_ minValue = MinValue_();
// A special constant which, when cast to an integer type, takes on the minimum possible value
// of that type. This is useful to use as e.g. a parameter to a function because it will be robust
// in the face of changes to the parameter's type.
//
// `char` is not supported, but `signed char` and `unsigned char` are.
inline double inf() { return 1.0 / 0.0; }
inline double nan() { return 0.0 / 0.0; }
// ======================================================================================= // =======================================================================================
// Useful fake containers // Useful fake containers
......
...@@ -25,7 +25,6 @@ ...@@ -25,7 +25,6 @@
#include "debug.h" #include "debug.h"
#include <stdio.h> #include <stdio.h>
#include <float.h> #include <float.h>
#include <limits>
#include <errno.h> #include <errno.h>
#include <stdlib.h> #include <stdlib.h>
...@@ -217,10 +216,10 @@ char* DoubleToBuffer(double value, char* buffer) { ...@@ -217,10 +216,10 @@ char* DoubleToBuffer(double value, char* buffer) {
// this assert. // this assert.
static_assert(DBL_DIG < 20, "DBL_DIG is too big."); static_assert(DBL_DIG < 20, "DBL_DIG is too big.");
if (value == std::numeric_limits<double>::infinity()) { if (value == inf()) {
strcpy(buffer, "inf"); strcpy(buffer, "inf");
return buffer; return buffer;
} else if (value == -std::numeric_limits<double>::infinity()) { } else if (value == -inf()) {
strcpy(buffer, "-inf"); strcpy(buffer, "-inf");
return buffer; return buffer;
} else if (IsNaN(value)) { } else if (IsNaN(value)) {
...@@ -273,10 +272,10 @@ char* FloatToBuffer(float value, char* buffer) { ...@@ -273,10 +272,10 @@ char* FloatToBuffer(float value, char* buffer) {
// this assert. // this assert.
static_assert(FLT_DIG < 10, "FLT_DIG is too big"); static_assert(FLT_DIG < 10, "FLT_DIG is too big");
if (value == std::numeric_limits<double>::infinity()) { if (value == inf()) {
strcpy(buffer, "inf"); strcpy(buffer, "inf");
return buffer; return buffer;
} else if (value == -std::numeric_limits<double>::infinity()) { } else if (value == -inf()) {
strcpy(buffer, "-inf"); strcpy(buffer, "-inf");
return buffer; return buffer;
} else if (IsNaN(value)) { } else if (IsNaN(value)) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment