src/ASN1Writer.h
author František Kučera <franta-hg@frantovo.cz>
Tue, 22 Oct 2019 21:53:25 +0200
branchv_0
changeset 7 c155b441306f
parent 2 d1b39a9bd591
permissions -rw-r--r--
fix license version: GNU GPLv3
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
7
c155b441306f fix license version: GNU GPLv3
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
     7
 * the Free Software Foundation, version 3 of the License.
0
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     8
 *
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     9
 * 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
    10
 * 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
    11
 * 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
    12
 * 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
    13
 *
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    14
 * 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
    15
 * 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
    16
 */
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    17
#pragma once
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    18
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    19
#include <iostream>
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    20
#include <sstream>
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    21
#include <string>
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    22
#include <vector>
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    23
#include <codecvt>
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    24
#include <locale>
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    25
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    26
#include <relpipe/reader/typedefs.h>
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    27
#include <relpipe/cli/RelpipeCLIException.h>
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    28
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    29
using namespace std;
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    30
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    31
namespace relpipe {
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    32
namespace out {
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    33
namespace asn1 {
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    34
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    35
using namespace relpipe::reader;
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    36
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
 * 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
    39
 */
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    40
class ASN1Writer {
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    41
private:
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    42
	ostream& output;
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    43
	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
    44
	int sequenceLevel = 0;
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    45
1
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    46
	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
    47
		/** 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
    48
		Universal = 0,
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    49
		/** 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
    50
		Application = 1,
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    51
		/** 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
    52
		ContextSpecific = 2,
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    53
		/** 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
    54
		Private = 3,
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    55
	};
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
	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
    58
		/** 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
    59
		Primitive = 0,
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    60
		/** 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
    61
		Constructed = 1,
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    62
	};
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
	enum UniversalType : uint16_t {
2
d1b39a9bd591 use more writeIdentifier() and writeLength() methods
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    65
		EndOfContent = 0,
1
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    66
		Boolean = 1,
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    67
		Integer = 2,
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    68
		OctetString = 4,
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    69
		Null = 5,
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    70
		ObjectIdentifier = 6,
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    71
		Real = 9,
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    72
		UTF8String = 12,
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    73
		RelativeObjectIdentifier = 13,
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    74
		Sequence = 16,
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    75
	};
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
	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
    78
		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
    79
		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
    80
		tag |= tagClass << 6;
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    81
		tag |= pc << 5;
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    82
		tag |= tagNumber;
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    83
		output.put(tag);
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    84
	}
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
	 * @param der
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    88
	 * @param length
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    89
	 */
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    90
	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
    91
	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
    92
		if (length < 128) {
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    93
			output.put(length);
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    94
		} else {
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    95
			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
    96
				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
    97
				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
    98
					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
    99
					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
   100
						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
   101
						output.put(b);
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   102
					}
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   103
					break;
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   104
				}
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
2
d1b39a9bd591 use more writeIdentifier() and writeLength() methods
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   109
	void writeLengthIndefinite() {
d1b39a9bd591 use more writeIdentifier() and writeLength() methods
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   110
		output.put('\x80');
d1b39a9bd591 use more writeIdentifier() and writeLength() methods
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   111
	}
d1b39a9bd591 use more writeIdentifier() and writeLength() methods
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   112
1
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   113
	static bool isLittleEndian() {
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   114
		int test = 1;
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   115
		return (*(char *) &test);
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   116
	}
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
	static bool isBigEndian() {
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   119
		return !isLittleEndian();
0
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   120
	}
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
public:
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   123
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   124
	ASN1Writer(std::ostream& output) : output(output) {
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   125
	}
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
	virtual ~ASN1Writer() {
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   128
		output.flush();
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   129
	}
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   130
1
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   131
	/**
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   132
	 * 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
   133
	 */
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   134
	void end() {
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   135
		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
   136
	}
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   137
0
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   138
	void writeStartSequence() {
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   139
		sequenceLevel++;
2
d1b39a9bd591 use more writeIdentifier() and writeLength() methods
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   140
		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
   141
		writeLengthIndefinite();
0
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   142
	}
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
	void writeEndSequence() {
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   145
		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
   146
		sequenceLevel--;
2
d1b39a9bd591 use more writeIdentifier() and writeLength() methods
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
   147
		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
   148
		writeLength(0u);
0
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   149
	}
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
	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
   152
		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
   153
		writeLength(1u);
1
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   154
		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
   155
0
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   156
	}
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
	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
   159
		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
   160
		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
   161
		uint8_t* current;
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   162
		int direction = -1;
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   163
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   164
		if (isBigEndian()) {
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   165
			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
   166
			direction = -direction;
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   167
		}
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
		// 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
   170
		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
   171
			switch (*current) {
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   172
				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
   173
					break;
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   174
				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
   175
					break;
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   176
			}
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   177
			break;
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   178
		}
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
		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
   181
		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
   182
		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
   183
		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
   184
	}
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
	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
   187
		// 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
   188
		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
   189
		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
   190
		writeLength(bytes.length());
e9b4f3a9e436 first working version with ASN.1 BER output
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   191
		output << bytes;
0
f4f9cdf7ed59 project and code skeleton: text output
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   192
	}
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
}