File: sml_shared.c

package info (click to toggle)
libsml 0.1.1%2Bgit20180125-1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 652 kB
  • sloc: ansic: 6,600; makefile: 163
file content (163 lines) | stat: -rw-r--r-- 3,920 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
// Copyright 2011 Juri Glass, Mathias Runge, Nadim El Sayed
// DAI-Labor, TU-Berlin
//
// This file is part of libSML.
//
// libSML is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// libSML is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with libSML.  If not, see <http://www.gnu.org/licenses/>.


#include <string.h>
#include <sml/sml_shared.h>
#include <stdio.h>

int sml_buf_get_next_length(sml_buffer *buf) {
	int length = 0;
	unsigned char byte = sml_buf_get_current_byte(buf);
	int list = ((byte & SML_TYPE_FIELD) == SML_TYPE_LIST) ? 0 : -1;

	for (;buf->cursor < buf->buffer_len;) {
		byte = sml_buf_get_current_byte(buf);
		length <<= 4;
		length |= (byte & SML_LENGTH_FIELD);

		if ((byte & SML_ANOTHER_TL) != SML_ANOTHER_TL) {
			break;
		}
		sml_buf_update_bytes_read(buf, 1);
		if(list) {
			list += -1;
		}
	}
	sml_buf_update_bytes_read(buf, 1);

	return length + list;
}

void sml_buf_set_type_and_length(sml_buffer *buf, unsigned int type, unsigned int l) {
	// set the type
	buf->buffer[buf->cursor] = type;

	if (type != SML_TYPE_LIST) {
		l++;
	}

	if (l > SML_LENGTH_FIELD) {

		// how much shifts are necessary
		int mask_pos = (sizeof(unsigned int) * 2) - 1;

		// the 4 most significant bits of l (1111 0000 0000 ...)
		unsigned int mask = 0xF0 << (8 * (sizeof(unsigned int) - 1));

		// select the next 4 most significant bits with a bit set until there 
		// is something
		while (!(mask & l)) {
			mask >>= 4;
			mask_pos--;
		}

		l += mask_pos; // for every TL-field

		if ((0x0F << (4 * (mask_pos + 1))) & l) {
			// for the rare case that the addition of the number of TL-fields
			// result in another TL-field.
			mask_pos++;
			l++;
		}

		// copy 4 bits of the number to the buffer
		while (mask > SML_LENGTH_FIELD) {
			buf->buffer[buf->cursor] |= SML_ANOTHER_TL;
			buf->buffer[buf->cursor] |= ((mask & l) >> (4 * mask_pos));
			mask >>= 4;
			mask_pos--;
			buf->cursor++;
		}
	}

	buf->buffer[buf->cursor] |= (l & SML_LENGTH_FIELD);
	buf->cursor++;
}

int sml_buf_has_errors(sml_buffer *buf) {
	return buf->error != 0;
}

int sml_buf_get_next_type(sml_buffer *buf) {
	return (buf->buffer[buf->cursor] & SML_TYPE_FIELD);
}

unsigned char sml_buf_get_current_byte(sml_buffer *buf) {
	return buf->buffer[buf->cursor];
}

unsigned char *sml_buf_get_current_buf(sml_buffer *buf) {
	return &(buf->buffer[buf->cursor]);
}

void sml_buf_update_bytes_read(sml_buffer *buf, int bytes) {
	buf->cursor += bytes;
}

sml_buffer *sml_buffer_init(size_t length) {
	sml_buffer *buf = (sml_buffer *) malloc(sizeof(sml_buffer));
	*buf = ( sml_buffer ) {
		.buffer = NULL,
		.buffer_len = 0,
		.cursor = 0,
		.error = 0,
		.error_msg = NULL
	};
	buf->buffer = (unsigned char *) malloc(length);
	buf->buffer_len = length;
	memset(buf->buffer, 0, buf->buffer_len);

	return buf;
}

void sml_buf_optional_write(sml_buffer *buf) {
	buf->buffer[buf->cursor] = SML_OPTIONAL_SKIPPED;
	buf->cursor++;
}

void sml_buffer_free(sml_buffer *buf) {
	if (buf) {
		if (buf->buffer)
			free(buf->buffer);
		if (buf->error_msg)
			free(buf->error_msg);
		free(buf);
	}
}

int sml_buf_optional_is_skipped(sml_buffer *buf) {
	if (sml_buf_get_current_byte(buf) == SML_OPTIONAL_SKIPPED) {
		sml_buf_update_bytes_read(buf, 1);

		return 1;
	}

	return 0;
}

void hexdump(unsigned char *buffer, size_t buffer_len) {
	for ( size_t i = 0; i < buffer_len; i++) {
		printf("%02X ", (unsigned char) buffer[i]);
		if ((i + 1) % 8 == 0) {
			printf("\n");
		}
	}
	puts( "" );
}