251 lines
5.4 KiB
C
251 lines
5.4 KiB
C
// 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 <sml/sml_list.h>
|
|
#include <sml/sml_shared.h>
|
|
#include <sml/sml_time.h>
|
|
#include <sml/sml_octet_string.h>
|
|
#include <sml/sml_status.h>
|
|
#include <sml/sml_value.h>
|
|
#include <stdio.h>
|
|
|
|
// sml_sequence;
|
|
|
|
sml_sequence *sml_sequence_init(void (*elem_free) (void *elem)) {
|
|
sml_sequence *seq = (sml_sequence *) malloc(sizeof(sml_sequence));
|
|
memset(seq, 0, sizeof(sml_sequence));
|
|
seq->elem_free = elem_free;
|
|
|
|
return seq;
|
|
}
|
|
|
|
sml_sequence *sml_sequence_parse(sml_buffer *buf, void *(*elem_parse) (sml_buffer *buf), void (*elem_free) (void *elem)) {
|
|
if (sml_buf_get_next_type(buf) != SML_TYPE_LIST) {
|
|
buf->error = 1;
|
|
goto error;
|
|
}
|
|
|
|
sml_sequence *seq = sml_sequence_init(elem_free);
|
|
int i, len = sml_buf_get_next_length(buf);
|
|
void *p;
|
|
for (i = 0; i < len; i++) {
|
|
p = elem_parse(buf);
|
|
if (sml_buf_has_errors(buf)) goto error;
|
|
sml_sequence_add(seq, p);
|
|
}
|
|
|
|
return seq;
|
|
|
|
error:
|
|
buf->error = 1;
|
|
sml_sequence_free(seq);
|
|
return 0;
|
|
}
|
|
|
|
void sml_sequence_write(sml_sequence *seq, sml_buffer *buf, void (*elem_write) (void *elem, sml_buffer *buf)) {
|
|
if (seq == 0) {
|
|
sml_buf_optional_write(buf);
|
|
return;
|
|
}
|
|
|
|
sml_buf_set_type_and_length(buf, SML_TYPE_LIST, seq->elems_len);
|
|
|
|
int i;
|
|
for (i = 0; i < seq->elems_len; i++) {
|
|
elem_write((seq->elems)[i], buf);
|
|
}
|
|
}
|
|
|
|
void sml_sequence_free(sml_sequence *seq) {
|
|
if (seq) {
|
|
int i;
|
|
for (i = 0; i < seq->elems_len; i++) {
|
|
seq->elem_free((seq->elems)[i]);
|
|
}
|
|
|
|
if (seq->elems != 0) {
|
|
free(seq->elems);
|
|
}
|
|
|
|
free(seq);
|
|
}
|
|
}
|
|
|
|
void sml_sequence_add(sml_sequence *seq, void *new_entry) {
|
|
seq->elems_len++;
|
|
seq->elems = (void **) realloc(seq->elems, sizeof(void *) * seq->elems_len);
|
|
seq->elems[seq->elems_len - 1] = new_entry;
|
|
}
|
|
|
|
|
|
// sml_list;
|
|
|
|
sml_list *sml_list_init(){
|
|
sml_list *s = (sml_list *)malloc(sizeof(sml_list));
|
|
memset(s, 0, sizeof(sml_list));
|
|
return s;
|
|
}
|
|
|
|
void sml_list_add(sml_list *list, sml_list *new_entry) {
|
|
list->next = new_entry;
|
|
}
|
|
|
|
sml_list *sml_list_entry_parse(sml_buffer *buf) {
|
|
if (sml_buf_get_next_type(buf) != SML_TYPE_LIST) {
|
|
buf->error = 1;
|
|
goto error;
|
|
}
|
|
|
|
if (sml_buf_get_next_length(buf) != 7) {
|
|
buf->error = 1;
|
|
goto error;
|
|
}
|
|
sml_list *l = sml_list_init();
|
|
|
|
l->obj_name = sml_octet_string_parse(buf);
|
|
if (sml_buf_has_errors(buf)) goto error;
|
|
|
|
l->status = sml_status_parse(buf);
|
|
if (sml_buf_has_errors(buf)) goto error;
|
|
|
|
l->val_time = sml_time_parse(buf);
|
|
if (sml_buf_has_errors(buf)) goto error;
|
|
|
|
l->unit = sml_u8_parse(buf);
|
|
if (sml_buf_has_errors(buf)) goto error;
|
|
|
|
l->scaler = sml_i8_parse(buf);
|
|
if (sml_buf_has_errors(buf)) goto error;
|
|
|
|
l->value = sml_value_parse(buf);
|
|
if (sml_buf_has_errors(buf)) goto error;
|
|
|
|
l->value_signature = sml_octet_string_parse(buf);
|
|
if (sml_buf_has_errors(buf)) goto error;
|
|
|
|
return l;
|
|
|
|
// This function doesn't free the allocated memory in error cases,
|
|
// this is done in sml_list_parse.
|
|
error:
|
|
buf->error = 1;
|
|
return 0;
|
|
}
|
|
|
|
sml_list *sml_list_parse(sml_buffer *buf) {
|
|
if (sml_buf_optional_is_skipped(buf)) {
|
|
return 0;
|
|
}
|
|
|
|
if (sml_buf_get_next_type(buf) != SML_TYPE_LIST) {
|
|
buf->error = 1;
|
|
return 0;
|
|
}
|
|
|
|
sml_list *first = 0;
|
|
sml_list *last = 0;
|
|
int elems;
|
|
|
|
elems = sml_buf_get_next_length(buf);
|
|
|
|
if (elems > 0) {
|
|
first = sml_list_entry_parse(buf);
|
|
if (sml_buf_has_errors(buf)) goto error;
|
|
last = first;
|
|
elems--;
|
|
}
|
|
|
|
while(elems > 0) {
|
|
last->next = sml_list_entry_parse(buf);
|
|
if (sml_buf_has_errors(buf)) goto error;
|
|
last = last->next;
|
|
elems--;
|
|
}
|
|
|
|
return first;
|
|
|
|
error:
|
|
buf->error = 1;
|
|
sml_list_free(first);
|
|
return 0;
|
|
}
|
|
|
|
|
|
void sml_list_entry_write(sml_list *list, sml_buffer *buf) {
|
|
sml_buf_set_type_and_length(buf, SML_TYPE_LIST, 7);
|
|
sml_octet_string_write(list->obj_name, buf);
|
|
sml_status_write(list->status, buf);
|
|
sml_time_write(list->val_time, buf);
|
|
sml_u8_write(list->unit, buf);
|
|
sml_i8_write(list->scaler, buf);
|
|
sml_value_write(list->value, buf);
|
|
sml_octet_string_write(list->value_signature, buf);
|
|
}
|
|
|
|
void sml_list_write(sml_list *list, sml_buffer *buf){
|
|
if (list == 0) {
|
|
sml_buf_optional_write(buf);
|
|
return;
|
|
}
|
|
|
|
sml_list *i = list;
|
|
int len = 0;
|
|
while(i) {
|
|
i = i->next;
|
|
len++;
|
|
}
|
|
|
|
sml_buf_set_type_and_length(buf, SML_TYPE_LIST, len);
|
|
|
|
i = list;
|
|
while(i) {
|
|
sml_list_entry_write(i, buf);
|
|
i = i->next;
|
|
}
|
|
}
|
|
|
|
void sml_list_entry_free(sml_list *list) {
|
|
if (list) {
|
|
sml_octet_string_free(list->obj_name);
|
|
sml_status_free(list->status);
|
|
sml_time_free(list->val_time);
|
|
sml_number_free(list->unit);
|
|
sml_number_free(list->scaler);
|
|
sml_value_free(list->value);
|
|
sml_octet_string_free(list->value_signature);
|
|
|
|
free(list);
|
|
}
|
|
}
|
|
|
|
void sml_list_free(sml_list *list) {
|
|
if (list) {
|
|
sml_list *f = list;
|
|
sml_list *n = list->next;
|
|
|
|
while(f) {
|
|
sml_list_entry_free(f);
|
|
f = n;
|
|
if (f) {
|
|
n = f->next;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|