src/lib/ASN1ContentHandler.h
branchv_0
changeset 17 f5281ab3e68f
parent 16 bb457bb5b515
child 18 cb85500c4a30
--- 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);
 	}