support object identifiers (OID) v_0
authorFrantišek Kučera <franta-hg@frantovo.cz>
Sun, 27 Jun 2021 19:22:23 +0200
branchv_0
changeset 20 fac034e3e867
parent 19 b7431bc6069b
child 21 705036445672
support object identifiers (OID)
src/lib/ASN1ContentHandler.h
src/lib/BasicASN1Reader.h
src/lib/GenericASN1ContentHandler.h
--- a/src/lib/ASN1ContentHandler.h	Sun Jun 27 18:04:34 2021 +0200
+++ b/src/lib/ASN1ContentHandler.h	Sun Jun 27 19:22:23 2021 +0200
@@ -112,8 +112,63 @@
 
 	};
 
+	class ObjectIdentifier {
+	private:
+		// TODO: use std::string (of octets, not ASCII) instead of std::vector?
+		// TODO: use this class across Relational pipes as one of basic types?
+		std::vector<uint8_t> data;
+
+	public:
+
+		/**
+		 * @param data integer octets as in BER encoding
+		 */
+		ObjectIdentifier(std::vector<uint8_t> data) : data(data) {
+			// TODO: cache size and element values?
+		}
+
+		virtual ~ObjectIdentifier() {
+		}
+
+		/**
+		 * @return number of elements, not octets
+		 */
+		size_t size() const {
+			return 0; // FIXME: correct OID size
+		}
+
+		/**
+		 * @param index 0 = root element
+		 * @return value of the element at given position
+		 */
+		const uint8_t& operator[](std::size_t index) const {
+			return data[index]; // FIXME: correct OID value
+		}
+
+		const std::string toString() const {
+			if (data.size() == 0) return "";
+
+			std::stringstream result;
+
+			result << (data[0] / 40) << "." << (data[0] % 40); // first two elements are encoded in the first octet
+
+			for (size_t i = 1, limit = data.size(), octet = 0, element = 0; i < limit; i++) {
+				octet = data[i];
+				element = element << 7 | (octet & 0xFF >> 1);
+				// TODO: throw exception if the element value overflows? (should not happen) or format even longer values
+				if ((octet & 1 << 7) == 0) {
+					result << "." << element;
+					element = 0;
+				}
+			}
+
+			return result.str();
+		}
+
+	};
+
 	virtual ~ASN1ContentHandler() = default;
-	
+
 	// TODO: more metadata, support OID decoding and ASN.1 modules (schema), probably through a plug-in
 
 	virtual void writeStreamStart() = 0;
@@ -125,7 +180,7 @@
 	virtual void writeNull() = 0;
 	virtual void writeInteger(Integer value) = 0;
 	virtual void writeString(StringType type, std::string value) = 0;
-	// virtual void writeOID(std::string value) = 0;
+	virtual void writeOID(ObjectIdentifier value) = 0;
 	// Object descriptor
 	// virtual void writeReal(float value) = 0;
 	// Enumerated
@@ -186,6 +241,11 @@
 		handler->writeString(type, value);
 	}
 
+	void writeOID(ObjectIdentifier value) override {
+		handler->writeOID(value);
+	}
+
+
 #undef handler
 
 };
--- a/src/lib/BasicASN1Reader.h	Sun Jun 27 18:04:34 2021 +0200
+++ b/src/lib/BasicASN1Reader.h	Sun Jun 27 19:22:23 2021 +0200
@@ -157,6 +157,10 @@
 			std::vector<uint8_t> value(typeHeader.length, 0x00);
 			read(value.data(), typeHeader.length);
 			handlers.writeInteger(ASN1ContentHandler::Integer(value));
+		} else if (typeHeader.tag == 6 && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) {
+			std::vector<uint8_t> value(typeHeader.length, 0x00);
+			read(value.data(), typeHeader.length);
+			handlers.writeOID({value});
 		} else if (typeHeader.tag == 12 && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) {
 			// TODO: check available bytes before allocating buffer
 			std::string s;
--- a/src/lib/GenericASN1ContentHandler.h	Sun Jun 27 18:04:34 2021 +0200
+++ b/src/lib/GenericASN1ContentHandler.h	Sun Jun 27 19:22:23 2021 +0200
@@ -83,6 +83,13 @@
 		handlers.writeEndElement();
 	}
 
+	void writeOID(ObjectIdentifier value) override {
+		handlers.writeStartElement("oid");
+		handlers.writeCharacters(value.toString());
+		handlers.writeEndElement();
+	}
+
+
 };
 
 }