source: branches/ms-style/zoo-project/zoo-kernel/service.c @ 980

Last change on this file since 980 was 805, checked in by djay, 10 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