src/ASN1Writer.h
author František Kučera <franta-hg@frantovo.cz>
Sat, 30 Mar 2019 01:51:54 +0100
branchv_0
changeset 2 d1b39a9bd591
parent 1 e9b4f3a9e436
child 7 c155b441306f
permissions -rw-r--r--
use more writeIdentifier() and writeLength() methods
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     1
/**
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     2
 * Relational pipes
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     3
 * Copyright © 2018 František Kučera (Frantovo.cz, GlobalCode.info)
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     4
 *
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     5
 * This program is free software: you can redistribute it and/or modify
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     6
 * it under the terms of the GNU General Public License as published by
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     7
 * the Free Software Foundation, either version 3 of the License, or
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     8
 * (at your option) any later version.
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     9
 *
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    10
 * This program is distributed in the hope that it will be useful,
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    13
 * GNU General Public License for more details.
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    14
 *
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    15
 * You should have received a copy of the GNU General Public License
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    16
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    17
 */
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    18
#pragma once
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    19
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    20
#include <iostream>
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    21
#include <sstream>
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    22
#include <string>
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    23
#include <vector>
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    24
#include <codecvt>
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    25
#include <locale>
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    26
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    27
#include <relpipe/reader/typedefs.h>
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    28
#include <relpipe/cli/RelpipeCLIException.h>
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    29
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    30
using namespace std;
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    31
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    32
namespace relpipe {
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    33
namespace out {
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    34
namespace asn1 {
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    35
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    36
using namespace relpipe::reader;
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    37
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    38
/**
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    39
 * A simple library for writing ASN.1 BER encoded files.
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    40
 */
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    41
class ASN1Writer {
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    42
private:
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    43
	ostream& output;
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    44
	wstring_convert<codecvt_utf8<wchar_t>> convertor; // only UTF8String is supported
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    45
	int sequenceLevel = 0;
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    46
1
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    47
	enum TagClass : uint8_t {
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    48
		/** The type is native to ASN.1 */
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    49
		Universal = 0,
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    50
		/** The type is only valid for one specific application */
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    51
		Application = 1,
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    52
		/** Meaning of this type depends on the context (such as within a sequence, set or choice) */
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    53
		ContextSpecific = 2,
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    54
		/** Defined in private specifications */
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    55
		Private = 3,
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    56
	};
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    57
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    58
	enum PC : uint8_t {
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    59
		/** The contents octets directly encode the element value. */
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    60
		Primitive = 0,
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    61
		/** The contents octets contain 0, 1, or more element encodings.  */
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    62
		Constructed = 1,
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    63
	};
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    64
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    65
	enum UniversalType : uint16_t {
2
d1b39a9bd591 use more writeIdentifier() and writeLength() methods
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    66
		EndOfContent = 0,
1
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    67
		Boolean = 1,
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    68
		Integer = 2,
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    69
		OctetString = 4,
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    70
		Null = 5,
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    71
		ObjectIdentifier = 6,
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    72
		Real = 9,
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    73
		UTF8String = 12,
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    74
		RelativeObjectIdentifier = 13,
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    75
		Sequence = 16,
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    76
	};
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    77
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    78
	void writeIdentifier(TagClass tagClass, PC pc, uint16_t tagNumber) {
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    79
		if (tagNumber > 30) throw cli::RelpipeCLIException(L"Tag numbers higher than 30 are currently unsupported.", cli::CLI::EXIT_CODE_UNEXPECTED_ERROR); // should not happen, error in the program // TODO: support tag numbers > 30
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    80
		uint8_t tag = 0;
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    81
		tag |= tagClass << 6;
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    82
		tag |= pc << 5;
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    83
		tag |= tagNumber;
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    84
		output.put(tag);
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    85
	}
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    86
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    87
	/**
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    88
	 * @param der
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    89
	 * @param length
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    90
	 */
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    91
	template<typename N, typename = typename std::enable_if<std::is_unsigned<N>::value, N>::type>
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    92
	void writeLength(N length) {
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    93
		if (length < 128) {
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    94
			output.put(length);
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    95
		} else {
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    96
			for (int i = sizeof (N) - 1; i >= 0; i--) {
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    97
				uint8_t b = length >> (i * 8);
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    98
				if (b || i == 0) {
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    99
					output.put((i + 1) | 0x80);
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   100
					for (; i >= 0; i--) {
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   101
						b = length >> (i * 8);
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   102
						output.put(b);
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   103
					}
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   104
					break;
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   105
				}
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   106
			}
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   107
		}
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   108
	}
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   109
2
d1b39a9bd591 use more writeIdentifier() and writeLength() methods
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   110
	void writeLengthIndefinite() {
d1b39a9bd591 use more writeIdentifier() and writeLength() methods
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   111
		output.put('\x80');
d1b39a9bd591 use more writeIdentifier() and writeLength() methods
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   112
	}
d1b39a9bd591 use more writeIdentifier() and writeLength() methods
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   113
1
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   114
	static bool isLittleEndian() {
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   115
		int test = 1;
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   116
		return (*(char *) &test);
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   117
	}
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   118
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   119
	static bool isBigEndian() {
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   120
		return !isLittleEndian();
0
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   121
	}
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   122
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   123
public:
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   124
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   125
	ASN1Writer(std::ostream& output) : output(output) {
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   126
	}
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   127
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   128
	virtual ~ASN1Writer() {
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   129
		output.flush();
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   130
	}
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   131
1
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   132
	/**
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   133
	 * Just check whether all sequences are closed. If not, throws RelpipeCLIException.
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   134
	 */
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   135
	void end() {
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   136
		if (sequenceLevel) throw cli::RelpipeCLIException(L"Unable to close ASN1Writer because there are not ended sequences.", cli::CLI::EXIT_CODE_UNEXPECTED_ERROR); // should not happen, error in the program
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   137
	}
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   138
0
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   139
	void writeStartSequence() {
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   140
		sequenceLevel++;
2
d1b39a9bd591 use more writeIdentifier() and writeLength() methods
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   141
		writeIdentifier(TagClass::Universal, PC::Constructed, UniversalType::Sequence);
d1b39a9bd591 use more writeIdentifier() and writeLength() methods
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   142
		writeLengthIndefinite();
0
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   143
	}
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   144
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   145
	void writeEndSequence() {
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   146
		if (sequenceLevel == 0) throw cli::RelpipeCLIException(L"Unable to writeEndSequence() if not sequence is currently started.", cli::CLI::EXIT_CODE_UNEXPECTED_ERROR); // should not happen, error in the program
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   147
		sequenceLevel--;
2
d1b39a9bd591 use more writeIdentifier() and writeLength() methods
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   148
		writeIdentifier(TagClass::Universal, PC::Primitive, UniversalType::EndOfContent);
d1b39a9bd591 use more writeIdentifier() and writeLength() methods
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   149
		writeLength(0u);
0
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   150
	}
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   151
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   152
	void writeBoolean(const boolean_t& value) {
2
d1b39a9bd591 use more writeIdentifier() and writeLength() methods
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   153
		writeIdentifier(TagClass::Universal, PC::Primitive, UniversalType::Boolean);
d1b39a9bd591 use more writeIdentifier() and writeLength() methods
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   154
		writeLength(1u);
1
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   155
		output.put(value ? '\xFF' : '\x00');
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   156
0
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   157
	}
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   158
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   159
	void writeInteger(const integer_t& value) {
1
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   160
		uint8_t* end = (uint8_t*) & value;
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   161
		uint8_t* start = end + sizeof (value) - 1;
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   162
		uint8_t* current;
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   163
		int direction = -1;
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   164
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   165
		if (isBigEndian()) {
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   166
			std::swap(end, start);
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   167
			direction = -direction;
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   168
		}
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   169
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   170
		// move current pointer to the first valuable octet
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   171
		for (current = start; current != end; current += direction) {
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   172
			switch (*current) {
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   173
				case 0x00: if ((*(current + direction) & 0x80) == 0) continue;
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   174
					break;
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   175
				case 0xFF: if ((*(current + direction) & 0x80) != 0) continue;
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   176
					break;
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   177
			}
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   178
			break;
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   179
		}
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   180
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   181
		std::vector<char> v;
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   182
		writeIdentifier(TagClass::Universal, PC::Primitive, UniversalType::Integer);
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   183
		writeLength((size_t) (end > current ? end - current : current - end) + 1);
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   184
		for (end += direction; current != end; current += direction) output.put(*current);
0
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   185
	}
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   186
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   187
	void writeString(const string_t& value) {
1
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   188
		// TODO: empty string → null?
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   189
		std::string bytes = convertor.to_bytes(value);
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   190
		writeIdentifier(TagClass::Universal, PC::Primitive, UniversalType::UTF8String);
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   191
		writeLength(bytes.length());
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   192
		output << bytes;
0
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   193
	}
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   194
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   195
};
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   196
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   197
}
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   198
}
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   199
}