#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>

#include <iiimp-data.h>

#include "iiimp-dataP.h"


IIIMP_language *
iiimp_language_new(
    IIIMP_data_s *	data_s,
    IIIMP_string *	hrn,
    IIIMP_string *	id)
{
    IIIMP_language *	lang;

    lang = (IIIMP_language *)malloc(sizeof (IIIMP_language));
    if (NULL == lang) {
	data_s->status = IIIMP_DATA_MALLOC_ERROR;
	return NULL;
    }

    lang->nbyte = 0;
    lang->next = NULL;

    if (NULL == hrn) {
	lang->nbyte += 4;
    } else {
	lang->nbyte += hrn->nbyte;
    }
    if (NULL == id) {
	lang->nbyte += 4;
    } else {
	lang->nbyte += id->nbyte;
    }

    lang->hrn = hrn;
    lang->id = id;

    return lang;
}


void
iiimp_language_delete(IIIMP_data_s * data_s, IIIMP_language * language)
{
    if (NULL == language) return;
    iiimp_string_delete(data_s, language->hrn);
    iiimp_string_delete(data_s, language->id);
    free(language);
    return;
}


void
iiimp_language_list_delete(IIIMP_data_s * data_s, IIIMP_language * language)
{
    IIIMP_language *	lang_next;
    for (; NULL != language; language = lang_next) {
	lang_next = language->next;
	iiimp_language_delete(data_s, language);
    }
    return;
}


void
iiimp_language_pack(
    IIIMP_data_s *	data_s,
    IIIMP_language *	m,
    size_t *		nbyte,
    uchar_t **		ptr)
{
    size_t	rest;
    uchar_t *	p;

    rest = *nbyte;
    p = *ptr;

    iiimp_string_pack(data_s, m->hrn, &rest, &p);
    iiimp_string_pack(data_s, m->id, &rest, &p);

    *nbyte -= rest;
    *ptr = p;

    return;
}


void
iiimp_language_list_pack(
    IIIMP_data_s *	data_s,
    IIIMP_language *	m,
    size_t *		nbyte,
    uchar_t **		ptr)
{
    size_t	rest;
    uchar_t *	p;

    rest = *nbyte;
    p = *ptr;

    for (; NULL != m; m = m->next) {
	iiimp_language_pack(data_s, m, &rest, &p);
    }

    *nbyte -= rest;
    *ptr = p;

    return;
}


IIIMP_language *
iiimp_language_unpack(
    IIIMP_data_s *	data_s,
    size_t *		nbyte,
    const uchar_t **	ptr,
    size_t		nbyte_max)
{
    IIIMP_language *	lang;
    size_t		rest;
    const uchar_t *	p;

    rest = nbyte_max;
    p = *ptr;

    if ((*nbyte < rest) || (rest < (4 + 4 + 4 + 4))) {
	data_s->status = IIIMP_DATA_INVALID;
	return NULL;
    }

    lang = (IIIMP_language *)malloc(sizeof (IIIMP_language));
    if (NULL == lang) {
	data_s->status = IIIMP_DATA_MALLOC_ERROR;
	return NULL;
    }

    lang->nbyte = 0;
    lang->hrn = NULL;
    lang->id = NULL;
    lang->next = NULL;

    lang->hrn = iiimp_string_unpack(data_s, &rest, &p, rest);
    if (NULL == lang->hrn) {
	iiimp_language_delete(data_s, lang);
	return NULL;
    }

    lang->id = iiimp_string_unpack(data_s, &rest, &p, rest);
    if (NULL == lang->id) {
	iiimp_language_delete(data_s, lang);
	return NULL;
    }

    *nbyte -= (nbyte_max - rest);
    *ptr = p;

    return lang;
}


IIIMP_language *
iiimp_language_list_unpack(
    IIIMP_data_s *	data_s,
    size_t *		nbyte,
    const uchar_t **	ptr,
    size_t		nbyte_max)
{
    IIIMP_language *	lang;
    size_t		rest;
    const uchar_t *	p;
    IIIMP_language *	lang_first;
    IIIMP_language *	lang_last;

    rest = nbyte_max;
    p = *ptr;
    lang = NULL;
    lang_first = NULL;
    lang_last = NULL;

    if ((*nbyte < rest) || (rest < (4 + 4 + 4 + 4))) {
	data_s->status = IIIMP_DATA_INVALID;
	return NULL;
    }

    while (0 < rest) {
	lang = iiimp_language_unpack(data_s, &rest, &p, rest);
	if (NULL == lang) {
	    iiimp_language_list_delete(data_s, lang_first);
	    return NULL;
	} else {
	    if (NULL == lang_first) {
		lang_first = lang;
	    } else {
		lang_last->next = lang;
	    }
	    lang_last = lang;
	}
    }

    *nbyte -= (nbyte_max - rest);
    *ptr = p;

    return lang_first;
}


void
iiimp_language_print(
    IIIMP_data_s *	data_s,
    IIIMP_language *	m)
{
    if (NULL == m) return;

    iiimp_string_print(data_s, m->hrn);
    (void)fputc(' ', data_s->print_fp);
    iiimp_string_print(data_s, m->id);
}


/* Local Variables: */
/* c-file-style: "iiim-project" */
/* End: */
