From 1662d2f186a9e7fa53ae7be620be620a77453ae6 Mon Sep 17 00:00:00 2001 From: Justin King Date: Mon, 25 Oct 2021 09:07:43 -0700 Subject: [PATCH] [C++] Refactor Guid to use std::array instead of std::vector --- contributors.txt | 2 + runtime/Cpp/runtime/src/antlr4-common.h | 2 +- runtime/Cpp/runtime/src/antlr4-runtime.h | 2 +- .../Cpp/runtime/src/atn/ATNDeserializer.cpp | 30 ++-- runtime/Cpp/runtime/src/atn/ATNDeserializer.h | 16 +- runtime/Cpp/runtime/src/atn/ATNSerializer.cpp | 6 +- runtime/Cpp/runtime/src/atn/ATNSerializer.h | 2 +- .../src/support/{guid.cpp => Guid.cpp} | 143 +++++++----------- .../runtime/src/support/{guid.h => Guid.h} | 90 ++++++++--- 9 files changed, 152 insertions(+), 141 deletions(-) rename runtime/Cpp/runtime/src/support/{guid.cpp => Guid.cpp} (70%) rename runtime/Cpp/runtime/src/support/{guid.h => Guid.h} (57%) diff --git a/contributors.txt b/contributors.txt index 673b73444f..e8eb5dd2a2 100644 --- a/contributors.txt +++ b/contributors.txt @@ -315,3 +315,5 @@ YYYY/MM/DD, github id, Full name, email 2021/08/08, ansiemens, Yi-Hong Lin, ansiemens@gmail.com 2021/09/08, jmcken8, Joel McKenzie, joel.b.mckenzie@gmail.com 2021/10/10, tools4origins, Erwan Guyomarc'h, contact@erwan-guyomarch.fr +2021/10/25, jcking, Justin King, jcking@google.com + diff --git a/runtime/Cpp/runtime/src/antlr4-common.h b/runtime/Cpp/runtime/src/antlr4-common.h index 020c6a560c..b2d6ab4a2b 100644 --- a/runtime/Cpp/runtime/src/antlr4-common.h +++ b/runtime/Cpp/runtime/src/antlr4-common.h @@ -107,7 +107,7 @@ #endif #endif -#include "support/guid.h" +#include "support/Guid.h" #include "support/Declarations.h" #if !defined(HAS_NOEXCEPT) diff --git a/runtime/Cpp/runtime/src/antlr4-runtime.h b/runtime/Cpp/runtime/src/antlr4-runtime.h index d58e4591e9..7f78f69870 100644 --- a/runtime/Cpp/runtime/src/antlr4-runtime.h +++ b/runtime/Cpp/runtime/src/antlr4-runtime.h @@ -133,7 +133,7 @@ #include "support/BitSet.h" #include "support/CPPUtils.h" #include "support/StringUtils.h" -#include "support/guid.h" +#include "support/Guid.h" #include "tree/AbstractParseTreeVisitor.h" #include "tree/ErrorNode.h" #include "tree/ErrorNodeImpl.h" diff --git a/runtime/Cpp/runtime/src/atn/ATNDeserializer.cpp b/runtime/Cpp/runtime/src/atn/ATNDeserializer.cpp index d1d622aebb..00d745d0b4 100755 --- a/runtime/Cpp/runtime/src/atn/ATNDeserializer.cpp +++ b/runtime/Cpp/runtime/src/atn/ATNDeserializer.cpp @@ -115,32 +115,32 @@ ATNDeserializer::~ATNDeserializer() { * This value should never change. Updates following this version are * reflected as change in the unique ID SERIALIZED_UUID. */ -Guid ATNDeserializer::ADDED_PRECEDENCE_TRANSITIONS() { - return Guid("1DA0C57D-6C06-438A-9B27-10BCB3CE0F61"); +antlrcpp::Guid ATNDeserializer::ADDED_PRECEDENCE_TRANSITIONS() { + return antlrcpp::Guid("1DA0C57D-6C06-438A-9B27-10BCB3CE0F61"); } -Guid ATNDeserializer::ADDED_LEXER_ACTIONS() { - return Guid("AADB8D7E-AEEF-4415-AD2B-8204D6CF042E"); +antlrcpp::Guid ATNDeserializer::ADDED_LEXER_ACTIONS() { + return antlrcpp::Guid("AADB8D7E-AEEF-4415-AD2B-8204D6CF042E"); } -Guid ATNDeserializer::ADDED_UNICODE_SMP() { - return Guid("59627784-3BE5-417A-B9EB-8131A7286089"); +antlrcpp::Guid ATNDeserializer::ADDED_UNICODE_SMP() { + return antlrcpp::Guid("59627784-3BE5-417A-B9EB-8131A7286089"); } -Guid ATNDeserializer::SERIALIZED_UUID() { +antlrcpp::Guid ATNDeserializer::SERIALIZED_UUID() { return ADDED_UNICODE_SMP(); } -Guid ATNDeserializer::BASE_SERIALIZED_UUID() { - return Guid("33761B2D-78BB-4A43-8B0B-4F5BEE8AACF3"); +antlrcpp::Guid ATNDeserializer::BASE_SERIALIZED_UUID() { + return antlrcpp::Guid("33761B2D-78BB-4A43-8B0B-4F5BEE8AACF3"); } -std::vector& ATNDeserializer::SUPPORTED_UUIDS() { - static std::vector singleton = { BASE_SERIALIZED_UUID(), ADDED_PRECEDENCE_TRANSITIONS(), ADDED_LEXER_ACTIONS(), ADDED_UNICODE_SMP() }; +std::vector& ATNDeserializer::SUPPORTED_UUIDS() { + static std::vector singleton = { BASE_SERIALIZED_UUID(), ADDED_PRECEDENCE_TRANSITIONS(), ADDED_LEXER_ACTIONS(), ADDED_UNICODE_SMP() }; return singleton; } -bool ATNDeserializer::isFeatureSupported(const Guid &feature, const Guid &actualUuid) { +bool ATNDeserializer::isFeatureSupported(const antlrcpp::Guid &feature, const antlrcpp::Guid &actualUuid) { auto featureIterator = std::find(SUPPORTED_UUIDS().begin(), SUPPORTED_UUIDS().end(), feature); if (featureIterator == SUPPORTED_UUIDS().end()) { return false; @@ -169,7 +169,7 @@ ATN ATNDeserializer::deserialize(const std::vector& input) { throw UnsupportedOperationException(reason); } - Guid uuid = toUUID(data.data(), p); + antlrcpp::Guid uuid = toUUID(data.data(), p); p += 8; auto uuidIterator = std::find(SUPPORTED_UUIDS().begin(), SUPPORTED_UUIDS().end(), uuid); if (uuidIterator == SUPPORTED_UUIDS().end()) { @@ -628,8 +628,8 @@ void ATNDeserializer::checkCondition(bool condition, const std::string &message) } } -Guid ATNDeserializer::toUUID(const unsigned short *data, size_t offset) { - return Guid((uint16_t *)data + offset, true); +antlrcpp::Guid ATNDeserializer::toUUID(const unsigned short *data, size_t offset) { + return antlrcpp::Guid((uint16_t *)data + offset, true); } /* mem check: all created instances are freed in the d-tor of the ATNState they are added to. */ diff --git a/runtime/Cpp/runtime/src/atn/ATNDeserializer.h b/runtime/Cpp/runtime/src/atn/ATNDeserializer.h index 12fd11d8ce..57b6c7b285 100755 --- a/runtime/Cpp/runtime/src/atn/ATNDeserializer.h +++ b/runtime/Cpp/runtime/src/atn/ATNDeserializer.h @@ -23,13 +23,13 @@ namespace atn { /// This is the current serialized UUID. // ml: defined as function to avoid the “static initialization order fiasco”. - static Guid SERIALIZED_UUID(); + static antlrcpp::Guid SERIALIZED_UUID(); ATNDeserializer(); ATNDeserializer(const ATNDeserializationOptions& dso); virtual ~ATNDeserializer(); - static Guid toUUID(const unsigned short *data, size_t offset); + static antlrcpp::Guid toUUID(const unsigned short *data, size_t offset); virtual ATN deserialize(const std::vector &input); virtual void verifyATN(const ATN &atn); @@ -54,35 +54,35 @@ namespace atn { /// {@code true} if the {@code actualUuid} value represents a /// serialized ATN at or after the feature identified by {@code feature} was /// introduced; otherwise, {@code false}. - virtual bool isFeatureSupported(const Guid &feature, const Guid &actualUuid); + virtual bool isFeatureSupported(const antlrcpp::Guid &feature, const antlrcpp::Guid &actualUuid); void markPrecedenceDecisions(const ATN &atn); Ref lexerActionFactory(LexerActionType type, int data1, int data2); private: /// This is the earliest supported serialized UUID. - static Guid BASE_SERIALIZED_UUID(); + static antlrcpp::Guid BASE_SERIALIZED_UUID(); /// This UUID indicates an extension of for the /// addition of precedence predicates. - static Guid ADDED_PRECEDENCE_TRANSITIONS(); + static antlrcpp::Guid ADDED_PRECEDENCE_TRANSITIONS(); /** * This UUID indicates an extension of ADDED_PRECEDENCE_TRANSITIONS * for the addition of lexer actions encoded as a sequence of * LexerAction instances. */ - static Guid ADDED_LEXER_ACTIONS(); + static antlrcpp::Guid ADDED_LEXER_ACTIONS(); /** * This UUID indicates the serialized ATN contains two sets of * IntervalSets, where the second set's values are encoded as * 32-bit integers to support the full Unicode SMP range up to U+10FFFF. */ - static Guid ADDED_UNICODE_SMP(); + static antlrcpp::Guid ADDED_UNICODE_SMP(); /// This list contains all of the currently supported UUIDs, ordered by when /// the feature first appeared in this branch. - static std::vector& SUPPORTED_UUIDS(); + static std::vector& SUPPORTED_UUIDS(); ATNDeserializationOptions deserializationOptions; }; diff --git a/runtime/Cpp/runtime/src/atn/ATNSerializer.cpp b/runtime/Cpp/runtime/src/atn/ATNSerializer.cpp index 293bee5e9d..c680d7be87 100755 --- a/runtime/Cpp/runtime/src/atn/ATNSerializer.cpp +++ b/runtime/Cpp/runtime/src/atn/ATNSerializer.cpp @@ -390,7 +390,7 @@ std::string ATNSerializer::decode(const std::wstring &inpdata) { throw UnsupportedOperationException("ATN Serializer" + reason); } - Guid uuid = ATNDeserializer::toUUID(data.data(), p); + antlrcpp::Guid uuid = ATNDeserializer::toUUID(data.data(), p); p += 8; if (uuid != ATNDeserializer::SERIALIZED_UUID()) { std::string reason = "Could not deserialize ATN with UUID " + uuid.toString() + " (expected " + @@ -602,10 +602,10 @@ std::string ATNSerializer::getDecoded(ATN *atn, std::vector &tokenN return ATNSerializer(atn, tokenNames).decode(serialized); } -void ATNSerializer::serializeUUID(std::vector &data, Guid uuid) { +void ATNSerializer::serializeUUID(std::vector &data, antlrcpp::Guid uuid) { unsigned int twoBytes = 0; bool firstByte = true; - for( std::vector::const_reverse_iterator rit = uuid.rbegin(); rit != uuid.rend(); ++rit ) + for(antlrcpp::Guid::const_reverse_iterator rit = uuid.rbegin(); rit != uuid.rend(); ++rit ) { if (firstByte) { twoBytes = *rit; diff --git a/runtime/Cpp/runtime/src/atn/ATNSerializer.h b/runtime/Cpp/runtime/src/atn/ATNSerializer.h index a6d1d6976f..d222ebb593 100755 --- a/runtime/Cpp/runtime/src/atn/ATNSerializer.h +++ b/runtime/Cpp/runtime/src/atn/ATNSerializer.h @@ -54,7 +54,7 @@ namespace atn { private: std::vector _tokenNames; - void serializeUUID(std::vector &data, Guid uuid); + void serializeUUID(std::vector &data, antlrcpp::Guid uuid); }; } // namespace atn diff --git a/runtime/Cpp/runtime/src/support/guid.cpp b/runtime/Cpp/runtime/src/support/Guid.cpp similarity index 70% rename from runtime/Cpp/runtime/src/support/guid.cpp rename to runtime/Cpp/runtime/src/support/Guid.cpp index b6105d70c6..76a78851f7 100755 --- a/runtime/Cpp/runtime/src/support/guid.cpp +++ b/runtime/Cpp/runtime/src/support/Guid.cpp @@ -22,7 +22,9 @@ THE SOFTWARE. */ -#include "guid.h" +#include + +#include "Guid.h" #ifdef GUID_LIBUUID #include @@ -40,93 +42,90 @@ #include #endif -using namespace std; +namespace antlrcpp { // overload << so that it's easy to convert to a string -ostream &operator<<(ostream &s, const Guid &guid) -{ - return s << hex << setfill('0') - << setw(2) << (int)guid._bytes[0] - << setw(2) << (int)guid._bytes[1] - << setw(2) << (int)guid._bytes[2] - << setw(2) << (int)guid._bytes[3] - << "-" - << setw(2) << (int)guid._bytes[4] - << setw(2) << (int)guid._bytes[5] - << "-" - << setw(2) << (int)guid._bytes[6] - << setw(2) << (int)guid._bytes[7] - << "-" - << setw(2) << (int)guid._bytes[8] - << setw(2) << (int)guid._bytes[9] - << "-" - << setw(2) << (int)guid._bytes[10] - << setw(2) << (int)guid._bytes[11] - << setw(2) << (int)guid._bytes[12] - << setw(2) << (int)guid._bytes[13] - << setw(2) << (int)guid._bytes[14] - << setw(2) << (int)guid._bytes[15]; +std::ostream &operator<<(std::ostream &s, const Guid &guid) { + return s << std::hex << std::setfill('0') + << std::setw(2) << static_cast(guid.bytes_[0]) + << std::setw(2) << static_cast(guid.bytes_[1]) + << std::setw(2) << static_cast(guid.bytes_[2]) + << std::setw(2) << static_cast(guid.bytes_[3]) + << "-" + << std::setw(2) << static_cast(guid.bytes_[4]) + << std::setw(2) << static_cast(guid.bytes_[5]) + << "-" + << std::setw(2) << static_cast(guid.bytes_[6]) + << std::setw(2) << static_cast(guid.bytes_[7]) + << "-" + << std::setw(2) << static_cast(guid.bytes_[8]) + << std::setw(2) << static_cast(guid.bytes_[9]) + << "-" + << std::setw(2) << static_cast(guid.bytes_[10]) + << std::setw(2) << static_cast(guid.bytes_[11]) + << std::setw(2) << static_cast(guid.bytes_[12]) + << std::setw(2) << static_cast(guid.bytes_[13]) + << std::setw(2) << static_cast(guid.bytes_[14]) + << std::setw(2) << static_cast(guid.bytes_[15]); } // create a guid from vector of bytes -Guid::Guid(const vector &bytes) -{ - _bytes = bytes; +Guid::Guid(const std::vector &bytes) { + std::memcpy(bytes_.data(), bytes.data(), std::min(bytes.size(), bytes_.size())); } +Guid::Guid(const std::array &bytes) : bytes_(bytes) {} + // create a guid from array of bytes -Guid::Guid(const unsigned char *bytes) -{ - _bytes.assign(bytes, bytes + 16); +Guid::Guid(const uint8_t *bytes) { + std::memcpy(bytes_.data(), bytes, 16); } // create a guid from array of words -Guid::Guid(const uint16_t *bytes, bool reverse) -{ +Guid::Guid(const uint16_t *bytes, bool reverse) { + size_t j = 0; if (reverse) { - for (size_t i = 8; i > 0; --i) - { - _bytes.push_back(bytes[i - 1] >> 8); - _bytes.push_back(bytes[i - 1] & 0xFF); + for (size_t i = 8; i > 0; --i) { + bytes_[j++] = static_cast(bytes[i - 1] >> 8); + bytes_[j++] = static_cast(bytes[i - 1] & 0xFF); } } else { - for (size_t i = 0; i < 8; ++i) - { - _bytes.push_back(bytes[i] & 0xFF); - _bytes.push_back(bytes[i] >> 8); + for (size_t i = 0; i < 8; ++i) { + bytes_[j++] = static_cast(bytes[i] & 0xFF); + bytes_[j++] = static_cast(bytes[i] >> 8); } } } +namespace { + // converts a single hex char to a number (0 - 15) -static unsigned char hexDigitToChar(char ch) -{ +uint8_t hexDigitToChar(char ch) { if (ch > 47 && ch < 58) - return (unsigned char)(ch - 48); + return (uint8_t)(ch - 48); if (ch > 96 && ch < 103) - return (unsigned char)(ch - 87); + return (uint8_t)(ch - 87); if (ch > 64 && ch < 71) - return (unsigned char)(ch - 55); + return (uint8_t)(ch - 55); return 0; } // converts the two hexadecimal characters to an unsigned char (a byte) -static unsigned char hexPairToChar(char a, char b) -{ +uint8_t hexPairToChar(char a, char b) { return hexDigitToChar(a) * 16 + hexDigitToChar(b); } -// create a guid from string -Guid::Guid(const string &fromString) -{ - _bytes.clear(); +} +// create a guid from string +Guid::Guid(const std::string &fromString) { char charOne = 0, charTwo; bool lookingForFirstChar = true; + size_t i = 0; for (const char &ch : fromString) { if (ch == '-') @@ -140,47 +139,13 @@ Guid::Guid(const string &fromString) else { charTwo = ch; - auto byte = hexPairToChar(charOne, charTwo); - _bytes.push_back(byte); + bytes_[i++] = hexPairToChar(charOne, charTwo); lookingForFirstChar = true; } } - -} - -// create empty guid -Guid::Guid() -{ - _bytes = vector(16, 0); -} - -// copy constructor -Guid::Guid(const Guid &other) -{ - _bytes = other._bytes; } -// overload assignment operator -Guid &Guid::operator=(const Guid &other) -{ - _bytes = other._bytes; - return *this; -} - -// overload equality operator -bool Guid::operator==(const Guid &other) const -{ - return _bytes == other._bytes; -} - -// overload inequality operator -bool Guid::operator!=(const Guid &other) const -{ - return !((*this) == other); -} - -const std::string Guid::toString() const -{ +std::string Guid::toString() const { std::stringstream os; os << *this; return os.str(); @@ -301,3 +266,5 @@ Guid GuidGenerator::newGuid() return bytes; } #endif + +} diff --git a/runtime/Cpp/runtime/src/support/guid.h b/runtime/Cpp/runtime/src/support/Guid.h similarity index 57% rename from runtime/Cpp/runtime/src/support/guid.h rename to runtime/Cpp/runtime/src/support/Guid.h index b412497790..3efc686891 100755 --- a/runtime/Cpp/runtime/src/support/guid.h +++ b/runtime/Cpp/runtime/src/support/Guid.h @@ -23,30 +23,42 @@ */ #pragma once +#include +#include +#include +#include #include -#include #include #include -#include -#include +#include #ifdef GUID_ANDROID #include #endif +namespace antlrcpp { + // Class to represent a GUID/UUID. Each instance acts as a wrapper around a // 16 byte value that can be passed around by value. It also supports // conversion to string (via the stream operator <<) and conversion from a // string via constructor. -class Guid -{ +class Guid final { public: + using size_type = typename std::array::size_type; + using pointer = typename std::array::pointer; + using const_pointer = typename std::array::const_pointer; + using iterator = typename std::array::iterator; + using reverse_iterator = typename std::array::reverse_iterator; + using const_iterator = typename std::array::const_iterator; + using const_reverse_iterator = typename std::array::const_reverse_iterator; // create a guid from vector of bytes - Guid(const std::vector &bytes); + Guid(const std::vector &bytes); + + explicit Guid(const std::array &bytes); // create a guid from array of bytes - Guid(const unsigned char *bytes); + Guid(const uint8_t *bytes); // Create a guid from array of words. Guid(const uint16_t *bytes, bool reverse); @@ -55,32 +67,61 @@ class Guid Guid(const std::string &fromString); // create empty guid - Guid(); + Guid() = default; // copy constructor - Guid(const Guid &other); + Guid(const Guid &other) = default; // overload assignment operator - Guid &operator=(const Guid &other); + Guid &operator=(const Guid &other) = default; // overload equality and inequality operator - bool operator==(const Guid &other) const; - bool operator!=(const Guid &other) const; + friend bool operator==(const Guid &lhs, const Guid &rhs) { + return std::memcmp(lhs.data(), rhs.data(), 16) == 0; + } + + friend bool operator!=(const Guid &lhs, const Guid &rhs) { + return !operator==(lhs, rhs); + } - const std::string toString() const; - std::vector::const_iterator begin() { return _bytes.begin(); } - std::vector::const_iterator end() { return _bytes.end(); } - std::vector::const_reverse_iterator rbegin() { return _bytes.rbegin(); } - std::vector::const_reverse_iterator rend() { return _bytes.rend(); } + // make the << operator a friend so it can access bytes_ + friend std::ostream &operator<<(std::ostream &s, const Guid &guid); + pointer data() { return bytes_.data(); } -private: + const_pointer data() const { return bytes_.data(); } - // actual data - std::vector _bytes; + size_type size() const { return bytes_.size(); } - // make the << operator a friend so it can access _bytes - friend std::ostream &operator<<(std::ostream &s, const Guid &guid); + std::string toString() const; + + iterator begin() { return bytes_.begin(); } + + iterator end() { return bytes_.end(); } + + reverse_iterator rbegin() { return bytes_.rbegin(); } + + reverse_iterator rend() { return bytes_.rend(); } + + const_iterator cbegin() const { return bytes_.begin(); } + + const_iterator cend() const { return bytes_.end(); } + + const_reverse_iterator crbegin() const { return bytes_.rbegin(); } + + const_reverse_iterator crend() const { return bytes_.rend(); } + + const_iterator begin() const { return bytes_.begin(); } + + const_iterator end() const { return bytes_.end(); } + + const_reverse_iterator rbegin() const { return bytes_.rbegin(); } + + const_reverse_iterator rend() const { return bytes_.rend(); } + +private: + // actual data + std::array bytes_; }; // Class that can create new guids. The only reason this exists instead of @@ -90,8 +131,7 @@ class Guid // function would no longer be cross-platform if we parameterized the android // version. Instead, construction of the GuidGenerator may be different on // each platform, but the use of newGuid is uniform. -class GuidGenerator -{ +class GuidGenerator final { public: #ifdef GUID_ANDROID GuidGenerator(JNIEnv *env); @@ -110,3 +150,5 @@ class GuidGenerator jmethodID _leastSignificantBitsMethod; #endif }; + +}