some support for Integers v_0
authorFrantišek Kučera <franta-hg@frantovo.cz>
Sat, 26 Jun 2021 20:04:52 +0200
branchv_0
changeset 17 f5281ab3e68f
parent 16 bb457bb5b515
child 18 cb85500c4a30
some support for Integers
src/lib/ASN1ContentHandler.h
src/lib/BasicASN1Reader.h
src/lib/GenericASN1ContentHandler.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 <memory>
 #include <vector>
+#include <sstream>
+#include <iomanip>
+#include <cmath>
 
 namespace relpipe {
 namespace in {
@@ -49,6 +52,62 @@
 		BMPString,
 	};
 
+	class Integer {
+	private:
+		std::vector<uint8_t> data;
+	public:
+
+		/**
+		 * @param data integer octets as in BER encoding
+		 */
+		Integer(std::vector<uint8_t> 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);
 	}
 
--- 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<uint8_t> 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:
--- 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();
 	}