src/lib/BasicASN1Reader.h
branchv_0
changeset 14 02725d301010
parent 13 d5e2cb9e31f1
child 15 95ca127ba816
equal deleted inserted replaced
13:d5e2cb9e31f1 14:02725d301010
    17 #pragma once
    17 #pragma once
    18 
    18 
    19 #include <memory>
    19 #include <memory>
    20 #include <vector>
    20 #include <vector>
    21 #include <array>
    21 #include <array>
       
    22 #include <sstream>
    22 
    23 
    23 #include "ASN1Reader.h"
    24 #include "ASN1Reader.h"
    24 
    25 
    25 namespace relpipe {
    26 namespace relpipe {
    26 namespace in {
    27 namespace in {
    54 		uint64_t tag;
    55 		uint64_t tag;
    55 		bool definiteLength;
    56 		bool definiteLength;
    56 		size_t length;
    57 		size_t length;
    57 	};
    58 	};
    58 
    59 
       
    60 	class LevelMetadata {
       
    61 	public:
       
    62 		bool definiteLength;
       
    63 		size_t length;
       
    64 		size_t start;
       
    65 	};
       
    66 
       
    67 	std::vector<LevelMetadata> level;
       
    68 
       
    69 	void checkRemainingItems() {
       
    70 		if (level.size()) {
       
    71 			LevelMetadata& l = level.back();
       
    72 			if (l.definiteLength && l.length == getBytesRead() - l.start) {
       
    73 				level.pop_back();
       
    74 				handlers.writeCollectionEnd();
       
    75 			}
       
    76 		}
       
    77 	}
       
    78 
    59 	Header readHeader() {
    79 	Header readHeader() {
    60 		Header h;
    80 		Header h;
    61 
    81 
    62 		memset(&h, 0, sizeof (h)); // TODO: remove, not needed
    82 		memset(&h, 0, sizeof (h)); // TODO: remove, not needed
    63 
    83 
    70 		if (h.tag > 30) throw relpipe::writer::RelpipeWriterException(L"not yet implemented, ASN.1 tag > 30"); // FIXME: higher tag values → read more bytes
    90 		if (h.tag > 30) throw relpipe::writer::RelpipeWriterException(L"not yet implemented, ASN.1 tag > 30"); // FIXME: higher tag values → read more bytes
    71 
    91 
    72 		uint8_t lengthByte;
    92 		uint8_t lengthByte;
    73 		read(&lengthByte, 1);
    93 		read(&lengthByte, 1);
    74 
    94 
    75 		std::wcerr << L"lengthByte = " << lengthByte << std::endl;
       
    76 
       
    77 		if (lengthByte >> 7 == 0) {
    95 		if (lengthByte >> 7 == 0) {
       
    96 			// definite short
    78 			h.definiteLength = true;
    97 			h.definiteLength = true;
    79 			h.length = lengthByte;
    98 			h.length = lengthByte;
    80 		} else if (lengthByte == 0b10000000) {
    99 		} else if (lengthByte == 0b10000000) {
       
   100 			// indefinite
    81 			h.definiteLength = false;
   101 			h.definiteLength = false;
    82 			h.length = 0;
   102 			h.length = 0;
    83 		} else if (lengthByte == 0xFF) {
   103 		} else if (lengthByte == 0xFF) {
    84 			throw relpipe::writer::RelpipeWriterException(L"ASN.1 lengthByte == 0xFF (reserved value)"); // TODO: better exception
   104 			throw relpipe::writer::RelpipeWriterException(L"ASN.1 lengthByte == 0xFF (reserved value)"); // TODO: better exception
    85 		} else {
   105 		} else {
    86 			// FIXME: longer values
   106 			// definite long
    87 			throw relpipe::writer::RelpipeWriterException(L"not yet implemented, ASN.1 lengthBytes: longer value"); // TODO: better exception
   107 			h.definiteLength = true;
    88 		}
   108 			h.length = 0;
    89 		
   109 			std::vector<uint8_t> lengthBytes(lengthByte & 0b01111111, 0);
       
   110 			read(lengthBytes.data(), lengthBytes.size());
       
   111 			for (uint8_t l : lengthBytes) h.length = (h.length << 8) + l;
       
   112 		}
       
   113 
    90 		return h;
   114 		return h;
    91 	}
   115 	}
    92 
   116 
    93 	void readNext() {
   117 	void readNext() {
       
   118 		checkRemainingItems();
    94 		Header typeHeader = readHeader();
   119 		Header typeHeader = readHeader();
    95 		commit();
   120 		// commit(); // TODO: commit here and recover later instead of rollback?
    96 
   121 
    97 		if (!started) {
   122 		if (!started) {
    98 			handlers.writeStreamStart();
   123 			handlers.writeStreamStart();
    99 			started = true;
   124 			started = true;
   100 		}
   125 		}
   101 
   126 		
       
   127 		// TODO: check tagClass and pc
       
   128 
       
   129 		// TODO: constants, more types
       
   130 		if (typeHeader.tag == 0) handlers.writeCollectionEnd();
       
   131 		else if (typeHeader.tag == 16) {
       
   132 			level.push_back({typeHeader.definiteLength, typeHeader.length, getBytesRead()}); // TODO: transaction
       
   133 			handlers.writeCollectionStart(ASN1ContentHandler::CollectionType::Sequence);
       
   134 		} else if (typeHeader.tag == 17) {
       
   135 			level.push_back({typeHeader.definiteLength, typeHeader.length, getBytesRead()}); // TODO: transaction
       
   136 			handlers.writeCollectionStart(ASN1ContentHandler::CollectionType::Set);
       
   137 		} else if (typeHeader.tag == 5 && typeHeader.length == 0) {
       
   138 			handlers.writeNull();
       
   139 		} else if (typeHeader.tag == 1) {
       
   140 			bool value;
       
   141 			read((uint8_t*) & value, 1);
       
   142 			handlers.writeBoolean(value);
       
   143 		} else {
       
   144 			// TODO: do not skip, parse
       
   145 			std::vector<uint8_t> temp(typeHeader.length, 0);
       
   146 			read(temp.data(), typeHeader.length);
       
   147 			// TODO: recover transaction?
       
   148 
       
   149 			std::stringstream description;
       
   150 			description << "value:"
       
   151 					<< " tag = " << typeHeader.tag
       
   152 					<< " tagClass = " << (int) typeHeader.tagClass
       
   153 					<< " pc = " << (int) typeHeader.pc
       
   154 					<< " length = " << typeHeader.length
       
   155 					<< " definite = " << (typeHeader.definiteLength ? "true" : "false");
       
   156 
       
   157 			handlers.writeString(ASN1ContentHandler::StringType::UTF8String, description.str());
       
   158 		}
       
   159 
       
   160 		commit();
       
   161 
       
   162 
       
   163 		// TODO: remove debug/demo output:
       
   164 		return;
   102 		handlers.writeCollectionStart(ASN1ContentHandler::CollectionType::Sequence);
   165 		handlers.writeCollectionStart(ASN1ContentHandler::CollectionType::Sequence);
   103 		handlers.writeNull();
   166 		handlers.writeNull();
   104 		handlers.writeBoolean(true);
   167 		handlers.writeBoolean(true);
   105 
   168 
   106 		handlers.writeString(ASN1ContentHandler::StringType::UTF8String, "tagClass:");
   169 		handlers.writeString(ASN1ContentHandler::StringType::UTF8String, "tagClass:");
   125 	}
   188 	}
   126 
   189 
   127 public:
   190 public:
   128 
   191 
   129 	void close() override {
   192 	void close() override {
   130 		if (started) handlers.writeStreamEnd();
   193 		// TODO: check the bytes remaining in the buffer
       
   194 		//if (started) handlers.writeStreamEnd();
   131 	}
   195 	}
   132 
   196 
   133 };
   197 };
   134 
   198 
   135 }
   199 }