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

Last change on this file since 868 was 868, checked in by djay, 6 years ago

Fix for multiple occurence of a BoundingBox? input (see #163)

  • Property svn:keywords set to Id
File size: 36.5 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[14]={
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    (char*)"LowerCorner",
902    (char*)"UpperCorner"   
903  };
904  sprintf(tmpLen,"%d",len+1);
905  addToMap(_cursor->content,"length",tmpLen);
906  int i=0;
907  for(i=0;i<14;i++){
908    map* tmpVI=getMap(tmp->content,tmpV[i]);
909    if(tmpVI!=NULL){
910#ifdef DEBUG
911      fprintf(stderr,"%s = %s\n",tmpV[i],tmpVI->value);
912#endif
913      setMapArray(_cursor->content,tmpV[i],len,tmpVI->value);
914    }
915  }
916   
917  addToMap(_cursor->content,"isArray","true");
918  return 0;
919}
920
921/**
922 * Set a key value pair to a map contained in a Maps
923 *
924 * @param m the maps
925 * @param key the maps name
926 * @param subkey the map name included in the maps corresponding to key
927 * @param value the corresponding value to add in the map
928 */
929void setMapInMaps(maps* m,const char* key,const char* subkey,const char *value){
930  maps* _tmpm=getMaps(m,key);
931  if(_tmpm!=NULL){
932    map* _ztmpm=getMap(_tmpm->content,subkey);
933    if(_ztmpm!=NULL){
934      if(_ztmpm->value!=NULL)
935        free(_ztmpm->value);
936      _ztmpm->value=zStrdup(value);
937    }else{
938      maps *tmp=createMaps(key);
939      tmp->content=createMap(subkey,value);
940      addMapsToMaps(&_tmpm,tmp);
941      freeMaps(&tmp);
942      free(tmp);
943    }
944  }else{
945    maps *tmp=createMaps(key);
946    tmp->content=createMap(subkey,value);
947    addMapsToMaps(&m,tmp);
948    freeMaps(&tmp);
949    free(tmp);
950  }
951}
952
953/**
954 * Create an empty elements
955 *
956 * @return a pointer to the allocated elements
957 */
958elements* createEmptyElements(){
959  elements* res=(elements*)malloc(ELEMENTS_SIZE);
960  res->name=NULL;
961  res->content=NULL;
962  res->metadata=NULL;
963  res->format=NULL;
964  res->defaults=NULL;
965  res->supported=NULL;
966  res->child=NULL;
967  res->next=NULL;
968  return res;
969}
970
971/**
972 * Create a named elements
973 *
974 * @param name the elements name
975 * @return a pointer to the allocated elements
976 */
977elements* createElements(char* name){
978  elements* res=(elements*)malloc(ELEMENTS_SIZE);
979  res->name=zStrdup(name);
980  res->content=NULL;
981  res->metadata=NULL;
982  res->format=NULL;
983  res->defaults=NULL;
984  res->supported=NULL;
985  res->child=NULL;
986  res->next=NULL;
987  return res;
988}
989
990/**
991 * Set the name of an elements
992 *
993 * @param name the elements name
994 * @return a pointer to the allocated elements
995 */
996void setElementsName(elements** elem,char* name){
997  elements* res=*elem;
998  res->name=zStrdup(name);
999  res->content=NULL;
1000  res->metadata=NULL;
1001  res->format=NULL;
1002  res->defaults=NULL;
1003  res->supported=NULL;
1004  res->child=NULL;
1005  res->next=NULL;
1006}
1007
1008/**
1009 * Dump an elements on stderr
1010 *
1011 * @param e the elements to dump
1012 */
1013void dumpElements(elements* e){
1014  elements* tmp=e;
1015  while(tmp!=NULL){
1016    fprintf(stderr,"ELEMENT [%s]\n",tmp->name);
1017    fprintf(stderr," > CONTENT [%s]\n",tmp->name);
1018    dumpMap(tmp->content);
1019    fprintf(stderr," > METADATA [%s]\n",tmp->name);
1020    dumpMap(tmp->metadata);
1021    fprintf(stderr," > FORMAT [%s]\n",tmp->format);
1022    iotype* tmpio=tmp->defaults;
1023    int ioc=0;
1024    while(tmpio!=NULL){
1025      fprintf(stderr," > DEFAULTS [%s] (%i)\n",tmp->name,ioc);
1026      dumpMap(tmpio->content);
1027      tmpio=tmpio->next;
1028      ioc++;
1029    }
1030    tmpio=tmp->supported;
1031    ioc=0;
1032    while(tmpio!=NULL){
1033      fprintf(stderr," > SUPPORTED [%s] (%i)\n",tmp->name,ioc);
1034      dumpMap(tmpio->content);
1035      tmpio=tmpio->next;
1036      ioc++;
1037    }
1038    if(tmp->child!=NULL){
1039      fprintf(stderr," > CHILD \n");
1040      dumpElements(tmp->child);
1041    }
1042    fprintf(stderr,"------------------\n");
1043    tmp=tmp->next;
1044  }
1045}
1046
1047/**
1048 * Dump an elements on stderr using the YAML syntaxe
1049 *
1050 * @param e the elements to dump
1051 */
1052void dumpElementsAsYAML(elements* e,int level){
1053  elements* tmp=e;
1054  int i;
1055  while(tmp!=NULL){
1056    for(i=0;i<2+(4*level);i++)
1057      fprintf(stderr," ");
1058    fprintf(stderr,"%s:\n",tmp->name);
1059    map* mcurs=tmp->content;
1060    while(mcurs!=NULL){
1061      for(i=0;i<4+(4*level);i++)
1062        fprintf(stderr," ");
1063      _dumpMap(mcurs);
1064      mcurs=mcurs->next;
1065    }
1066    mcurs=tmp->metadata;
1067    if(mcurs!=NULL){
1068      for(i=0;i<4+(4*level);i++)
1069        fprintf(stderr," ");
1070      fprintf(stderr,"MetaData:\n");
1071      while(mcurs!=NULL){
1072        for(i=0;i<6+(4*level);i++)
1073          fprintf(stderr," ");
1074        _dumpMap(mcurs);
1075        mcurs=mcurs->next;
1076      }
1077    }
1078    for(i=0;i<4+(4*level);i++)
1079      fprintf(stderr," ");
1080    if(tmp->format!=NULL)
1081      fprintf(stderr,"%s:\n",tmp->format);
1082    else{
1083      fprintf(stderr,"Child:\n");
1084      if(tmp->child!=NULL)
1085        dumpElementsAsYAML(tmp->child,level+1);
1086    }
1087    iotype* tmpio=tmp->defaults;
1088    int ioc=0;
1089    while(tmpio!=NULL){
1090      for(i=0;i<6+(4*level);i++)
1091        fprintf(stderr," ");
1092      fprintf(stderr,"default:\n");
1093      mcurs=tmpio->content;
1094      while(mcurs!=NULL){
1095        for(i=0;i<8+(4*level);i++)
1096          fprintf(stderr," ");
1097        if(strcasecmp(mcurs->name,"range")==0){
1098          fprintf(stderr,"range: \"%s\"\n",mcurs->value);
1099        }else
1100          _dumpMap(mcurs);
1101        mcurs=mcurs->next;
1102      }
1103      tmpio=tmpio->next;
1104      ioc++;
1105    }
1106    tmpio=tmp->supported;
1107    ioc=0;
1108    while(tmpio!=NULL){
1109      for(i=0;i<6+(4*level);i++)
1110        fprintf(stderr," ");
1111      fprintf(stderr,"supported:\n");
1112      mcurs=tmpio->content;
1113      while(mcurs!=NULL){
1114        for(i=0;i<8+(4*level);i++)
1115          fprintf(stderr," ");
1116        if(strcasecmp(mcurs->name,"range")==0){
1117          fprintf(stderr,"range: \"%s\"\n",mcurs->value);
1118        }else
1119          _dumpMap(mcurs);
1120        mcurs=mcurs->next;
1121      }
1122      tmpio=tmpio->next;
1123      ioc++;
1124    }
1125    tmp=tmp->next;
1126  }
1127}
1128
1129/**
1130 * Duplicate an elements
1131 *
1132 * @param e the elements to clone
1133 * @return the allocated elements containing a copy of the elements e
1134 */
1135elements* dupElements(elements* e){
1136  elements* cursor=e;
1137  elements* tmp=NULL;
1138  if(cursor!=NULL){
1139#ifdef DEBUG
1140    fprintf(stderr,">> %s %i\n",__FILE__,__LINE__);
1141    dumpElements(e);
1142    fprintf(stderr,">> %s %i\n",__FILE__,__LINE__);
1143#endif
1144    tmp=(elements*)malloc(ELEMENTS_SIZE);
1145    tmp->name=zStrdup(e->name);
1146    tmp->content=NULL;
1147    addMapToMap(&tmp->content,e->content);
1148    tmp->metadata=NULL;
1149    addMapToMap(&tmp->metadata,e->metadata);
1150    if(e->format!=NULL)
1151      tmp->format=zStrdup(e->format);
1152    else
1153      tmp->format=NULL;
1154    if(e->defaults!=NULL){
1155      tmp->defaults=(iotype*)malloc(IOTYPE_SIZE);
1156      tmp->defaults->content=NULL;
1157      addMapToMap(&tmp->defaults->content,e->defaults->content);
1158      tmp->defaults->next=NULL;
1159#ifdef DEBUG
1160      fprintf(stderr,">> %s %i\n",__FILE__,__LINE__);
1161      dumpMap(tmp->defaults->content);
1162#endif
1163    }else
1164      tmp->defaults=NULL;
1165    if(e->supported!=NULL){
1166      tmp->supported=(iotype*)malloc(IOTYPE_SIZE);
1167      tmp->supported->content=NULL;
1168      addMapToMap(&tmp->supported->content,e->supported->content);
1169      tmp->supported->next=NULL;
1170      iotype *tmp2=e->supported->next;
1171      while(tmp2!=NULL){
1172        addMapToIoType(&tmp->supported,tmp2->content);
1173#ifdef DEBUG
1174        fprintf(stderr,">> %s %i\n",__FILE__,__LINE__);
1175        dumpMap(tmp->defaults->content);
1176#endif
1177        tmp2=tmp2->next;
1178      }
1179    }
1180    else
1181      tmp->supported=NULL;
1182    if(cursor->child!=NULL)
1183      tmp->child=dupElements(cursor->child);
1184    else
1185      tmp->child=NULL;
1186    tmp->next=dupElements(cursor->next);
1187  }
1188  return tmp;
1189}
1190
1191/**
1192 * Add an elements to another elements.
1193 *
1194 * @see dupElements
1195 * @param m the elements to add the e
1196 * @param e the elements to be added to m
1197 */
1198void addToElements(elements** m,elements* e){
1199  elements* tmp=e;
1200  if(*m==NULL){
1201    *m=dupElements(tmp);
1202  }else{
1203    addToElements(&(*m)->next,tmp);
1204  }
1205}
1206
1207/**
1208 * Set the name of a service
1209 *
1210 * @param name the service name
1211 */
1212void setServiceName(service** serv,char* name){
1213  service* res=*serv;
1214  res->name=zStrdup(name);
1215  res->content=NULL;
1216  res->metadata=NULL;
1217  res->inputs=NULL;
1218  res->outputs=NULL;
1219}
1220
1221/**
1222 * Dump a service on stderr
1223 *
1224 * @param s the service to dump
1225 */
1226void dumpService(service* s){
1227  if(s==NULL)
1228    return;
1229  fprintf(stderr,"++++++++++++++++++\nSERVICE [%s]\n++++++++++++++++++\n",s->name);
1230  if(s->content!=NULL){
1231    fprintf(stderr,"CONTENT MAP\n");
1232    dumpMap(s->content);
1233    fprintf(stderr,"CONTENT METADATA\n");
1234    dumpMap(s->metadata);
1235  }
1236  if(s->inputs!=NULL){
1237    fprintf(stderr,"INPUT ELEMENTS [%s]\n------------------\n",s->name);
1238    dumpElements(s->inputs);
1239  }
1240  if(s->outputs!=NULL){
1241    fprintf(stderr,"OUTPUT ELEMENTS [%s]\n------------------\n",s->name);
1242    dumpElements(s->outputs);
1243  }
1244  fprintf(stderr,"++++++++++++++++++\n");
1245}
1246
1247/**
1248 * Dump a service on stderr using the YAML syntaxe
1249 *
1250 * @param s the service to dump
1251 */
1252void dumpServiceAsYAML(service* s){
1253  int i;
1254  fprintf(stderr,"# %s\n\n",s->name);
1255  if(s->content!=NULL){
1256    map* mcurs=s->content;
1257    dumpMap(mcurs);
1258    mcurs=s->metadata;
1259    if(mcurs!=NULL){
1260      fprintf(stderr,"MetaData:\n");
1261      while(mcurs!=NULL){
1262        for(i=0;i<2;i++)
1263          fprintf(stderr," ");
1264        _dumpMap(mcurs);
1265        mcurs=mcurs->next;
1266      }
1267    }
1268  }
1269  if(s->inputs!=NULL){
1270    fprintf(stderr,"\ninputs:\n");
1271    dumpElementsAsYAML(s->inputs,0);
1272  }
1273  if(s->outputs!=NULL){
1274    fprintf(stderr,"\noutputs:\n");
1275    dumpElementsAsYAML(s->outputs,0);
1276  }
1277}
1278
1279/**
1280 * Duplicate a service
1281 *
1282 * @param s the service to clone
1283 * @return the allocated service containing a copy of the serfvice s
1284 */
1285service* dupService(service* s){
1286  service *res=(service*)malloc(SERVICE_SIZE);
1287  res->name=zStrdup(s->name);
1288  res->content=NULL;
1289  addMapToMap(&res->content,s->content);
1290  res->metadata=NULL;
1291  addMapToMap(&res->metadata,s->metadata);
1292  res->inputs=dupElements(s->inputs);
1293  res->outputs=dupElements(s->outputs);
1294  return res;
1295}
1296
1297/**
1298 * Print the registry on stderr.
1299 *
1300 * @param r the registry
1301 */
1302void dumpRegistry(registry* r){
1303  registry* p=r;
1304  while(p!=NULL){
1305    fprintf(stderr,"%s \n",p->name);
1306    services* s=p->content;
1307    s=p->content;
1308    while(s!=NULL){
1309      dumpService(s->content);
1310      s=s->next;
1311    }
1312    p=p->next;
1313  }
1314}
1315
1316/**
1317 * Add a service to the registry
1318 *
1319 * @param reg the resgitry to add the service
1320 * @param name the registry name to update
1321 * @param content the service to add
1322 */
1323bool addServiceToRegistry(registry** reg,char* name,service* content){
1324  registry *l=*reg;
1325  int isInitial=-1;
1326  if(l==NULL){
1327    l=(registry*)malloc(REGISTRY_SIZE);
1328    isInitial=1;
1329  }
1330  if(l!=NULL){
1331    int hasLevel=-1;
1332    while(isInitial<0 && l!=NULL){
1333      if(l->name!=NULL && strcasecmp(name,l->name)==0){
1334        hasLevel=1;
1335        break;
1336      }
1337      l=l->next;
1338    }
1339    if(hasLevel<0){
1340      if(isInitial<0)
1341        l=(registry*)malloc(REGISTRY_SIZE);
1342      l->name=zStrdup(name);
1343      l->content=NULL;
1344      l->next=NULL;
1345    }
1346    if(l->content==NULL){
1347      l->content=(services*)malloc(SERVICES_SIZE);
1348      l->content->content=dupService(content);
1349      l->content->next=NULL;
1350    }
1351    else{
1352      services* s=l->content;
1353      while(s->next!=NULL)
1354        s=s->next;
1355      s->next=(services*)malloc(SERVICES_SIZE);
1356      s->next->content=dupService(content);
1357      s->next->next=NULL;
1358    }
1359    l->next=NULL;
1360    if(isInitial>0)
1361      *reg=l;
1362    else{
1363      registry *r=*reg;
1364      while(r->next!=NULL)
1365        r=r->next;
1366      r->next=l;
1367      r->next->next=NULL;
1368    }
1369    return true;
1370  }
1371  else
1372    return false;
1373}
1374
1375/**
1376 * Free memory allocated for the registry
1377 *
1378 * @param r the registry
1379 */
1380void freeRegistry(registry** r){
1381  registry* lr=*r;
1382  while(lr!=NULL){
1383    services* s=lr->content;
1384    free(lr->name);
1385    while(s!=NULL){
1386      service* s1=s->content;
1387      s=s->next;
1388      if(s1!=NULL){
1389        freeService(&s1);
1390        free(s1);
1391        s1=NULL;
1392      }
1393    }
1394    lr=lr->next;
1395  }   
1396}
1397
1398/**
1399 * Access a service in the registry
1400 *
1401 * @param r the registry
1402 * @param level the regitry to search ("concept", "generic" or "implementation")
1403 * @param sname the service name
1404 * @return the service pointer if a corresponding service was found or NULL
1405 */
1406service* getServiceFromRegistry(registry* r,char  *level,char* sname){
1407  registry *lr=r;
1408  while(lr!=NULL){
1409    if(strcasecmp(lr->name,level)==0){
1410      services* s=lr->content;
1411      while(s!=NULL){
1412        if(s->content!=NULL && strcasecmp(s->content->name,sname)==0)
1413          return s->content;
1414        s=s->next;
1415      }
1416      break;
1417    }
1418    lr=lr->next;
1419  }
1420  return NULL;
1421}
1422
1423/**
1424 * Apply inheritance to an out map from a reference in map
1425 *
1426 * @param out the map to update
1427 * @param in the reference map (containing inherited properties)
1428 */
1429void inheritMap(map** out,map* in){
1430  map* content=in;
1431  if((*out)==NULL){
1432    addMapToMap(out,in);
1433    return;
1434  }
1435  while(content!=NULL){
1436    map* cmap=getMap(*out,content->name);
1437    if(cmap==NULL)
1438      addToMap(*out,content->name,content->value);
1439    content=content->next;
1440  }
1441}
1442
1443/**
1444 * Apply inheritance to an out iotype from a reference in iotype
1445 *
1446 * @param out the iotype to update
1447 * @param in the reference iotype (containing inherited properties)
1448 */
1449void inheritIOType(iotype** out,iotype* in){
1450  iotype* io=in;
1451  iotype* oio=*out;
1452  if(io!=NULL){
1453    if(*out==NULL){
1454      *out=(iotype*)malloc(IOTYPE_SIZE);
1455      (*out)->content=NULL;
1456      addMapToMap(&(*out)->content,io->content);
1457      (*out)->next=NULL;
1458      oio=*out;
1459      inheritIOType(&oio->next,io->next);
1460    }else{
1461      inheritIOType(&oio->next,io->next);
1462    }
1463  }
1464}
1465
1466/**
1467 * Apply inheritance to an out elements from a reference in elements
1468 *
1469 * @param out the elements to update
1470 * @param in the reference elements (containing inherited properties)
1471 */
1472void inheritElements(elements** out,elements* in){
1473  elements* content=in;
1474  while(content!=NULL && *out!=NULL){
1475    elements* cmap=getElements(*out,content->name);
1476    if(cmap==NULL)
1477      addToElements(out,content);
1478    else{
1479      inheritMap(&cmap->content,content->content);
1480      inheritMap(&cmap->metadata,content->metadata);
1481      if(cmap->format==NULL && content->format!=NULL)
1482        cmap->format=zStrdup(content->format);
1483      inheritIOType(&cmap->defaults,content->defaults);
1484      if(cmap->supported==NULL)
1485        inheritIOType(&cmap->supported,content->supported);
1486      else{
1487        iotype* p=content->supported;
1488        while(p!=NULL){
1489          addMapToIoType(&cmap->supported,p->content);
1490          p=p->next;
1491        }
1492      }
1493    }
1494    content=content->next;
1495  }
1496}
1497
1498/**
1499 * Apply inheritance to a service based on a registry
1500 *
1501 * @param r the registry storing profiles hierarchy
1502 * @param s the service to update depending on its inheritance
1503 */
1504void inheritance(registry *r,service** s){
1505  if(r==NULL)
1506    return;
1507  service* ls=*s;
1508  if(ls->content==NULL)
1509    return;
1510  map* profile=getMap(ls->content,"extend");
1511  map* level=getMap(ls->content,"level");
1512  if(profile!=NULL&&level!=NULL){
1513    service* s1;
1514    if(strncasecmp(level->value,"profile",7)==0)
1515      s1=getServiceFromRegistry(r,(char*)"generic",profile->value);
1516    else
1517      s1=getServiceFromRegistry(r,level->value,profile->value);
1518     
1519    inheritMap(&ls->content,s1->content);
1520    inheritMap(&ls->metadata,s1->metadata);
1521    if(ls->inputs==NULL && s1->inputs!=NULL){
1522      ls->inputs=dupElements(s1->inputs);
1523    }else{
1524      inheritElements(&ls->inputs,s1->inputs);
1525    }
1526    if(ls->outputs==NULL && s1->outputs!=NULL){
1527      ls->outputs=dupElements(s1->outputs);
1528    }else
1529      inheritElements(&ls->outputs,s1->outputs);
1530  }
1531}
1532
1533/**
1534 * Convert a maps to a char*** (only used for Fortran support)
1535 *
1536 * @param m the maps to convert
1537 * @param c the resulting array
1538 */
1539void mapsToCharXXX(maps* m,char*** c){
1540  maps* tm=m;
1541  int i=0;
1542  int j=0;
1543  char tmp[10][30][1024];
1544  memset(tmp,0,1024*10*10);
1545  while(tm!=NULL){
1546    if(i>=10)
1547      break;
1548    strcpy(tmp[i][j],"name");
1549    j++;
1550    strcpy(tmp[i][j],tm->name);
1551    j++;
1552    map* tc=tm->content;
1553    while(tc!=NULL){
1554      if(j>=30)
1555        break;
1556      strcpy(tmp[i][j],tc->name);
1557      j++;
1558      strcpy(tmp[i][j],tc->value);
1559      j++;
1560      tc=tc->next;
1561    }
1562    tm=tm->next;
1563    j=0;
1564    i++;
1565  }
1566  memcpy(c,tmp,10*10*1024);
1567}
1568
1569/**
1570 * Convert a char*** to a maps (only used for Fortran support)
1571 *
1572 * @param c the array to convert
1573 * @param m the resulting maps
1574 */
1575void charxxxToMaps(char*** c,maps**m){
1576  maps* trorf=*m;
1577  int i,j;
1578  char tmp[10][30][1024];
1579  memcpy(tmp,c,10*30*1024);
1580  for(i=0;i<10;i++){
1581    if(strlen(tmp[i][1])==0)
1582      break;
1583    trorf->name=tmp[i][1];
1584    trorf->content=NULL;
1585    trorf->next=NULL;
1586    for(j=2;j<29;j+=2){
1587      if(strlen(tmp[i][j+1])==0)
1588        break;
1589      if(trorf->content==NULL)
1590        trorf->content=createMap(tmp[i][j],tmp[i][j+1]);
1591      else
1592        addToMap(trorf->content,tmp[i][j],tmp[i][j+1]);
1593    }
1594    trorf=trorf->next;
1595  }
1596  m=&trorf;
1597}
1598
1599#ifdef WIN32
1600#ifndef USE_MS
1601char *strcasestr (char const *a, char const *b)
1602  {
1603    char *x = zStrdup (a);
1604    char *y = zStrdup (b);
1605 
1606      x = _strlwr (x);
1607      y = _strlwr (y);
1608    char *pos = strstr (x, y);
1609    char *ret = pos == NULL ? NULL : (char *) (a + (pos - x));
1610      free (x);
1611      free (y);
1612      return ret;
1613  };
1614#else
1615   ;
1616#endif
1617#endif
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