source: trunk/zoo-project/zoo-kernel/service.c @ 805

Last change on this file since 805 was 805, checked in by djay, 4 years ago

Return default iotype if no value has been provided. Fix potential segfault in case tmpIoType is null.

  • Property svn:keywords set to Id
File size: 36.1 KB
Line 
1/*
2 * Author : Gérald FENOY
3 *
4 * Copyright (c) 2015 GeoLabs SARL
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24
25#include "service.h"
26
27
28#if defined(_MSC_VER) && _MSC_VER < 1800
29#include <stdarg.h>
30/**
31 * snprintf for Visual Studio compiler.
32 *
33 * See https://dxr.mozilla.org/mozilla-central/source/media/mtransport/third_party/nrappkit/src/util/util.c
34 */
35int snprintf(char *buffer, size_t n, const char *format, ...)
36{
37  va_list argp;
38  int ret;
39  va_start(argp, format);
40  ret = _vscprintf(format, argp);
41  vsnprintf_s(buffer, n, _TRUNCATE, format, argp);
42  va_end(argp);
43  return ret;
44}
45#endif
46
47/**
48 * Dump a map on stderr
49 *
50 * @param t the map to dump
51 */
52void _dumpMap(map* t){
53  if(t!=NULL){
54    fprintf(stderr,"%s: %s\n",t->name,t->value);
55    fflush(stderr);
56  }else{
57    fprintf(stderr,"NULL\n");
58    fflush(stderr);
59  }
60}
61
62/**
63 * Dump a map on stderr, see _dumpMap()
64 *
65 * @param t the map to dump
66 */
67void dumpMap(map* t){
68  map* tmp=t;
69  while(tmp!=NULL){
70    _dumpMap(tmp);
71    tmp=tmp->next;
72  }
73}
74
75/**
76 * Dump a map to a file
77 *
78 * @param t the map to dump to file
79 * @param file the file pointer to store the map
80 */
81void dumpMapToFile(map* t,FILE* file){
82  map* tmp=t;
83  while(tmp!=NULL){
84    fprintf(file,"%s = %s\n",tmp->name,tmp->value);
85    tmp=tmp->next;
86  }
87}
88
89/**
90 * Dump a maps on stderr, see dumpMap().
91 *
92 * @param m the map to dump
93 */
94void dumpMaps(maps* m){
95  maps* tmp=m;
96  while(tmp!=NULL){
97    fprintf(stderr,"MAP => [%s] \n",tmp->name);
98    fprintf(stderr," * CONTENT [%s] \n",tmp->name);
99    dumpMap(tmp->content);
100    fprintf(stderr," * CHILD [%s] \n",tmp->name);
101    dumpMaps(tmp->child);
102    tmp=tmp->next;
103  }
104}
105
106/**
107 * Dump a maps to a file, see dumpMapToFile().
108 *
109 * @param m the map to dump
110 * @param file the the file pointer to store the map
111 */
112void _dumpMapsToFile(maps* m,FILE* file,int limit){
113  maps* tmp=m;
114  int cnt=0;
115  while(tmp!=NULL){
116    fprintf(file,"[%s]\n",tmp->name);
117    if(tmp->child!=NULL){
118      _dumpMapsToFile(tmp->child,file,limit);
119    }else
120      dumpMapToFile(tmp->content,file);
121    fflush(file);
122    tmp=tmp->next;
123    cnt++;
124    if(limit>=0 && cnt==limit)
125      tmp=NULL;
126  }
127  fflush(file);
128}
129
130/**
131 * Dump a maps to a file, see _dumpMapsToFile().
132 *
133 * @param m the map to dump
134 * @param file_path the full path to the file name to store the map
135 * @param limit the number limiting the maps to be dumped
136 */
137void dumpMapsToFile(maps* m,char* file_path,int limit){
138  FILE* file=fopen(file_path,"w+");
139  _dumpMapsToFile(m,file,limit);
140  fflush(file);
141  fclose(file);
142}
143
144/**
145 * Create a new map
146 *
147 * @param name the key to add to the map
148 * @param value the corresponding value to add to the map
149 * @return a pointer to the allocated map
150 */
151map* createMap(const char* name,const char* value){
152  map* tmp=(map *)malloc(MAP_SIZE);
153  tmp->name=zStrdup(name);
154  tmp->value=zStrdup(value);
155  tmp->next=NULL;
156  return tmp;
157}
158
159/**
160 * Create a new maps with the given name
161 *
162 * @param name of the maps
163 * @return the allocated map
164 */
165maps* createMaps(const char* name){
166  maps* tmp = (maps *) malloc (MAPS_SIZE);
167  tmp->name = zStrdup (name);
168  tmp->content = NULL;
169  tmp->child = NULL;
170  tmp->next = NULL;
171  return tmp;
172}
173
174/**
175 * Count number of map in a map
176 *
177 * @param m the maps to count
178 * @return number of map in a map
179 */
180int count(map* m){
181  map* tmp=m;
182  int c=0;
183  while(tmp!=NULL){
184    c++;
185    tmp=tmp->next;
186  }
187  return c;
188}
189
190/**
191 * Verify if a key exist in a map
192 *
193 * @param m the map to search for the key
194 * @param key the key to search in the map
195 * @return true if the key wwas found, false in other case
196 */
197bool hasKey(map* m,const char *key){
198  map* tmp=m;
199  while(tmp!=NULL){
200    if(strcasecmp(tmp->name,key)==0)
201      return true;
202    tmp=tmp->next;
203  }
204#ifdef DEBUG_MAP
205  fprintf(stderr,"NOT FOUND \n");
206#endif
207  return false;
208}
209
210/**
211 * Access a specific maps
212 *
213 * @param m the maps to search for the key
214 * @param key the key to search in the maps
215 * @return a pointer on the maps found or NULL if not found
216 */
217maps* getMaps(maps* m,const char *key){
218  maps* tmp=m;
219  while(tmp!=NULL){
220    if(strcasecmp(tmp->name,key)==0){
221      return tmp;
222    }
223    tmp=tmp->next;
224  }
225  return NULL;
226}
227
228/**
229 * Access a specific map
230 *
231 * @param m the map to search for the key
232 * @param key the key to search in the map
233 * @return a pointer on the map found or NULL if not found
234 */
235map* getMap(map* m,const char *key){
236  map* tmp=m;
237  while(tmp!=NULL){
238    if(strcasecmp(tmp->name,key)==0){
239      return tmp;
240    }
241    tmp=tmp->next;
242  }
243  return NULL;
244}
245
246
247/**
248 * Access the last map
249 *
250 * @param m the map to search for the lastest map
251 * @return a pointer on the lastest map found or NULL if not found
252 */
253map* getLastMap(map* m){
254  map* tmp=m;
255  while(tmp!=NULL){
256    if(tmp->next==NULL){
257      return tmp;
258    }
259    tmp=tmp->next;
260  }
261  return NULL;
262}
263
264/**
265 * Access a specific map from a maps
266 *
267 * @param m the maps to search for the key
268 * @param key the key to search in the maps
269 * @param subkey the key to search in the map (found for the key, if any)
270 * @return a pointer on the map found or NULL if not found
271 */
272map* getMapFromMaps(maps* m,const char* key,const char* subkey){
273  maps* _tmpm=getMaps(m,key);
274  if(_tmpm!=NULL){
275    map* _ztmpm=getMap(_tmpm->content,subkey);
276    return _ztmpm;
277  }
278  else return NULL;
279}
280
281/**
282 * Free allocated memory of a map.
283 * Require to call free on mo after calling this function.
284 *
285 * @param mo the map to free
286 */
287void freeMap(map** mo){
288  map* _cursor=*mo;
289  if(_cursor!=NULL){
290#ifdef DEBUG
291    fprintf(stderr,"freeMap\n");
292#endif
293    free(_cursor->name);
294    free(_cursor->value);
295    if(_cursor->next!=NULL){
296      freeMap(&_cursor->next);
297      free(_cursor->next);
298    }
299  }
300}
301
302/**
303 * Free allocated memory of a maps.
304 * Require to call free on mo after calling this function.
305 *
306 * @param mo the maps to free
307 */
308void freeMaps(maps** mo){
309  maps* _cursor=*mo;
310  if(_cursor && _cursor!=NULL){
311#ifdef DEBUG
312    fprintf(stderr,"freeMaps\n");
313#endif
314    free(_cursor->name);
315    if(_cursor->content!=NULL){
316      freeMap(&_cursor->content);
317      free(_cursor->content);
318    }
319    if(_cursor->child!=NULL){
320      freeMaps(&_cursor->child);
321      free(_cursor->child);
322    }
323    if(_cursor->next!=NULL){
324      freeMaps(&_cursor->next);
325      free(_cursor->next);
326    }
327  }
328}
329
330/**
331 * Verify if an elements contains a name equal to the given key.
332 *
333 * @param e the elements to search for the key
334 * @param key the elements name to search
335 * @return true if the elements contains the name, false in other cases.
336 */ 
337bool hasElement(elements* e,const char* key){
338  elements* tmp=e;
339  while(tmp!=NULL){
340    if(strcasecmp(key,tmp->name)==0)
341      return true;
342    tmp=tmp->next;
343  }
344  return false;
345}
346
347/**
348 * Access a specific elements named key.
349 *
350 * @param m the elements to search
351 * @param key the elements name to search
352 * @return a pointer to the specific element if found, NULL in other case.
353 */ 
354elements* getElements(elements* m,char *key){
355  elements* tmp=m;
356  while(tmp!=NULL){
357    if(strcasecmp(tmp->name,key)==0)
358      return tmp;
359    tmp=tmp->next;
360  }
361  return NULL;
362}
363
364/**
365 * Free allocated memory of an iotype.
366 * Require to call free on i after calling this function.
367 *
368 * @param i the iotype to free
369 */
370void freeIOType(iotype** i){
371  iotype* _cursor=*i;
372  if(_cursor!=NULL){
373    if(_cursor->next!=NULL){
374      freeIOType(&_cursor->next);
375      free(_cursor->next);
376    }
377    freeMap(&_cursor->content);
378    free(_cursor->content);
379  }
380}
381
382/**
383 * Free allocated memory of an elements.
384 * Require to call free on e after calling this function.
385 *
386 * @param e the iotype to free
387 */
388void freeElements(elements** e){
389  elements* tmp=*e;
390  if(tmp!=NULL){
391    if(tmp->name!=NULL)
392      free(tmp->name);
393    freeMap(&tmp->content);
394    if(tmp->content!=NULL)
395      free(tmp->content);
396    freeMap(&tmp->metadata);
397    if(tmp->metadata!=NULL)
398      free(tmp->metadata);
399    if(tmp->format!=NULL)
400      free(tmp->format);
401    if(tmp->child!=NULL){
402      freeElements(&tmp->child);
403      free(tmp->child);
404    }
405    freeIOType(&tmp->defaults);
406    if(tmp->defaults!=NULL)
407      free(tmp->defaults);
408    freeIOType(&tmp->supported);
409    if(tmp->supported!=NULL){
410      free(tmp->supported);
411    }
412    freeElements(&tmp->next);
413    if(tmp->next!=NULL)
414      free(tmp->next);
415  }
416}
417
418/**
419 * Free allocated memory of a service.
420 * Require to call free on e after calling this function.
421 *
422 * @param s the service to free
423 */
424void freeService(service** s){
425  service* tmp=*s;
426  if(tmp!=NULL){
427    if(tmp->name!=NULL)
428      free(tmp->name);
429    freeMap(&tmp->content);
430    if(tmp->content!=NULL)
431      free(tmp->content);
432    freeMap(&tmp->metadata);
433    if(tmp->metadata!=NULL)
434      free(tmp->metadata);
435    freeElements(&tmp->inputs);
436    if(tmp->inputs!=NULL)
437      free(tmp->inputs);
438    freeElements(&tmp->outputs);
439    if(tmp->outputs!=NULL)
440      free(tmp->outputs);
441  }
442}
443
444/**
445 * Add key value pair to an existing map.
446 *
447 * @param m the map to add the KVP
448 * @param n the key to add
449 * @param v the corresponding value to add
450 */
451void addToMap(map* m,const char* n,const char* v){
452  if(hasKey(m,n)==false){
453    map* _cursor=m;
454    while(_cursor->next!=NULL){
455      _cursor=_cursor->next;
456    }
457    _cursor->next=createMap(n,v);
458  }
459  else{
460    map *tmp=getMap(m,n);
461    if(tmp->value!=NULL)
462      free(tmp->value);
463    tmp->value=zStrdup(v);
464  }
465}
466
467/**
468 * Add a key and an integer value to an existing map.
469 *
470 * @param m the map to add the KVP
471 * @param n the key to add
472 * @param v the corresponding value to add
473 */
474void addIntToMap(map* m,const char* n,const int v){
475  char svalue[10];
476  sprintf(svalue,"%d",v);
477  if(hasKey(m,n)==false){
478    map* _cursor=m;
479    while(_cursor->next!=NULL){
480      _cursor=_cursor->next;
481    }
482    _cursor->next=createMap(n,svalue);
483  }
484  else{
485    map *tmp=getMap(m,n);
486    if(tmp->value!=NULL)
487      free(tmp->value);
488    tmp->value=zStrdup(svalue);
489  }
490}
491
492/**
493 * Add a key and a binary value to an existing map.
494 *
495 * @param m the map to add the KVP
496 * @param n the key to add
497 * @param v the corresponding value to add
498 * @param size the size of the given value
499 * @return a pointer to the updated map m
500 */
501map* addToMapWithSize(map* m,const char* n,const char* v,int size){
502  if(hasKey(m,n)==false){
503    map* _cursor=m;
504    if(_cursor!=NULL){
505      addToMap(m,n,"");
506    }else{
507      m=createMap(n,"");
508    }
509  }
510  char sname[10]="size";
511  if(strlen(n)>5)
512    sprintf(sname,"size_%s",n+6);
513  map *tmp=getMap(m,n);
514  if(tmp->value!=NULL)
515    free(tmp->value);
516  tmp->value=(char*)malloc((size+1)*sizeof(char));
517  if(v!=NULL)
518    memmove(tmp->value,v,size*sizeof(char));
519  tmp->value[size]=0;
520  char sin[128];
521  sprintf(sin,"%d",size);
522  addToMap(m,sname,sin);
523  return m;
524}
525
526/**
527 * Add a map at the end of another map.
528 *
529 * @param mo the map to add mi
530 * @param mi the map to add to mo
531 */
532void addMapToMap(map** mo,map* mi){
533  map* tmp=mi;
534  map* _cursor=*mo;
535  while(tmp!=NULL){
536    if(_cursor==NULL){
537      *mo=createMap(tmp->name,tmp->value);
538      (*mo)->next=NULL;
539    }
540    else{
541#ifdef DEBUG
542      fprintf(stderr,"_CURSOR\n");
543      dumpMap(_cursor);
544#endif
545      while(_cursor->next!=NULL)
546        _cursor=_cursor->next;
547      map* tmp1=getMap(*mo,tmp->name);
548      if(tmp1==NULL){
549        _cursor->next=createMap(tmp->name,tmp->value);
550      }
551      else{
552        addToMap(*mo,tmp->name,tmp->value);
553      }
554    }
555    _cursor=*mo;
556    tmp=tmp->next;
557#ifdef DEBUG
558    fprintf(stderr,"MO\n");
559    dumpMap(*mo);
560#endif
561  }
562}
563
564/**
565 * Add a map to iotype.
566 *
567 * @param io the iotype to add the map
568 * @param mi the map to add to io
569 */
570void addMapToIoType(iotype** io,map* mi){
571  iotype* tmp=*io;
572  while(tmp->next!=NULL){
573    tmp=tmp->next;
574  }
575  tmp->next=(iotype*)malloc(IOTYPE_SIZE);
576  tmp->next->content=NULL;
577  addMapToMap(&tmp->next->content,mi);
578  tmp->next->next=NULL;
579}
580
581/**
582 * Access a specific map or set its value.
583 *
584 * @param m the map to search for the key
585 * @param key the key to search/add in the map
586 * @param value the value to add if the key does not exist
587 * @return a pointer on the map found or NULL if not found
588 */
589map* getMapOrFill(map** m,const char *key,const char* value){
590  map* tmp=*m;
591  map* tmpMap=getMap(tmp,key);
592  if(tmpMap==NULL){
593    if(tmp!=NULL){
594      addToMap((*m),key,value);
595    }
596    else
597      (*m)=createMap(key,value);
598    tmpMap=getMap(*m,key);
599  }
600  return tmpMap;
601}
602
603/**
604 * Verify if a map is contained in another map.
605 *
606 * @param m the map to search for i
607 * @param i the map to search in m
608 * @return true if i was found in m, false in other case
609 */
610bool contains(map* m,map* i){
611  while(i!=NULL){     
612    if(strcasecmp(i->name,"value")!=0 &&
613       strcasecmp(i->name,"xlink:href")!=0 &&
614       strcasecmp(i->name,"useMapServer")!=0 &&
615       strcasecmp(i->name,"asReference")!=0){
616      map *tmp;
617      if(hasKey(m,i->name) && (tmp=getMap(m,i->name))!=NULL && 
618         strcasecmp(i->value,tmp->value)!=0)
619        return false;
620    }
621    i=i->next;
622  }
623  return true;
624}
625
626/**
627 * Access a specific iotype from an elements.
628 *
629 * @param e the elements to search for the name
630 * @param name the name to search in the elements e
631 * @param values the map to verify it was contained in the defaults or
632 *  supported content of the elements e
633 * @return a pointer on the iotype found or NULL if not found
634 */
635iotype* getIoTypeFromElement(elements* e,char *name, map* values){
636  elements* cursor=e;
637  if(values!=NULL){
638    while(cursor!=NULL){
639      if(strcasecmp(cursor->name,name)==0 && (cursor->defaults!=NULL || cursor->supported!=NULL)){
640        if(contains(cursor->defaults->content,values)==true)
641          return cursor->defaults;
642        else{
643          iotype* tmp=cursor->supported;
644          while(tmp!=NULL){
645            if(contains(tmp->content,values)==true)
646              return tmp;           
647            tmp=tmp->next;
648          }
649        }
650      }
651      cursor=cursor->next;
652    }
653  }else{
654    while(cursor!=NULL){
655      if(strcasecmp(cursor->name,name)==0 && cursor->defaults!=NULL){
656        return cursor->defaults;
657      }
658      cursor=cursor->next;
659    }
660  }
661  return NULL;
662}
663
664/**
665 * Load binary values from a map (in) and add them to another map (out)
666 *
667 * @param out the map to add binaries values
668 * @param in the map containing the binary values to add ti out
669 * @param pos index of the binary in an array (in case of "MapArray")
670 */
671void loadMapBinary(map** out,map* in,int pos){
672  map* size=getMap(in,"size");
673  map *lout=*out;
674  if(size!=NULL && pos>0){
675    char tmp[11];
676    sprintf(tmp,"size_%d",pos);
677    size=getMap(in,tmp);
678    sprintf(tmp,"value_%d",pos);
679    map* tmpVin=getMap(in,tmp);
680    map* tmpVout=getMap(lout,tmp);
681    free(tmpVout->value);
682    tmpVout->value=(char*)malloc((atoi(size->value)+1)*sizeof(char));
683    memmove(tmpVout->value,tmpVin->value,atoi(size->value)*sizeof(char));
684    tmpVout->value[atoi(size->value)]=0;
685  }else{
686    if(size!=NULL){
687      map* tmpVin=getMap(in,"value");
688      map* tmpVout=getMap(lout,"value");
689      free(tmpVout->value);
690      tmpVout->value=(char*)malloc((atoi(size->value)+1)*sizeof(char));
691      memmove(tmpVout->value,tmpVin->value,atoi(size->value)*sizeof(char));
692      tmpVout->value[atoi(size->value)]=0;
693    }
694  }
695}
696 
697/**
698 * Load binary values from a map (in) and add them to another map (out).
699 * This function will take care of MapArray.
700 * @see loadMapBinary
701 *
702 * @param out the map to add binaries values
703 * @param in the map containing the binary values to add ti out
704 */
705void loadMapBinaries(map** out,map* in){
706  map* size=getMap(in,"size");
707  map* length=getMap(in,"length");
708  if(length!=NULL){
709    int len=atoi(length->value);
710    int i=0;
711    for(i=0;i<len;i++){
712      loadMapBinary(out,in,i);
713    }
714  }
715  else
716    if(size!=NULL)
717      loadMapBinary(out,in,-1);
718}
719
720/**
721 * Duplicate a Maps
722 *
723 * @param mo the maps to clone
724 * @return the allocated maps containing a copy of the mo maps
725 */
726maps* dupMaps(maps** mo){
727  maps* _cursor=*mo;
728  maps* res=NULL;
729  if(_cursor!=NULL){
730    res=createMaps(_cursor->name);
731    map* mc=_cursor->content;
732    if(mc!=NULL){
733      addMapToMap(&res->content,mc);
734      loadMapBinaries(&res->content,mc);
735    }
736    maps* mcs=_cursor->child;
737    if(mcs!=NULL){
738      res->child=dupMaps(&mcs);
739    }
740    res->next=dupMaps(&_cursor->next);
741  }
742  return res;
743}
744
745/**
746 * Add a maps at the end of another maps.
747 *
748 * @see addMapToMap, dupMaps, getMaps
749 * @param mo the maps to add mi
750 * @param mi the maps to add to mo
751 */
752void addMapsToMaps(maps** mo,maps* mi){
753  maps* tmp=mi;
754  maps* _cursor=*mo;
755  while(tmp!=NULL){
756    if(_cursor==NULL){
757      *mo=dupMaps(&mi);
758    }
759    else{
760      while(_cursor->next!=NULL)
761        _cursor=_cursor->next;
762      maps* tmp1=getMaps(*mo,tmp->name);
763      if(tmp1==NULL){
764        _cursor->next=dupMaps(&tmp);
765        if(tmp->child!=NULL)
766          _cursor->next->child=dupMaps(&tmp->child);
767        else
768          _cursor->next->child=NULL;
769      }
770      else{
771        addMapToMap(&tmp1->content,tmp->content);
772        if(tmp->child!=NULL)
773          tmp1->child=dupMaps(&tmp->child);
774        else
775          tmp1->child=NULL;
776      }
777      _cursor=*mo;
778    }
779    tmp=tmp->next;
780  }
781}
782
783/**
784 * Access a specific map array element
785 *
786 * @param m the map to search for the key
787 * @param key the key to search in the map
788 * @param index of the MapArray
789 * @return a pointer on the map found or NULL if not found
790 */
791map* getMapArray(map* m,const char* key,int index){
792  char tmp[1024];
793  if(index>0)
794    sprintf(tmp,"%s_%d",key,index);
795  else
796    sprintf(tmp,"%s",key);
797#ifdef DEBUG
798  fprintf(stderr,"** KEY %s\n",tmp);
799#endif
800  map* tmpMap=getMap(m,tmp);
801#ifdef DEBUG
802  if(tmpMap!=NULL)
803    dumpMap(tmpMap);
804#endif
805  return tmpMap;
806}
807
808/**
809 * Add a key value in a MapArray for a specific index
810 *
811 * @param m the map to search for the key
812 * @param key the key to search in the map
813 * @param index the index of the MapArray
814 * @param value the value to set in the MapArray
815 * @return a pointer on the map found or NULL if not found
816 */
817void setMapArray(map* m,const char* key,int index,const char* value){
818  char tmp[1024];
819  if(index>0){
820    sprintf(tmp,"%s_%d",key,index);
821    map* len=getMap(m,"length");
822    if((len!=NULL && atoi(len->value)<index+1) || len==NULL){
823      char tmp0[5];
824      sprintf(tmp0,"%d",index+1);
825      addToMap(m,"length",tmp0);
826    }
827  }
828  else
829    sprintf(tmp,"%s",key);
830  map* tmpSize=getMapArray(m,"size",index);
831  if(tmpSize!=NULL && strncasecmp(key,"value",5)==0){
832#ifdef DEBUG
833    fprintf(stderr,"%s\n",tmpSize->value);
834#endif
835    map* ptr=getMapOrFill(&m,tmp,(char *)"");
836    free(ptr->value);
837    ptr->value=(char*)malloc((atoi(tmpSize->value)+1)*sizeof(char));
838    memcpy(ptr->value,value,atoi(tmpSize->value)); 
839  }
840  else
841    addToMap(m,tmp,value);
842}
843
844/**
845 * Access the map "type"
846 *
847 * @param mt the map
848 * @return a pointer on the map for mimeType/dataType/CRS if found, NULL in
849 *  other case
850 */
851map* getMapType(map* mt){
852  map* tmap=getMap(mt,(char *)"mimeType");
853  if(tmap==NULL){
854    tmap=getMap(mt,"dataType");
855    if(tmap==NULL){
856      tmap=getMap(mt,"CRS");
857    }
858  }
859#ifdef DEBUG
860  dumpMap(tmap);
861#endif
862  return tmap;
863}
864
865/**
866 * Add a Maps containing a MapArray to a Maps
867 *
868 * @see getMapType
869 * @param mo the maps
870 * @param mi the maps
871 * @param typ the map "type"
872 * @return
873 */
874int addMapsArrayToMaps(maps** mo,maps* mi,char* typ){
875  maps* tmp=mi;   
876  maps* _cursor=getMaps(*mo,tmp->name);
877
878  if(_cursor==NULL)
879    return -1;
880
881  map* tmpLength=getMap(_cursor->content,"length");
882  char tmpLen[10];
883  int len=1;
884  if(tmpLength!=NULL){
885    len=atoi(tmpLength->value);
886  }
887
888  char *tmpV[12]={
889    (char*)"size",
890    (char*)"value",
891    (char*)"uom",
892    (char*)"Reference",
893    (char*)"Order",
894    (char*)"cache_file",
895    (char*)"fmimeType",
896    (char*)"xlink:href",
897    typ,
898    (char*)"schema",
899    (char*)"encoding",
900    (char*)"isCached"
901  };
902  sprintf(tmpLen,"%d",len+1);
903  addToMap(_cursor->content,"length",tmpLen);
904  int i=0;
905  for(i=0;i<12;i++){
906    map* tmpVI=getMap(tmp->content,tmpV[i]);
907    if(tmpVI!=NULL){
908#ifdef DEBUG
909      fprintf(stderr,"%s = %s\n",tmpV[i],tmpVI->value);
910#endif
911      setMapArray(_cursor->content,tmpV[i],len,tmpVI->value);
912    }
913  }
914   
915  addToMap(_cursor->content,"isArray","true");
916  return 0;
917}
918
919/**
920 * Set a key value pair to a map contained in a Maps
921 *
922 * @param m the maps
923 * @param key the maps name
924 * @param subkey the map name included in the maps corresponding to key
925 * @param value the corresponding value to add in the map
926 */
927void setMapInMaps(maps* m,const char* key,const char* subkey,const char *value){
928  maps* _tmpm=getMaps(m,key);
929  if(_tmpm!=NULL){
930    map* _ztmpm=getMap(_tmpm->content,subkey);
931    if(_ztmpm!=NULL){
932      if(_ztmpm->value!=NULL)
933        free(_ztmpm->value);
934      _ztmpm->value=zStrdup(value);
935    }else{
936      maps *tmp=createMaps(key);
937      tmp->content=createMap(subkey,value);
938      addMapsToMaps(&_tmpm,tmp);
939      freeMaps(&tmp);
940      free(tmp);
941    }
942  }else{
943    maps *tmp=createMaps(key);
944    tmp->content=createMap(subkey,value);
945    addMapsToMaps(&m,tmp);
946    freeMaps(&tmp);
947    free(tmp);
948  }
949}
950
951/**
952 * Create an empty elements
953 *
954 * @return a pointer to the allocated elements
955 */
956elements* createEmptyElements(){
957  elements* res=(elements*)malloc(ELEMENTS_SIZE);
958  res->name=NULL;
959  res->content=NULL;
960  res->metadata=NULL;
961  res->format=NULL;
962  res->defaults=NULL;
963  res->supported=NULL;
964  res->child=NULL;
965  res->next=NULL;
966  return res;
967}
968
969/**
970 * Create a named elements
971 *
972 * @param name the elements name
973 * @return a pointer to the allocated elements
974 */
975elements* createElements(char* name){
976  elements* res=(elements*)malloc(ELEMENTS_SIZE);
977  res->name=zStrdup(name);
978  res->content=NULL;
979  res->metadata=NULL;
980  res->format=NULL;
981  res->defaults=NULL;
982  res->supported=NULL;
983  res->child=NULL;
984  res->next=NULL;
985  return res;
986}
987
988/**
989 * Set the name of an elements
990 *
991 * @param name the elements name
992 * @return a pointer to the allocated elements
993 */
994void setElementsName(elements** elem,char* name){
995  elements* res=*elem;
996  res->name=zStrdup(name);
997  res->content=NULL;
998  res->metadata=NULL;
999  res->format=NULL;
1000  res->defaults=NULL;
1001  res->supported=NULL;
1002  res->child=NULL;
1003  res->next=NULL;
1004}
1005
1006/**
1007 * Dump an elements on stderr
1008 *
1009 * @param e the elements to dump
1010 */
1011void dumpElements(elements* e){
1012  elements* tmp=e;
1013  while(tmp!=NULL){
1014    fprintf(stderr,"ELEMENT [%s]\n",tmp->name);
1015    fprintf(stderr," > CONTENT [%s]\n",tmp->name);
1016    dumpMap(tmp->content);
1017    fprintf(stderr," > METADATA [%s]\n",tmp->name);
1018    dumpMap(tmp->metadata);
1019    fprintf(stderr," > FORMAT [%s]\n",tmp->format);
1020    iotype* tmpio=tmp->defaults;
1021    int ioc=0;
1022    while(tmpio!=NULL){
1023      fprintf(stderr," > DEFAULTS [%s] (%i)\n",tmp->name,ioc);
1024      dumpMap(tmpio->content);
1025      tmpio=tmpio->next;
1026      ioc++;
1027    }
1028    tmpio=tmp->supported;
1029    ioc=0;
1030    while(tmpio!=NULL){
1031      fprintf(stderr," > SUPPORTED [%s] (%i)\n",tmp->name,ioc);
1032      dumpMap(tmpio->content);
1033      tmpio=tmpio->next;
1034      ioc++;
1035    }
1036    if(tmp->child!=NULL){
1037      fprintf(stderr," > CHILD \n");
1038      dumpElements(tmp->child);
1039    }
1040    fprintf(stderr,"------------------\n");
1041    tmp=tmp->next;
1042  }
1043}
1044
1045/**
1046 * Dump an elements on stderr using the YAML syntaxe
1047 *
1048 * @param e the elements to dump
1049 */
1050void dumpElementsAsYAML(elements* e,int level){
1051  elements* tmp=e;
1052  int i;
1053  while(tmp!=NULL){
1054    for(i=0;i<2+(4*level);i++)
1055      fprintf(stderr," ");
1056    fprintf(stderr,"%s:\n",tmp->name);
1057    map* mcurs=tmp->content;
1058    while(mcurs!=NULL){
1059      for(i=0;i<4+(4*level);i++)
1060        fprintf(stderr," ");
1061      _dumpMap(mcurs);
1062      mcurs=mcurs->next;
1063    }
1064    mcurs=tmp->metadata;
1065    if(mcurs!=NULL){
1066      for(i=0;i<4+(4*level);i++)
1067        fprintf(stderr," ");
1068      fprintf(stderr,"MetaData:\n");
1069      while(mcurs!=NULL){
1070        for(i=0;i<6+(4*level);i++)
1071          fprintf(stderr," ");
1072        _dumpMap(mcurs);
1073        mcurs=mcurs->next;
1074      }
1075    }
1076    for(i=0;i<4+(4*level);i++)
1077      fprintf(stderr," ");
1078    if(tmp->format!=NULL)
1079      fprintf(stderr,"%s:\n",tmp->format);
1080    else{
1081      fprintf(stderr,"Child:\n");
1082      if(tmp->child!=NULL)
1083        dumpElementsAsYAML(tmp->child,level+1);
1084    }
1085    iotype* tmpio=tmp->defaults;
1086    int ioc=0;
1087    while(tmpio!=NULL){
1088      for(i=0;i<6+(4*level);i++)
1089        fprintf(stderr," ");
1090      fprintf(stderr,"default:\n");
1091      mcurs=tmpio->content;
1092      while(mcurs!=NULL){
1093        for(i=0;i<8+(4*level);i++)
1094          fprintf(stderr," ");
1095        if(strcasecmp(mcurs->name,"range")==0){
1096          fprintf(stderr,"range: \"%s\"\n",mcurs->value);
1097        }else
1098          _dumpMap(mcurs);
1099        mcurs=mcurs->next;
1100      }
1101      tmpio=tmpio->next;
1102      ioc++;
1103    }
1104    tmpio=tmp->supported;
1105    ioc=0;
1106    while(tmpio!=NULL){
1107      for(i=0;i<6+(4*level);i++)
1108        fprintf(stderr," ");
1109      fprintf(stderr,"supported:\n");
1110      mcurs=tmpio->content;
1111      while(mcurs!=NULL){
1112        for(i=0;i<8+(4*level);i++)
1113          fprintf(stderr," ");
1114        if(strcasecmp(mcurs->name,"range")==0){
1115          fprintf(stderr,"range: \"%s\"\n",mcurs->value);
1116        }else
1117          _dumpMap(mcurs);
1118        mcurs=mcurs->next;
1119      }
1120      tmpio=tmpio->next;
1121      ioc++;
1122    }
1123    tmp=tmp->next;
1124  }
1125}
1126
1127/**
1128 * Duplicate an elements
1129 *
1130 * @param e the elements to clone
1131 * @return the allocated elements containing a copy of the elements e
1132 */
1133elements* dupElements(elements* e){
1134  elements* cursor=e;
1135  elements* tmp=NULL;
1136  if(cursor!=NULL){
1137#ifdef DEBUG
1138    fprintf(stderr,">> %s %i\n",__FILE__,__LINE__);
1139    dumpElements(e);
1140    fprintf(stderr,">> %s %i\n",__FILE__,__LINE__);
1141#endif
1142    tmp=(elements*)malloc(ELEMENTS_SIZE);
1143    tmp->name=zStrdup(e->name);
1144    tmp->content=NULL;
1145    addMapToMap(&tmp->content,e->content);
1146    tmp->metadata=NULL;
1147    addMapToMap(&tmp->metadata,e->metadata);
1148    if(e->format!=NULL)
1149      tmp->format=zStrdup(e->format);
1150    else
1151      tmp->format=NULL;
1152    if(e->defaults!=NULL){
1153      tmp->defaults=(iotype*)malloc(IOTYPE_SIZE);
1154      tmp->defaults->content=NULL;
1155      addMapToMap(&tmp->defaults->content,e->defaults->content);
1156      tmp->defaults->next=NULL;
1157#ifdef DEBUG
1158      fprintf(stderr,">> %s %i\n",__FILE__,__LINE__);
1159      dumpMap(tmp->defaults->content);
1160#endif
1161    }else
1162      tmp->defaults=NULL;
1163    if(e->supported!=NULL){
1164      tmp->supported=(iotype*)malloc(IOTYPE_SIZE);
1165      tmp->supported->content=NULL;
1166      addMapToMap(&tmp->supported->content,e->supported->content);
1167      tmp->supported->next=NULL;
1168      iotype *tmp2=e->supported->next;
1169      while(tmp2!=NULL){
1170        addMapToIoType(&tmp->supported,tmp2->content);
1171#ifdef DEBUG
1172        fprintf(stderr,">> %s %i\n",__FILE__,__LINE__);
1173        dumpMap(tmp->defaults->content);
1174#endif
1175        tmp2=tmp2->next;
1176      }
1177    }
1178    else
1179      tmp->supported=NULL;
1180    if(cursor->child!=NULL)
1181      tmp->child=dupElements(cursor->child);
1182    else
1183      tmp->child=NULL;
1184    tmp->next=dupElements(cursor->next);
1185  }
1186  return tmp;
1187}
1188
1189/**
1190 * Add an elements to another elements.
1191 *
1192 * @see dupElements
1193 * @param m the elements to add the e
1194 * @param e the elements to be added to m
1195 */
1196void addToElements(elements** m,elements* e){
1197  elements* tmp=e;
1198  if(*m==NULL){
1199    *m=dupElements(tmp);
1200  }else{
1201    addToElements(&(*m)->next,tmp);
1202  }
1203}
1204
1205/**
1206 * Set the name of a service
1207 *
1208 * @param name the service name
1209 */
1210void setServiceName(service** serv,char* name){
1211  service* res=*serv;
1212  res->name=zStrdup(name);
1213  res->content=NULL;
1214  res->metadata=NULL;
1215  res->inputs=NULL;
1216  res->outputs=NULL;
1217}
1218
1219/**
1220 * Dump a service on stderr
1221 *
1222 * @param s the service to dump
1223 */
1224void dumpService(service* s){
1225  if(s==NULL)
1226    return;
1227  fprintf(stderr,"++++++++++++++++++\nSERVICE [%s]\n++++++++++++++++++\n",s->name);
1228  if(s->content!=NULL){
1229    fprintf(stderr,"CONTENT MAP\n");
1230    dumpMap(s->content);
1231    fprintf(stderr,"CONTENT METADATA\n");
1232    dumpMap(s->metadata);
1233  }
1234  if(s->inputs!=NULL){
1235    fprintf(stderr,"INPUT ELEMENTS [%s]\n------------------\n",s->name);
1236    dumpElements(s->inputs);
1237  }
1238  if(s->outputs!=NULL){
1239    fprintf(stderr,"OUTPUT ELEMENTS [%s]\n------------------\n",s->name);
1240    dumpElements(s->outputs);
1241  }
1242  fprintf(stderr,"++++++++++++++++++\n");
1243}
1244
1245/**
1246 * Dump a service on stderr using the YAML syntaxe
1247 *
1248 * @param s the service to dump
1249 */
1250void dumpServiceAsYAML(service* s){
1251  int i;
1252  fprintf(stderr,"# %s\n\n",s->name);
1253  if(s->content!=NULL){
1254    map* mcurs=s->content;
1255    dumpMap(mcurs);
1256    mcurs=s->metadata;
1257    if(mcurs!=NULL){
1258      fprintf(stderr,"MetaData:\n");
1259      while(mcurs!=NULL){
1260        for(i=0;i<2;i++)
1261          fprintf(stderr," ");
1262        _dumpMap(mcurs);
1263        mcurs=mcurs->next;
1264      }
1265    }
1266  }
1267  if(s->inputs!=NULL){
1268    fprintf(stderr,"\ninputs:\n");
1269    dumpElementsAsYAML(s->inputs,0);
1270  }
1271  if(s->outputs!=NULL){
1272    fprintf(stderr,"\noutputs:\n");
1273    dumpElementsAsYAML(s->outputs,0);
1274  }
1275}
1276
1277/**
1278 * Duplicate a service
1279 *
1280 * @param s the service to clone
1281 * @return the allocated service containing a copy of the serfvice s
1282 */
1283service* dupService(service* s){
1284  service *res=(service*)malloc(SERVICE_SIZE);
1285  res->name=zStrdup(s->name);
1286  res->content=NULL;
1287  addMapToMap(&res->content,s->content);
1288  res->metadata=NULL;
1289  addMapToMap(&res->metadata,s->metadata);
1290  res->inputs=dupElements(s->inputs);
1291  res->outputs=dupElements(s->outputs);
1292  return res;
1293}
1294
1295/**
1296 * Print the registry on stderr.
1297 *
1298 * @param r the registry
1299 */
1300void dumpRegistry(registry* r){
1301  registry* p=r;
1302  while(p!=NULL){
1303    fprintf(stderr,"%s \n",p->name);
1304    services* s=p->content;
1305    s=p->content;
1306    while(s!=NULL){
1307      dumpService(s->content);
1308      s=s->next;
1309    }
1310    p=p->next;
1311  }
1312}
1313
1314/**
1315 * Add a service to the registry
1316 *
1317 * @param reg the resgitry to add the service
1318 * @param name the registry name to update
1319 * @param content the service to add
1320 */
1321bool addServiceToRegistry(registry** reg,char* name,service* content){
1322  registry *l=*reg;
1323  int isInitial=-1;
1324  if(l==NULL){
1325    l=(registry*)malloc(REGISTRY_SIZE);
1326    isInitial=1;
1327  }
1328  if(l!=NULL){
1329    int hasLevel=-1;
1330    while(isInitial<0 && l!=NULL){
1331      if(l->name!=NULL && strcasecmp(name,l->name)==0){
1332        hasLevel=1;
1333        break;
1334      }
1335      l=l->next;
1336    }
1337    if(hasLevel<0){
1338      if(isInitial<0)
1339        l=(registry*)malloc(REGISTRY_SIZE);
1340      l->name=zStrdup(name);
1341      l->content=NULL;
1342      l->next=NULL;
1343    }
1344    if(l->content==NULL){
1345      l->content=(services*)malloc(SERVICES_SIZE);
1346      l->content->content=dupService(content);
1347      l->content->next=NULL;
1348    }
1349    else{
1350      services* s=l->content;
1351      while(s->next!=NULL)
1352        s=s->next;
1353      s->next=(services*)malloc(SERVICES_SIZE);
1354      s->next->content=dupService(content);
1355      s->next->next=NULL;
1356    }
1357    l->next=NULL;
1358    if(isInitial>0)
1359      *reg=l;
1360    else{
1361      registry *r=*reg;
1362      while(r->next!=NULL)
1363        r=r->next;
1364      r->next=l;
1365      r->next->next=NULL;
1366    }
1367    return true;
1368  }
1369  else
1370    return false;
1371}
1372
1373/**
1374 * Free memory allocated for the registry
1375 *
1376 * @param r the registry
1377 */
1378void freeRegistry(registry** r){
1379  registry* lr=*r;
1380  while(lr!=NULL){
1381    services* s=lr->content;
1382    free(lr->name);
1383    while(s!=NULL){
1384      service* s1=s->content;
1385      s=s->next;
1386      if(s1!=NULL){
1387        freeService(&s1);
1388        free(s1);
1389        s1=NULL;
1390      }
1391    }
1392    lr=lr->next;
1393  }   
1394}
1395
1396/**
1397 * Access a service in the registry
1398 *
1399 * @param r the registry
1400 * @param level the regitry to search ("concept", "generic" or "implementation")
1401 * @param sname the service name
1402 * @return the service pointer if a corresponding service was found or NULL
1403 */
1404service* getServiceFromRegistry(registry* r,char  *level,char* sname){
1405  registry *lr=r;
1406  while(lr!=NULL){
1407    if(strcasecmp(lr->name,level)==0){
1408      services* s=lr->content;
1409      while(s!=NULL){
1410        if(s->content!=NULL && strcasecmp(s->content->name,sname)==0)
1411          return s->content;
1412        s=s->next;
1413      }
1414      break;
1415    }
1416    lr=lr->next;
1417  }
1418  return NULL;
1419}
1420
1421/**
1422 * Apply inheritance to an out map from a reference in map
1423 *
1424 * @param out the map to update
1425 * @param in the reference map (containing inherited properties)
1426 */
1427void inheritMap(map** out,map* in){
1428  map* content=in;
1429  if((*out)==NULL){
1430    addMapToMap(out,in);
1431    return;
1432  }
1433  while(content!=NULL){
1434    map* cmap=getMap(*out,content->name);
1435    if(cmap==NULL)
1436      addToMap(*out,content->name,content->value);
1437    content=content->next;
1438  }
1439}
1440
1441/**
1442 * Apply inheritance to an out iotype from a reference in iotype
1443 *
1444 * @param out the iotype to update
1445 * @param in the reference iotype (containing inherited properties)
1446 */
1447void inheritIOType(iotype** out,iotype* in){
1448  iotype* io=in;
1449  iotype* oio=*out;
1450  if(io!=NULL){
1451    if(*out==NULL){
1452      *out=(iotype*)malloc(IOTYPE_SIZE);
1453      (*out)->content=NULL;
1454      addMapToMap(&(*out)->content,io->content);
1455      (*out)->next=NULL;
1456      oio=*out;
1457      inheritIOType(&oio->next,io->next);
1458    }else{
1459      inheritIOType(&oio->next,io->next);
1460    }
1461  }
1462}
1463
1464/**
1465 * Apply inheritance to an out elements from a reference in elements
1466 *
1467 * @param out the elements to update
1468 * @param in the reference elements (containing inherited properties)
1469 */
1470void inheritElements(elements** out,elements* in){
1471  elements* content=in;
1472  while(content!=NULL && *out!=NULL){
1473    elements* cmap=getElements(*out,content->name);
1474    if(cmap==NULL)
1475      addToElements(out,content);
1476    else{
1477      inheritMap(&cmap->content,content->content);
1478      inheritMap(&cmap->metadata,content->metadata);
1479      if(cmap->format==NULL && content->format!=NULL)
1480        cmap->format=zStrdup(content->format);
1481      inheritIOType(&cmap->defaults,content->defaults);
1482      if(cmap->supported==NULL)
1483        inheritIOType(&cmap->supported,content->supported);
1484      else{
1485        iotype* p=content->supported;
1486        while(p!=NULL){
1487          addMapToIoType(&cmap->supported,p->content);
1488          p=p->next;
1489        }
1490      }
1491    }
1492    content=content->next;
1493  }
1494}
1495
1496/**
1497 * Apply inheritance to a service based on a registry
1498 *
1499 * @param r the registry storing profiles hierarchy
1500 * @param s the service to update depending on its inheritance
1501 */
1502void inheritance(registry *r,service** s){
1503  if(r==NULL)
1504    return;
1505  service* ls=*s;
1506  if(ls->content==NULL)
1507    return;
1508  map* profile=getMap(ls->content,"extend");
1509  map* level=getMap(ls->content,"level");
1510  if(profile!=NULL&&level!=NULL){
1511    service* s1;
1512    if(strncasecmp(level->value,"profile",7)==0)
1513      s1=getServiceFromRegistry(r,(char*)"generic",profile->value);
1514    else
1515      s1=getServiceFromRegistry(r,level->value,profile->value);
1516     
1517    inheritMap(&ls->content,s1->content);
1518    inheritMap(&ls->metadata,s1->metadata);
1519    if(ls->inputs==NULL && s1->inputs!=NULL){
1520      ls->inputs=dupElements(s1->inputs);
1521    }else{
1522      inheritElements(&ls->inputs,s1->inputs);
1523    }
1524    if(ls->outputs==NULL && s1->outputs!=NULL){
1525      ls->outputs=dupElements(s1->outputs);
1526    }else
1527      inheritElements(&ls->outputs,s1->outputs);
1528  }
1529}
1530
1531/**
1532 * Convert a maps to a char*** (only used for Fortran support)
1533 *
1534 * @param m the maps to convert
1535 * @param c the resulting array
1536 */
1537void mapsToCharXXX(maps* m,char*** c){
1538  maps* tm=m;
1539  int i=0;
1540  int j=0;
1541  char tmp[10][30][1024];
1542  memset(tmp,0,1024*10*10);
1543  while(tm!=NULL){
1544    if(i>=10)
1545      break;
1546    strcpy(tmp[i][j],"name");
1547    j++;
1548    strcpy(tmp[i][j],tm->name);
1549    j++;
1550    map* tc=tm->content;
1551    while(tc!=NULL){
1552      if(j>=30)
1553        break;
1554      strcpy(tmp[i][j],tc->name);
1555      j++;
1556      strcpy(tmp[i][j],tc->value);
1557      j++;
1558      tc=tc->next;
1559    }
1560    tm=tm->next;
1561    j=0;
1562    i++;
1563  }
1564  memcpy(c,tmp,10*10*1024);
1565}
1566
1567/**
1568 * Convert a char*** to a maps (only used for Fortran support)
1569 *
1570 * @param c the array to convert
1571 * @param m the resulting maps
1572 */
1573void charxxxToMaps(char*** c,maps**m){
1574  maps* trorf=*m;
1575  int i,j;
1576  char tmp[10][30][1024];
1577  memcpy(tmp,c,10*30*1024);
1578  for(i=0;i<10;i++){
1579    if(strlen(tmp[i][1])==0)
1580      break;
1581    trorf->name=tmp[i][1];
1582    trorf->content=NULL;
1583    trorf->next=NULL;
1584    for(j=2;j<29;j+=2){
1585      if(strlen(tmp[i][j+1])==0)
1586        break;
1587      if(trorf->content==NULL)
1588        trorf->content=createMap(tmp[i][j],tmp[i][j+1]);
1589      else
1590        addToMap(trorf->content,tmp[i][j],tmp[i][j+1]);
1591    }
1592    trorf=trorf->next;
1593  }
1594  m=&trorf;
1595}
Note: See TracBrowser for help on using the repository browser.

Search

ZOO Sponsors

http://www.zoo-project.org/trac/chrome/site/img/geolabs-logo.pnghttp://www.zoo-project.org/trac/chrome/site/img/neogeo-logo.png http://www.zoo-project.org/trac/chrome/site/img/apptech-logo.png http://www.zoo-project.org/trac/chrome/site/img/3liz-logo.png http://www.zoo-project.org/trac/chrome/site/img/gateway-logo.png

Become a sponsor !

Knowledge partners

http://www.zoo-project.org/trac/chrome/site/img/ocu-logo.png http://www.zoo-project.org/trac/chrome/site/img/gucas-logo.png http://www.zoo-project.org/trac/chrome/site/img/polimi-logo.png http://www.zoo-project.org/trac/chrome/site/img/fem-logo.png http://www.zoo-project.org/trac/chrome/site/img/supsi-logo.png http://www.zoo-project.org/trac/chrome/site/img/cumtb-logo.png

Become a knowledge partner

Related links

http://zoo-project.org/img/ogclogo.png http://zoo-project.org/img/osgeologo.png