view xml.c @ 29:d2e627af7f61

fix.
author koba <koba@cr.ie.u-ryukyu.ac.jp>
date Tue, 28 Dec 2010 16:22:22 +0900
parents 435ac1cdb64e
children cee55c8365e9
line wrap: on
line source

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <libxml/parser.h>
#include "object.h"
#include "sys.h"
#include "xml.h"

#include "error.h"

#define ALIGN_16BYTE 16

extern int decode(char *cont, FILE *outfile);

static inline char *skip_to_number(char *cont)
{
    if (cont == NULL) return(NULL);
    for (;(*cont < '+' || *cont > '9') && (*cont != '\0');cont++) {}
    if (*cont == '\0')
    {
	fprintf(stderr,"Content data is short\n");
	return(NULL);
    }
    return(cont);
}


static inline char *pickup_exponent(int *exp, char *cont)
{
    int n,value=0,shift=10;

    if (*cont == ',' || *cont == '\n') return(NULL);

    for (;*cont != ',' && *cont != '\n' && *cont != '\t';cont++)
    {
	if (*cont == '-')
	{
	    shift = 0.1;
	}
	else if (*cont >= '0' && *cont <= '9')
	{
	    value *= 10;
	    value += *cont - 48;
	}
	else if (*cont == '+' || *cont == ' ')
	{
	    // ignore
	}
	else
	{
	    fprintf(stderr,"Pick up exponent failed : %c(%d)\n",*cont,*cont);
	    return(NULL);
	}
    }
  
    for (n=0;n < value;n++) shift *= shift;

    if (value == 0)
    {
	*exp = 1;
    }
    else
    {
	*exp = shift;
    }
    return(cont-1);
}


static inline char *pickup_float(char *cont, float *index)
{
    int sign=1,exp=1;
    float shift=10,val_dec=0,val_int=0;

    cont = skip_to_number(cont);
    if (cont == NULL) return(NULL);

    for (;*cont != ',' && *cont != '\n' && *cont != '\t';cont++)
    {
	if (*cont == '-')
	{
	    sign = -1;
	}
	else if (*cont == '.')
	{
	    shift = 0.1;
	}
	else if (*cont >= '0' && *cont <= '9')
	{
	    if (shift == 10)
	    {
		val_int *= shift;
		val_int += *cont - 48;
	    }
	    else
	    {
		val_dec += (*cont - 48) * shift;
		shift *= 0.1;
	    }
	}
	else if (*cont == 'e' || *cont == 'E')
	{
	    cont = pickup_exponent(&exp,cont+1);
	    if (cont == NULL) return(NULL);
	}
	else if (*cont == '+' || *cont == '/' || *cont == ' ')
	{
	    // ignore
	}
	else
	{
	    fprintf(stderr,"Pick up float failed : %c(%d)\n",*cont,*cont);
	    return(NULL);
	}
    }
  
    *index = sign * (val_int + val_dec) * exp;
    cont++;
    return(cont);
}


static FVECTOR *get_surface_data(SURFACE *surf, xmlNodePtr cur)
{
    int n;
    char *cont;
    float *index;
    FVECTOR *data[4];
    FILE *outfile = NULL;

    /*    
          data[0]: point position
          data[1]: point direction
          data[2]: point QT position
          data[3]: point color
    */
  
    data[0] = (FVECTOR *)malloc(sizeof(FVECTOR)*(surf->size)*4);
    data[1] = data[0] + surf->size;
    data[2] = data[1] + surf->size;
    data[3] = data[2] + surf->size;
    
    for (;cur;cur=cur->next)
    {
	if (!xmlStrcmp(cur->name,(xmlChar*)"coordinate"))
	{
	    cont = (char *)xmlNodeGetContent(cur);
	    for (n=0,index=(float*)data[0];n < surf->size;n++,index+=4)
	    {
		cont = pickup_float(cont,index);
		cont = pickup_float(cont,index+1);
		cont = pickup_float(cont,index+2);
		index[3] = 1.0;

		if (cont == NULL)
		{
		    fprintf(stderr,"Analyzing surface data failed coordinate\n");
		    return(NULL);
		}
	    }
	}
	else if (!xmlStrcmp(cur->name,(xmlChar*)"normal"))
	{
	    cont = (char *)xmlNodeGetContent(cur);
	    for (n=0,index=(float*)data[1];n < surf->size;n++,index+=4)
	    {
		cont = pickup_float(cont,index);
		cont = pickup_float(cont,index+1);
		cont = pickup_float(cont,index+2);
		index[3] = 1.0;
	      
		if (cont == NULL)
		{
		    fprintf(stderr,"Analyzing surface data failed normal\n");
		    return(NULL);
		}
	    }
	}
	else if (!xmlStrcmp(cur->name,(xmlChar*)"model"))
	{
	    cont = (char *)xmlNodeGetContent(cur);
	    //for (n=0,index=(float*)data[2]; n < surf->size;n++,index+=4)
	    for (n=0,index=(float*)data[2]; n < 1; n++,index+=4)
	    {
		cont = pickup_float(cont,index);
		cont = pickup_float(cont,index+1);
		cont = pickup_float(cont,index+2);
		//cont = pickup_float(cont,index+3);
		index[3] = 1.0;

		if (cont == NULL)
		{
		    fprintf(stderr,"Analyzing surface data failed model\n");
		    return(NULL);
		}
	    }
	}
	else if (!xmlStrcmp(cur->name,(xmlChar*)"texture"))
	{
	    cont = (char *)xmlNodeGetContent(cur);
	    if (cont == NULL)
	    {
		for (n=0,index=(float*)data[3];n < surf->size;n++,index+=4)
		{
		    index[0] = 0.0;
		    index[1] = 0.0;
		    index[2] = 0.0;
		    index[3] = 0.0;
		}
	    }	  
	    else
	    {
		for (n=0,index=(float*)data[3]; n < surf->size; n++,index+=4)
		{
		    cont = pickup_float(cont,index);
		    cont = pickup_float(cont,index+1);
		    index[2] = 1.0;
		    index[3] = 0.0;
		  
		    if (cont == NULL)
		    {
			fprintf(stderr,"Analyzing surface data failed last\n");
			return(NULL);
		    }
		}
	    }
	}
	else if(!xmlStrcmp(cur->name,(xmlChar*)"image"))
	{
	    surf->image_name = (char *)xmlGetProp(cur,(xmlChar *)"name");
            char *buf = (char*)malloc(strlen(surf->image_name)+10); 
            buf[0] = 0;
            strcat(buf,"/tmp/");
	    surf->image_name = strcat(buf, surf->image_name);

	    outfile = fopen(surf->image_name,"wb");
	    if(NULL == outfile)
	    {
		printf("error open file\n");
	    }

	    cont = (char *)xmlNodeGetContent(cur);
	    decode(cont, outfile);
	    fclose(outfile);
            // unlink(surf->image_name);
	}
    }
    return(data[0]);
}  
  

