libsml/sml/src/sml_list.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;
}
}
}
}