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

#include <iiimp-data.h>

#include "iiimp-dataP.h"


IIIMP_jarfile_object *
iiimp_jarfile_object_new(
    IIIMP_data_s *	data_s,
    IIIMP_string *	class_names,
    size_t		value_nbyte,
    const uchar_t *	value)
{
    IIIMP_jarfile_object *	jar;

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

    jar->nbyte = 4;
    jar->class_names_nbyte = 0;

    jar->class_names = class_names;
    for (; NULL != class_names; class_names = class_names->next) {
	jar->class_names_nbyte += class_names->nbyte;
    }
    jar->nbyte += jar->class_names_nbyte;

    jar->nbyte += 4;
    jar->value.nbyte = value_nbyte;

    jar->value.ptr = (uchar_t*) malloc(value_nbyte * sizeof(uchar_t));
    if (!jar->value.ptr) {
	free(jar);
	data_s->status = IIIMP_DATA_MALLOC_ERROR;
	return NULL;
    }
    memcpy(jar->value.ptr, value, value_nbyte);
    jar->nbyte += (value_nbyte + PAD(value_nbyte));

    return jar;
}


void
iiimp_jarfile_object_delete(
    IIIMP_data_s *		data_s,
    IIIMP_jarfile_object *	jarfile)
{
    if (NULL == jarfile) return;
    iiimp_string_list_delete(data_s, jarfile->class_names);
    free(jarfile->value.ptr);
    free(jarfile);
    return;
}


void
iiimp_jarfile_object_pack(
    IIIMP_data_s *		data_s,
    IIIMP_jarfile_object *	m,
    size_t *			nbyte,
    uchar_t **			ptr)
{
    size_t	rest;
    uchar_t *	p;
    size_t	pad;

    rest = *nbyte;
    p = *ptr;

    PUTU32(m->class_names_nbyte, rest, p, data_s->byte_swap);
    iiimp_string_list_pack(data_s, m->class_names, &rest, &p);
    PUTU32(m->value.nbyte, rest, p, data_s->byte_swap);
    (void)memcpy(p, m->value.ptr, m->value.nbyte);
    p += m->value.nbyte;
    rest -= m->value.nbyte;
    for (pad = PAD(m->value.nbyte); 0 < pad; --pad) {
	PUTU8(0, rest, p, data_s->byte_swap);
    }

    *nbyte = rest;
    *ptr = p;

    return;
}


IIIMP_jarfile_object *
iiimp_jarfile_object_unpack(
    IIIMP_data_s *	data_s,
    size_t *		nbyte,
    const uchar_t **	ptr,
    size_t		nbyte_max)
{
    IIIMP_jarfile_object *	jar;
    size_t			rest;
    const uchar_t *		p;
    size_t			len;
    int				i;

    rest = nbyte_max;
    p = *ptr;

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

    GETU32(len, rest, p, data_s->byte_swap);
    if (rest < len) {
	data_s->status = IIIMP_DATA_INVALID;
	return NULL;
    }

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

    jar->class_names = iiimp_string_list_unpack(data_s, &rest, &p, len);
    if (NULL == jar->class_names) {
	free(jar);
	return NULL;
    }

    GETU32(len, rest, p, data_s->byte_swap);
    if (rest < len) {
	iiimp_string_list_delete(data_s, jar->class_names);
	free(jar);
	data_s->status = IIIMP_DATA_INVALID;
	return NULL;
    }

    jar->value.nbyte = len;
    jar->value.ptr = (uchar_t *)malloc(len);
    if (NULL == jar->value.ptr) {
	iiimp_string_list_delete(data_s, jar->class_names);
	free(jar);
	data_s->status = IIIMP_DATA_MALLOC_ERROR;
	return NULL;
    }
    (void)memcpy(jar->value.ptr, p, len);

    i = PAD(len);
    if ((len + i) < rest) {
	rest -= (len + i);
	p += (len + i);
    } else {
	p += rest;
	rest = 0;
    }

    *nbyte = rest;
    *ptr = p;

    return jar;
}


void
iiimp_jarfile_object_print(
    IIIMP_data_s *		data_s,
    IIIMP_jarfile_object *	m)
{
    IIIMP_string *	s;

    if (NULL == m) return;

    (void)fprintf(data_s->print_fp, "\tname=");
    for (s = m->class_names; NULL != s; s = s->next) {
	if (s != m->class_names) {
	    (void)fprintf(data_s->print_fp, "\t     ");
	}
	iiimp_string_print(data_s, s);
	(void)fputc('\n', data_s->print_fp);
    }
    (void)fprintf(data_s->print_fp, "\tjarfile object=");
    if (IIIMP_PRINT_JARFILE & data_s->print_flag) {
	(void)fputc('\n', data_s->print_fp);
	iiimp_byte_stream_print(data_s, &(m->value));
    } else {
	(void)fprintf(data_s->print_fp, "(%d)\n", m->value.nbyte);
    }
}


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