# HG changeset patch # User František Kučera # Date 1624730692 -7200 # Node ID f5281ab3e68f14891f2d3b2e5a1a14eac7b16dac # Parent bb457bb5b515bfd2bd8e4cec6e55f7fb138e88f8 some support for Integers diff -r bb457bb5b515 -r f5281ab3e68f src/lib/ASN1ContentHandler.h --- a/src/lib/ASN1ContentHandler.h Tue Jun 22 21:41:59 2021 +0200 +++ b/src/lib/ASN1ContentHandler.h Sat Jun 26 20:04:52 2021 +0200 @@ -18,6 +18,9 @@ #include #include +#include +#include +#include namespace relpipe { namespace in { @@ -49,6 +52,62 @@ BMPString, }; + class Integer { + private: + std::vector data; + public: + + /** + * @param data integer octets as in BER encoding + */ + Integer(std::vector data) : data(data) { + } + + virtual ~Integer() { + } + + size_t size() const { + return data.size(); + } + + const uint8_t& operator[](std::size_t index) const { + return data[index]; + } + + const std::string toHex() const { + std::stringstream hex; + hex << std::hex << std::setfill('0'); + for (uint8_t b : data) hex << std::setw(2) << (int) b; + return hex.str(); + } + + const std::string toString() const { + try { + return std::to_string(toInt64()); + } catch (...) { + // TODO: support longer values than 64 bits + // integer has more than 64 bits → only HEX form value will be available + return ""; + } + } + + const int64_t toInt64() const { + int64_t value = 0; + + if (data.size() > sizeof (value)) throw std::invalid_argument("integer is too long"); + + for (size_t i = 0, limit = data.size(), negative = 0; i < limit; i++) { + uint8_t b = data[i]; + if (i == 0 && b & 0x80) negative = true; + value = (value << 8) | b; + if (i == (limit - 1) && negative) value -= std::pow(256, data.size()); + } + + return value; + } + + }; + virtual ~ASN1ContentHandler() = default; virtual void writeStreamStart() = 0; @@ -58,7 +117,7 @@ virtual void writeCollectionEnd() = 0; virtual void writeBoolean(bool value) = 0; virtual void writeNull() = 0; - virtual void writeInteger(int64_t value) = 0; + virtual void writeInteger(Integer value) = 0; virtual void writeString(StringType type, std::string value) = 0; // virtual void writeOID(std::string value) = 0; // Object descriptor @@ -113,7 +172,7 @@ handler->writeNull(); } - void writeInteger(int64_t value) override { // TODO: Integer class containing raw data + methods for converting them to particular numeric data types + void writeInteger(Integer value) override { handler->writeInteger(value); } diff -r bb457bb5b515 -r f5281ab3e68f src/lib/BasicASN1Reader.h --- a/src/lib/BasicASN1Reader.h Tue Jun 22 21:41:59 2021 +0200 +++ b/src/lib/BasicASN1Reader.h Sat Jun 26 20:04:52 2021 +0200 @@ -145,13 +145,20 @@ bool value; read((uint8_t*) & value, 1); handlers.writeBoolean(value); - } else if (typeHeader.tag == 12 && typeHeader.tagClass == TagClass::Universal) { + } else if (typeHeader.tag == 2 && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) { + // TODO: check available bytes before allocating buffer + std::vector value(typeHeader.length, 0x00); + read(value.data(), typeHeader.length); + handlers.writeInteger(ASN1ContentHandler::Integer(value)); + } else if (typeHeader.tag == 12 && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) { + // TODO: check available bytes before allocating buffer std::string s; s.resize(typeHeader.length); read((uint8_t*) s.data(), typeHeader.length); handlers.writeString(ASN1ContentHandler::StringType::UTF8String, s); - } else if (typeHeader.tag == 19 && typeHeader.tagClass == TagClass::Universal) { + } else if (typeHeader.tag == 19 && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) { // TODO: check encoding + // TODO: check available bytes before allocating buffer std::string s; s.resize(typeHeader.length); read((uint8_t*) s.data(), typeHeader.length); @@ -174,27 +181,6 @@ } commit(); - - - // TODO: remove debug/demo output: - return; - handlers.writeCollectionStart(ASN1ContentHandler::CollectionType::Sequence); - handlers.writeNull(); - handlers.writeBoolean(true); - - handlers.writeString(ASN1ContentHandler::StringType::UTF8String, "tagClass:"); - handlers.writeInteger((int64_t) typeHeader.tagClass); - handlers.writeString(ASN1ContentHandler::StringType::UTF8String, "pc:"); - handlers.writeInteger((int64_t) typeHeader.pc); - handlers.writeString(ASN1ContentHandler::StringType::UTF8String, "tag:"); - handlers.writeInteger((int64_t) typeHeader.tag); - handlers.writeString(ASN1ContentHandler::StringType::UTF8String, "definiteLength:"); - handlers.writeBoolean(typeHeader.definiteLength); - handlers.writeString(ASN1ContentHandler::StringType::UTF8String, "length:"); - handlers.writeInteger((int64_t) typeHeader.length); - - handlers.writeString(ASN1ContentHandler::StringType::UTF8String, "relational pipes"); - handlers.writeCollectionEnd(); } protected: diff -r bb457bb5b515 -r f5281ab3e68f src/lib/GenericASN1ContentHandler.h --- a/src/lib/GenericASN1ContentHandler.h Tue Jun 22 21:41:59 2021 +0200 +++ b/src/lib/GenericASN1ContentHandler.h Sat Jun 26 20:04:52 2021 +0200 @@ -71,9 +71,9 @@ handlers.writeEndElement(); } - void writeInteger(int64_t value) override { - handlers.writeStartElement("integer"); - handlers.writeCharacters(std::to_string(value)); + void writeInteger(Integer value) override { + handlers.writeStartElement("integer",{"hex", value.toHex()}); + handlers.writeCharacters(value.toString()); handlers.writeEndElement(); }