// 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 .
#include
#include
#include
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
unsigned int mask = 0xF0 << (8 * (sizeof(unsigned int) - 1));
// select the 4 most significant bits with a bit set
while (!(mask & l)) {
mask >>= 4;
mask_pos--;
}
// copy the bits 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));
memset(buf, 0, sizeof(sml_buffer));
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) {
int i;
for (i = 0; i < buffer_len; i++) {
printf("%02X ", (unsigned char) buffer[i]);
if ((i + 1) % 8 == 0) {
printf("\n");
}
}
printf("\n");
}