source: branches/prototype-v0/zoo-project/zoo-kernel/service.c @ 822

Last change on this file since 822 was 822, checked in by djay, 3 years ago

Commit the minimal requirements for remote HPC support

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