static SURFACE *create_surface_data(xmlNodePtr cur)
{
    char *name;
    char *parent_name;
    SURFACE *surface;


    surface = (SURFACE *)malloc(sizeof(SURFACE));
    if (surface == NULL)
    {
	fprintf(stderr,"malloc failed at create_surface_data");
	return(NULL);
    }
    surface->size = atoi((char *)xmlGetProp(cur,(xmlChar *)"size"));
    name = (char *)xmlGetProp(cur,(xmlChar *)"name");
    parent_name = (char *)xmlGetProp(cur,(xmlChar *)"parent");
    surface->name = name;
    surface->parent_name = parent_name;
    surface->next = NULL;

    surface->data[0] = get_surface_data(surface,cur->children);
    surface->data[1] = get_surface_data(surface,cur->children)+surface->size;
    surface->data[2] = get_surface_data(surface,cur->children)+surface->size*2;
    surface->data[3] = get_surface_data(surface,cur->children)+surface->size*3;


    return(surface);
}



static SURFACE *get_node_point(SURFACE *surfaces, char *name)
{
    SURFACE *list = surfaces;
    SURFACE *node = NULL;
    while(list != NULL)
    {
	if(!xmlStrcmp((xmlChar *)list->name,(xmlChar *)name))
	{
	    node = list;
	}
	list = list->next;
    }
    return node;
}


static SURFACE *create_tree(SURFACE *surfaces)
{
    SURFACE *linear_list;
    SURFACE *list_top = NULL;
    SURFACE *parent;

    linear_list = surfaces;
  
    while(linear_list != NULL)
    {
	if(xmlStrcmp((xmlChar *)linear_list->parent_name, (xmlChar *)"NULL"))
	{
	    parent = get_node_point(surfaces,linear_list->parent_name);
	    if(parent->child == NULL)
	    {
		parent->child = linear_list;
	    }
	    else
	    {
		parent->child->brother = linear_list;
	    }
	    linear_list->parent = parent;
	    __debug("name = %s, parent name = %s\n",linear_list->name, linear_list->parent_name);
	    __debug("  parent = %s\n",linear_list->parent->name);
	    __debug("  parent->child = %s\n",linear_list->parent->child->name);

	    linear_list->child = NULL;
	    linear_list->brother = NULL;
	    linear_list = linear_list->next;
	}
	else
	{
	    list_top = linear_list;
	    list_top->parent = NULL;
	    list_top->brother = NULL;
	    list_top->child = NULL;
	    linear_list = linear_list->next;
	    //printf("top name = %s\n",list_top->name);
	}
    }

    return list_top;
}


static OBJECT *create_object(xmlDocPtr doc)
{
    char *align,*head;
    OBJECT *obj;
    SURFACE *tmp,**joint;
    xmlNodePtr cur;

    cur = xmlDocGetRootElement(doc);
    if (cur == NULL)
    {
	fprintf(stderr,"XML file is empty\n");
	return(NULL);
    }

    if (xmlStrcmp(cur->name,(xmlChar*)"OBJECT-3D"))
    {
	fprintf(stderr,"This data format isn't OBJECT-3D\n");
	return(NULL);
    }

    if (malloc_align16(&head,&align,sizeof(OBJECT)) < 0)
    {
	fprintf(stderr,"malloc failed at create_object : OBJECT\n");
	return(NULL);
    }

    obj = (OBJECT *)align;
    obj->free_me = head;
    init_object(obj);

    obj->surfaces = NULL;    
    joint = &(obj->surfaces);

    for (cur=cur->children; cur; cur=cur->next)
    {
	if (!xmlStrcmp(cur->name,(xmlChar*)"surface"))
	{
	    tmp = create_surface_data(cur);
	    if (tmp == NULL)
	    {
		printf("temp is NULL\n");
		free_object(obj);
		return(NULL);
	    }
	    *joint = tmp;
	    joint = &(tmp->next);
	}
    }

    obj->surfaces = create_tree(obj->surfaces);

    return(obj);
}


//static int read_xml_3d_file(const char *file_name)
OBJECT *read_xml_3d_file(const char *file_name)
{
    xmlDocPtr doc;
    OBJECT *ptr;

    doc = xmlParseFile(file_name);
    if(doc == NULL)
    {
	printf("It seems that %s is not a xml data.\n", file_name);
    }
  
    ptr = create_object(doc);
    if(ptr == NULL)
    {
	printf("XML create_object failed : %s\n",file_name);
    }

    xmlFreeDoc(doc);
    return(ptr);
}