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

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

Add support for the two inputs / outputs syntaxes discussed in SWG in both the ZOO-Kernel and the HTML basic UI. Update documentation, add a section for the ZOO-API in Python language section. Rename variables in service.c to ease readabiliy.

  • Property svn:keywords set to Id
File size: 47.5 KB
Line 
1/*
2 * Author : Gérald FENOY
3 *
4 * Copyright (c) 2015-2019 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// knut: time utilities required for new log function (logMessage)
28#include <ctime>
29#include <chrono>
30#ifdef WIN32
31#include <process.h>
32#endif
33
34#if defined(_MSC_VER) && _MSC_VER < 1800
35#include <stdarg.h>
36/**
37 * snprintf for Visual Studio compiler.
38 *
39 * See https://dxr.mozilla.org/mozilla-central/source/media/mtransport/third_party/nrappkit/src/util/util.c
40 */
41int snprintf(char *pcBuffer, size_t n, const char *pccFormat, ...)
42{
43  va_list argp;
44  int ret;
45  va_start(argp, pccFormat);
46  ret = _vscprintf(pccFormat, argp);
47  vsnprintf_s(pcBuffer, n, _TRUNCATE, pccFormat, argp);
48  va_end(argp);
49  return ret;
50}
51#endif
52
53/**
54 * Dump a map on stderr
55 *
56 * @param pmMap the map to dump
57 */
58void _dumpMap(map* pmMap){
59  if(pmMap!=NULL){
60    fprintf(stderr,"%s: %s\n",pmMap->name,pmMap->value);
61    fflush(stderr);
62  }else{
63    fprintf(stderr,"NULL\n");
64    fflush(stderr);
65  }
66}
67
68/**
69 * Dump a map on stderr, see _dumpMap()
70 *
71 * @param pmMap the map to dump
72 */
73void dumpMap(map* pmMap){
74  map* pmTmp=pmMap;
75  while(pmTmp!=NULL){
76    _dumpMap(pmTmp);
77    pmTmp=pmTmp->next;
78  }
79}
80
81/**
82 * Dump a map to a file
83 *
84 * @param pmMap the map to dump to file
85 * @param pfFile the file pointer to store the map
86 */
87void dumpMapToFile(map* pmMap,FILE* pfFile){
88  map* pmTmp=pmMap;
89  while(pmTmp!=NULL){
90    fprintf(pfFile,"%s = %s\n",pmTmp->name,pmTmp->value);
91    pmTmp=pmTmp->next;
92  }
93}
94
95/**
96 * Dump a maps on stderr, see dumpMap().
97 *
98 * @param pmMap the map to dump
99 */
100void dumpMaps(maps* pmMap){
101  maps* pmTmp=pmMap;
102  while(pmTmp!=NULL){
103    fprintf(stderr,"MAP => [%s] \n",pmTmp->name);
104    fprintf(stderr," * CONTENT [%s] \n",pmTmp->name);
105    dumpMap(pmTmp->content);
106    if(pmTmp->child!=NULL){
107      fprintf(stderr," * CHILD [%s] \n",pmTmp->name);
108      dumpMaps(pmTmp->child);
109      fprintf(stderr," * /CHILD [%s] \n",pmTmp->name);
110    }
111    pmTmp=pmTmp->next;
112  }
113}
114
115/**
116 * Dump a maps to a file, see dumpMapToFile().
117 *
118 * @param pmsMaps the map to dump
119 * @param psFile the the file pointer to store the map
120 * @param iLimit the number of maps to print (0 for no limit)
121 */
122void _dumpMapsToFile(maps* pmsMaps,FILE* psFile,int iLimit){
123  maps* tmp=pmsMaps;
124  int cnt=0;
125  while(tmp!=NULL){
126    fprintf(psFile,"[%s]\n",tmp->name);
127    if(tmp->child!=NULL){
128      _dumpMapsToFile(tmp->child,psFile,iLimit);
129    }else
130      dumpMapToFile(tmp->content,psFile);
131    fflush(psFile);
132    tmp=tmp->next;
133    cnt++;
134    if(iLimit>=0 && cnt==iLimit)
135      tmp=NULL;
136  }
137  fflush(psFile);
138}
139
140/**
141 * Dump a maps to a file, see _dumpMapsToFile().
142 *
143 * @param pmsMaps the map to dump
144 * @param pcaFilePath the the file pointer to store the map
145 * @param iLimit the number of maps to print (0 for no limit)
146 */
147void dumpMapsToFile(maps* pmsMaps,char* pcaFilePath,int iLimit){
148  FILE* psFile=fopen(pcaFilePath,"w+");
149  _dumpMapsToFile(pmsMaps,psFile,iLimit);
150  fflush(psFile);
151  fclose(psFile);
152}
153
154/**
155 * Create a new iotype*
156 *
157 * @return a pointer to the allocated iotype
158 */
159iotype* createIoType(){
160  iotype* pioIO=(iotype*)malloc(IOTYPE_SIZE);
161  pioIO->content=NULL;
162  pioIO->next=NULL;
163  return pioIO;
164}
165
166/**
167 * Create a new map
168 *
169 * @param pccName the key to add to the map
170 * @param pccValue the corresponding value to add to the map
171 * @return a pointer to the allocated map
172 */
173map* createMap(const char* pccName,const char* pccValue){
174  map* pmTtmp=(map *)malloc(MAP_SIZE);
175  pmTtmp->name=zStrdup(pccName);
176  pmTtmp->value=zStrdup(pccValue);
177  pmTtmp->next=NULL;
178  return pmTtmp;
179}
180
181/**
182 * Create a new maps with the given name
183 *
184 * @param pccName of the maps
185 * @return the allocated map
186 */
187maps* createMaps(const char* pccName){
188  maps* pmTmp = (maps *) malloc (MAPS_SIZE);
189  pmTmp->name = zStrdup (pccName);
190  pmTmp->content = NULL;
191  pmTmp->child = NULL;
192  pmTmp->next = NULL;
193  return pmTmp;
194}
195
196/**
197 * Count number of map in a map
198 *
199 * @param pmMap the map to count
200 * @return number of map in a map
201 */
202int count(map* pmMap){
203  map* pmTmp=pmMap;
204  int c=0;
205  while(pmTmp!=NULL){
206    c++;
207    pmTmp=pmTmp->next;
208  }
209  return c;
210}
211
212/**
213 * Count number of maps in a maps
214 *
215 * @param pmMap the maps to count
216 * @return number of maps in a maps
217 */
218int maps_length(maps* pmMap){
219  maps* pmTmp=pmMap;
220  int c=0;
221  while(pmTmp!=NULL){
222    c++;
223    pmTmp=pmTmp->next;
224  }
225  return c;
226}
227
228/**
229 * Verify if a key exist in a map
230 *
231 * @param pmMap the map to search for the key
232 * @param pccKey the key to search in the map
233 * @return true if the key wwas found, false in other case
234 */
235bool hasKey(map* pmMap,const char *pccKey){
236  map* pmTmp=pmMap;
237  while(pmTmp!=NULL){
238    if(strcasecmp(pmTmp->name,pccKey)==0)
239      return true;
240    pmTmp=pmTmp->next;
241  }
242#ifdef DEBUG_MAP
243  fprintf(stderr,"NOT FOUND \n");
244#endif
245  return false;
246}
247
248/**
249 * Access a specific maps
250 *
251 * @param pmMap the maps to search for the key
252 * @param pccKey the key to search in the maps
253 * @return a pointer on the maps found or NULL if not found
254 */
255maps* getMaps(maps* pmsMaps,const char *pccKey){
256  maps* pmTmp=pmsMaps;
257  while(pmTmp!=NULL){
258    if(strcasecmp(pmTmp->name,pccKey)==0){
259      return pmTmp;
260    }
261    pmTmp=pmTmp->next;
262  }
263  return NULL;
264}
265
266/**
267 * Access a specific map
268 *
269 * @param pmMap the map to search for the key
270 * @param pccKey the key to search in the map
271 * @return a pointer on the map found or NULL if not found
272 */
273map* getMap(map* pmMap,const char *pccKey){
274  map* pmTmp=pmMap;
275  while(pmTmp!=NULL){
276    if(strcasecmp(pmTmp->name,pccKey)==0){
277      return pmTmp;
278    }
279    pmTmp=pmTmp->next;
280  }
281  return NULL;
282}
283
284
285/**
286 * Access the last map
287 *
288 * @param pmMap the map to search for the lastest map
289 * @return a pointer on the lastest map found or NULL if not found
290 */
291map* getLastMap(map* pmMap){
292  map* pmTmp=pmMap;
293  while(pmTmp!=NULL){
294    if(pmTmp->next==NULL){
295      return pmTmp;
296    }
297    pmTmp=pmTmp->next;
298  }
299  return NULL;
300}
301
302/**
303 * Access a specific map from a maps
304 *
305 * @param pmMap the maps to search for the key
306 * @param pccKey the key to search in the maps
307 * @param pccSubkey the key to search in the map (found for the key, if any)
308 * @return a pointer on the map found or NULL if not found
309 */
310map* getMapFromMaps(maps* pmMap,const char* pccKey,const char* pccSubkey){
311  maps* pmTmp=getMaps(pmMap,pccKey);
312  if(pmTmp!=NULL){
313    map* pmTmp1=getMap(pmTmp->content,pccSubkey);
314    return pmTmp1;
315  }
316  else return NULL;
317}
318
319/**
320 * Free allocated memory of a map.
321 * Require to call free on mo after calling this function.
322 *
323 * @param pmMap the map to free
324 */
325void freeMap(map** pmMap){
326  map* pmCursor=*pmMap;
327  if(pmCursor!=NULL){
328#ifdef DEBUG
329    fprintf(stderr,"freeMap\n");
330#endif
331    if(pmCursor->name!=NULL)
332      free(pmCursor->name);
333    if(pmCursor->value!=NULL)
334      free(pmCursor->value);
335    if(pmCursor->next!=NULL){
336      freeMap(&pmCursor->next);
337      if(pmCursor->next!=NULL)
338        free(pmCursor->next);
339    }
340  }
341}
342
343/**
344 * Free allocated memory of a maps.
345 * Require to call free on mo after calling this function.
346 *
347 * @param pmMap the maps to free
348 */
349void freeMaps(maps** pmMap){
350  maps* pmCursor=*pmMap;
351  if(pmCursor && pmCursor!=NULL){
352#ifdef DEBUG
353    fprintf(stderr,"freeMaps\n");
354#endif
355    free(pmCursor->name);
356    if(pmCursor->content!=NULL){
357      freeMap(&pmCursor->content);
358      free(pmCursor->content);
359    }
360    if(pmCursor->child!=NULL){
361      freeMaps(&pmCursor->child);
362      free(pmCursor->child);
363    }
364    if(pmCursor->next!=NULL){
365      freeMaps(&pmCursor->next);
366      free(pmCursor->next);
367    }
368  }
369}
370
371/**
372 * Verify if an elements contains a name equal to the given key.
373 *
374 * @param peElem the elements to search for the key
375 * @param pccKey the elements name to search
376 * @return true if the elements contains the name, false in other cases.
377 */ 
378bool hasElement(elements* peElem,const char* pccKey){
379  elements* peTmp=peElem;
380  while(peTmp!=NULL){
381    if(strcasecmp(pccKey,peTmp->name)==0)
382      return true;
383    peTmp=peTmp->next;
384  }
385  return false;
386}
387
388/**
389 * Access a specific elements named key.
390 *
391 * @param peElem the elements to search
392 * @param pccKey the elements name to search
393 * @return a pointer to the specific element if found, NULL in other case.
394 */ 
395elements* getElements(elements* peElem,const char *pccKey){
396  elements* peTmp=peElem;
397  while(peTmp!=NULL){
398    if(strcasecmp(peTmp->name,pccKey)==0)
399      return peTmp;
400    peTmp=peTmp->next;
401  }
402  return NULL;
403}
404
405/**
406 * Free allocated memory of an iotype.
407 * Require to call free on i after calling this function.
408 *
409 * @param piotIO the iotype to free
410 */
411void freeIOType(iotype** piotIO){
412  iotype* piotCursor=*piotIO;
413  if(piotCursor!=NULL){
414    if(piotCursor->next!=NULL){
415      freeIOType(&piotCursor->next);
416      free(piotCursor->next);
417    }
418    freeMap(&piotCursor->content);
419    free(piotCursor->content);
420  }
421}
422
423/**
424 * Free allocated memory of an elements.
425 * Require to call free on e after calling this function.
426 *
427 * @param peElem the iotype to free
428 */
429void freeElements(elements** peElem){
430  elements* peTmp=*peElem;
431  if(peTmp!=NULL){
432    if(peTmp->name!=NULL)
433      free(peTmp->name);
434    freeMap(&peTmp->content);
435    if(peTmp->content!=NULL)
436      free(peTmp->content);
437    freeMap(&peTmp->metadata);
438    if(peTmp->metadata!=NULL)
439      free(peTmp->metadata);
440    freeMap(&peTmp->additional_parameters);
441    if(peTmp->additional_parameters!=NULL)
442      free(peTmp->additional_parameters);
443    if(peTmp->format!=NULL)
444      free(peTmp->format);
445    freeElements(&peTmp->child);
446    if(peTmp->child!=NULL){
447      free(peTmp->child);
448    }
449    if(peTmp->defaults!=NULL){
450      freeIOType(&peTmp->defaults);
451      free(peTmp->defaults);
452    }
453    if(peTmp->supported!=NULL){
454      freeIOType(&peTmp->supported);
455      free(peTmp->supported);
456    }
457    if(peTmp->next!=NULL){
458      freeElements(&peTmp->next);
459      free(peTmp->next);
460    }
461  }
462}
463
464
465/**
466 * Allocate memory for a service.
467 * Require to call free after calling this function.
468 *
469 * @return the service
470 */
471service* createService(){
472  service *psService = (service *) malloc (SERVICE_SIZE);
473  psService->name=NULL;
474  psService->content=NULL;
475  psService->metadata=NULL;
476  psService->additional_parameters=NULL;
477  psService->inputs=NULL;
478  psService->outputs=NULL;
479  return psService;
480}
481
482/**
483 * Free allocated memory of a service.
484 * Require to be invoked for every createService call.
485 *
486 * @param psService the service to free
487 */
488void freeService(service** psService){
489  service* psTmp=*psService;
490  if(psTmp!=NULL){
491    if(psTmp->name!=NULL)
492      free(psTmp->name);
493    freeMap(&psTmp->content);
494    if(psTmp->content!=NULL)
495      free(psTmp->content);
496    freeMap(&psTmp->metadata);
497    if(psTmp->metadata!=NULL)
498      free(psTmp->metadata);
499    freeMap(&psTmp->additional_parameters);
500    if(psTmp->additional_parameters!=NULL)
501      free(psTmp->additional_parameters);
502    freeElements(&psTmp->inputs);
503    if(psTmp->inputs!=NULL)
504      free(psTmp->inputs);
505    freeElements(&psTmp->outputs);
506    if(psTmp->outputs!=NULL)
507      free(psTmp->outputs);
508  }
509}
510
511/**
512 * Add key value pair to an existing map.
513 *
514 * @param pMap the map to add the KVP
515 * @param pccName the key to add
516 * @param pccValue the corresponding value to add
517 */
518void addToMap(map* pMap,const char* pccName,const char* pccValue){
519  if (pMap != NULL) { // knut: add NULL-pointer check
520    if (hasKey(pMap, pccName) == false) {
521      map* pmCursor = pMap;
522      while (pmCursor->next != NULL) {
523        pmCursor = pmCursor->next;
524      }
525      pmCursor->next = createMap(pccName, pccValue);
526    }
527    else {
528      map *tmp = getMap(pMap, pccName);
529      if (tmp->value != NULL)
530        free(tmp->value);
531      tmp->value = zStrdup(pccValue);
532    }
533  }
534}
535
536/**
537 * Add a key and an integer value to an existing map.
538 *
539 * @param pMap the map to add the KVP
540 * @param pccName the key to add
541 * @param iValue the corresponding value to add
542 */
543void addIntToMap(map* pMap,const char* pccName,const int iValue){
544  char acValue[10];
545  sprintf(acValue,"%d",iValue);
546  if(hasKey(pMap,pccName)==false){
547    map* pmCursor=pMap;
548    while(pmCursor->next!=NULL){
549      pmCursor=pmCursor->next;
550    }
551    pmCursor->next=createMap(pccName,acValue);
552  }
553  else{
554    map *pmTmp=getMap(pMap,pccName);
555    if(pmTmp->value!=NULL)
556      free(pmTmp->value);
557    pmTmp->value=zStrdup(acValue);
558  }
559}
560
561/**
562 * Add a key and a binary value to an existing map.
563 *
564 * @param pMap the map to add the KVP
565 * @param pccName the key to add
566 * @param pccValue the corresponding value to add
567 * @param iSize the size of the given value
568 * @return a pointer to the updated map m
569 */
570map* addToMapWithSize(map* pMap,const char* pccName,const char* pccValue,int iSize){
571  char acIn[128];
572  char acName[10]="size";
573  map *pmTmp;
574  if(hasKey(pMap,pccName)==false){
575    map* _cursor=pMap;
576    if(_cursor!=NULL){
577      addToMap(pMap,pccName,"");
578    }else{
579      pMap=createMap(pccName,"");
580    }
581  }
582  if(strlen(pccName)>5)
583    sprintf(acName,"size_%s",pccName+6);
584  pmTmp=getMap(pMap,pccName);
585  if(pmTmp->value!=NULL)
586    free(pmTmp->value);
587  pmTmp->value=(char*)malloc((iSize+1)*sizeof(char));
588  if(pccValue!=NULL)
589    memmove(pmTmp->value,pccValue,iSize*sizeof(char));
590  pmTmp->value[iSize]=0;
591  sprintf(acIn,"%d",iSize);
592  addToMap(pMap,acName,acIn);
593  return pMap;
594}
595
596/**
597 * Add a map at the end of another map.
598 *
599 * @param pmMapOut the map to add pmMapIn to
600 * @param pmMapIn the map to add to pmMapOut
601 */
602void addMapToMap(map** pmMapOut,map* pmMapIn){
603  map* pmTmp=pmMapIn;
604  map* pmCursor=*pmMapOut;
605  while(pmTmp!=NULL){
606    if(pmCursor==NULL){
607      *pmMapOut=createMap(pmTmp->name,pmTmp->value);
608      (*pmMapOut)->next=NULL;
609    }
610    else{
611      map* pmTmp1=getMap(*pmMapOut,pmTmp->name);
612      if(pmTmp1==NULL){
613        while(pmCursor->next!=NULL)
614          pmCursor=pmCursor->next;
615        pmCursor->next=createMap(pmTmp->name,pmTmp->value);
616      }
617      else{
618        addToMap(*pmMapOut,pmTmp->name,pmTmp->value);
619      }
620    }
621    pmCursor=*pmMapOut;
622    pmTmp=pmTmp->next;
623  }
624}
625
626/**
627 * Add a map to iotype.
628 *
629 * @param piotType the iotype to add the map
630 * @param pmMap the map to add to io
631 */
632void addMapToIoType(iotype** piotType,map* pmMap){
633  iotype* piotTmp=*piotType;
634  while(piotTmp->next!=NULL){
635    piotTmp=piotTmp->next;
636  }
637  piotTmp->next=(iotype*)malloc(IOTYPE_SIZE);
638  piotTmp->next->content=NULL;
639  addMapToMap(&piotTmp->next->content,pmMap);
640  piotTmp->next->next=NULL;
641}
642
643/**
644 * Access a specific map or set its value.
645 *
646 * @param ppmMap the map to search for the key
647 * @param pccKey the key to search/add in the map
648 * @param pccValue the value to add if the key does not exist
649 * @return a pointer on the map found or NULL if not found
650 */
651map* getMapOrFill(map** ppmMap,const char *pccKey,const char* pccValue){
652  map* pmTmp=*ppmMap;
653  map* pmTmp1=getMap(pmTmp,pccKey);
654  if(pmTmp1==NULL){
655    if(pmTmp!=NULL){
656      addToMap((*ppmMap),pccKey,pccValue);
657    }
658    else
659      (*ppmMap)=createMap(pccKey,pccValue);
660    pmTmp1=getMap(*ppmMap,pccKey);
661  }
662  return pmTmp1;
663}
664
665/**
666 * Verify if a map is contained in another map.
667 *
668 * @param pmMap the map to search for i
669 * @param pmSearch the map to search in m
670 * @return true if i was found in m, false in other case
671 */
672bool contains(map* pmMap,map* pmSearch){
673  while(pmSearch!=NULL){     
674    if(strcasecmp(pmSearch->name,"value")!=0 &&
675       strcasecmp(pmSearch->name,"xlink:href")!=0 &&
676       strcasecmp(pmSearch->name,"useMapServer")!=0 &&
677       strcasecmp(pmSearch->name,"asReference")!=0){
678      map *tmp;
679      if(hasKey(pmMap,pmSearch->name) &&
680         (tmp=getMap(pmMap,pmSearch->name))!=NULL && 
681         strcasecmp(pmSearch->value,tmp->value)!=0)
682        return false;
683    }
684    pmSearch=pmSearch->next;
685  }
686  return true;
687}
688
689/**
690 * Access a specific iotype from an elements.
691 *
692 * @param peElem the elements to search for the name
693 * @param pcName the name to search in the elements e
694 * @param pcValues the map to verify it was contained in the defaults or
695 *  supported content of the elements e
696 * @return a pointer on the iotype found or NULL if not found
697 */
698iotype* getIoTypeFromElement(elements* peElem,char *pcName, map* pcValues){
699  elements* peCursor=peElem;
700  if(pcValues!=NULL){
701    while(peCursor!=NULL){
702      if(strcasecmp(peCursor->name,pcName)==0 && (peCursor->defaults!=NULL || peCursor->supported!=NULL)){
703        if(contains(peCursor->defaults->content,pcValues)==true)
704          return peCursor->defaults;
705        else{
706          iotype* tmp=peCursor->supported;
707          while(tmp!=NULL){
708            if(contains(tmp->content,pcValues)==true)
709              return tmp;           
710            tmp=tmp->next;
711          }
712        }
713      }
714      peCursor=peCursor->next;
715    }
716  }else{
717    while(peCursor!=NULL){
718      if(strcasecmp(peCursor->name,pcName)==0 && peCursor->defaults!=NULL){
719        return peCursor->defaults;
720      }
721      peCursor=peCursor->next;
722    }
723  }
724  return NULL;
725}
726
727/**
728 * Load binary values from a map (in) and add them to another map (out)
729 *
730 * @param pmOut the map to add binaries values
731 * @param pmIn the map containing the binary values to add ti out
732 * @param iPos index of the binary in an array (in case of "MapArray")
733 */
734void loadMapBinary(map** ppmOut,map* pmIn,int iPos){
735  map* pmSize=getMap(pmIn,"size");
736  map *pmOut=*ppmOut;
737  map *pmTmpVin,*pmTmpVout;
738  if(pmSize!=NULL && iPos>0){
739    char tmp[11];
740    sprintf(tmp,"size_%d",iPos);
741    pmSize=getMap(pmIn,tmp);
742    sprintf(tmp,"value_%d",iPos);
743    pmTmpVin=getMap(pmIn,tmp);
744    pmTmpVout=getMap(pmOut,tmp);
745    free(pmTmpVout->value);
746    pmTmpVout->value=(char*)malloc((atoi(pmSize->value)+1)*sizeof(char));
747    memmove(pmTmpVout->value,pmTmpVin->value,atoi(pmSize->value)*sizeof(char));
748    pmTmpVout->value[atoi(pmSize->value)]=0;
749  }else{
750    if(pmSize!=NULL){
751      pmTmpVin=getMap(pmIn,"value");
752      pmTmpVout=getMap(pmOut,"value");
753      free(pmTmpVout->value);
754      pmTmpVout->value=(char*)malloc((atoi(pmSize->value)+1)*sizeof(char));
755      memmove(pmTmpVout->value,pmTmpVin->value,atoi(pmSize->value)*sizeof(char));
756      pmTmpVout->value[atoi(pmSize->value)]=0;
757    }
758  }
759}
760
761/**
762 * Load binary values from a map (in) and add them to another map (out).
763 * This function will take care of MapArray.
764 * @see loadMapBinary
765 *
766 * @param ppmOut the map to add binaries values
767 * @param pmIn the map containing the binary values to add ti out
768 */
769void loadMapBinaries(map** ppmOut,map* pmIn){
770  map* pmSize=getMap(pmIn,"size");
771  map* pmLength=getMap(pmIn,"length");
772  map* pmToload=getMap(pmIn,"to_load");
773  if(pmToload!=NULL && strcasecmp(pmToload->value,"false")==0){
774#ifdef DEBUG
775    fprintf(stderr,"NO LOAD %s %d \n",__FILE__,__LINE__);
776#endif
777    return ;
778  }
779  if(pmLength!=NULL){
780    int len=atoi(pmLength->value);
781    int i=0;
782    for(i=0;i<len;i++){
783      loadMapBinary(ppmOut,pmIn,i);
784    }
785  }
786  else
787    if(pmSize!=NULL)
788      loadMapBinary(ppmOut,pmIn,-1);
789}
790
791/**
792 * Duplicate a Maps
793 *
794 * @param ppmsOut the maps to clone
795 * @return the allocated maps containing a copy of the mo maps
796 */
797maps* dupMaps(maps** ppmsOut){
798  maps* pmsCursor=*ppmsOut;
799  maps* pmRes=NULL;
800  if(pmsCursor!=NULL){
801    map* pmContent=pmsCursor->content;
802    maps* pmsChild=pmsCursor->child;
803    pmRes=createMaps(pmsCursor->name);
804    if(pmContent!=NULL){
805      addMapToMap(&pmRes->content,pmContent);
806      loadMapBinaries(&pmRes->content,pmContent);
807    }
808    if(pmsChild!=NULL){
809      pmRes->child=dupMaps(&pmsChild);
810    }
811    pmRes->next=dupMaps(&pmsCursor->next);
812  }
813  return pmRes;
814}
815
816/**
817 * Add a maps at the end of another maps.
818 *
819 * @see addMapToMap, dupMaps, getMaps
820 * @param ppmsOut the maps to add mi
821 * @param pmIn the maps to add to mo
822 */
823void addMapsToMaps(maps** ppmsOut,maps* pmIn){
824  maps* pmsTmp=pmIn;
825  maps* pmsCursor=*ppmsOut;
826  while(pmsTmp!=NULL){
827    if(pmsCursor==NULL){
828      *ppmsOut=dupMaps(&pmIn);
829    }
830    else{
831      maps* pmsTmp1=getMaps(*ppmsOut,pmsTmp->name);
832      if(pmsTmp1==NULL){
833        while(pmsCursor->next!=NULL)
834          pmsCursor=pmsCursor->next;
835        pmsCursor->next=dupMaps(&pmsTmp);
836        if(pmsTmp->child!=NULL)
837          pmsCursor->next->child=dupMaps(&pmsTmp->child);
838        else
839          pmsCursor->next->child=NULL;
840      }
841      else{
842        addMapToMap(&pmsTmp1->content,pmsTmp->content);
843        if(pmsTmp->child!=NULL)
844          pmsTmp1->child=dupMaps(&pmsTmp->child);
845        else
846          pmsTmp1->child=NULL;
847      }
848      pmsCursor=*ppmsOut;
849    }
850    pmsTmp=pmsTmp->next;
851  }
852}
853
854/**
855 * Access a specific map array element
856 *
857 * @param pmMap the map to search for the key
858 * @param pccKey the key to search in the map
859 * @param iIndex of the MapArray
860 * @return a pointer on the map found or NULL if not found
861 */
862map* getMapArray(map* pmMap,const char* pccKey,int iIndex){
863  char acTmp[1024];
864  map* pmTmp;
865  if(iIndex>0)
866    sprintf(acTmp,"%s_%d",pccKey,iIndex);
867  else
868    sprintf(acTmp,"%s",pccKey);
869#ifdef DEBUG
870  fprintf(stderr,"** KEY %s\n",acTmp);
871#endif
872  pmTmp=getMap(pmMap,acTmp);
873#ifdef DEBUG
874  if(pmTmp!=NULL)
875    dumpMap(pmTmp);
876#endif
877  return pmTmp;
878}
879
880/**
881 * Add a key value in a MapArray for a specific index
882 *
883 * @param pmMap the map to search for the key
884 * @param pccKey the key to search in the map
885 * @param iIndex the index of the MapArray
886 * @param pccValue the value to set in the MapArray
887 * @return a pointer on the map found or NULL if not found
888 */
889void setMapArray(map* pmMap,const char* pccKey,int iIndex,const char* pccValue){
890  char acTmp[1024];
891  map* pmSize;
892  if(iIndex>0){
893    map* pmLen=getMap(pmMap,"length");
894    sprintf(acTmp,"%s_%d",pccKey,iIndex);
895    if((pmLen!=NULL && atoi(pmLen->value)<iIndex+1) || pmLen==NULL){
896      char acTmp0[5];
897      sprintf(acTmp0,"%d",iIndex+1);
898      addToMap(pmMap,"length",acTmp0);
899    }
900  }
901  else{
902    sprintf(acTmp,"%s",pccKey);
903    addToMap(pmMap,"length","1");
904  }
905  pmSize=getMapArray(pmMap,"size",iIndex);
906  if(pmSize!=NULL && strncasecmp(pccKey,"value",5)==0){
907    map* pmPtr=getMapOrFill(&pmMap,acTmp,(char *)"");
908#ifdef DEBUG
909    fprintf(stderr,"%s\n",pmSize->value);
910#endif
911    free(pmPtr->value);
912    pmPtr->value=(char*)malloc((atoi(pmSize->value)+1)*sizeof(char));
913    memcpy(pmPtr->value,pccValue,atoi(pmSize->value)); 
914  }
915  else
916    addToMap(pmMap,acTmp,pccValue);
917}
918
919/**
920 * Add a key and an integer value to an existing map array.
921 *
922 * @param pmMap the map to add the KVP
923 * @param pccName the key to add
924 * @param iIndex the index of the MapArray
925 * @param icValue the corresponding value to add
926 */
927void addIntToMapArray(map* pmMap,const char* pccName,int iIndex,const int icValue){
928  char acValue[10];
929  sprintf(acValue,"%d",icValue);
930  setMapArray(pmMap,pccName,iIndex,acValue);
931}
932
933/**
934 * Access the map "type"
935 *
936 * @param pmMap the map
937 * @return a pointer on the map for mimeType/dataType/CRS if found, NULL in
938 *  other case
939 */
940map* getMapType(map* pmMap){
941  map* pmMime=getMap(pmMap,(char *)"mimeType");
942  if(pmMime==NULL){
943    pmMime=getMap(pmMap,"dataType");
944    if(pmMime==NULL){
945      pmMime=getMap(pmMap,"CRS");
946    }
947  }
948#ifdef DEBUG
949  dumpMap(pmMime);
950#endif
951  return pmMime;
952}
953
954/**
955 * Add a Maps containing a MapArray to a Maps
956 *
957 * @see getMapType
958 * @param pmsOut the maps
959 * @param pmsIn the maps
960 * @param pcType the map "type"
961 * @return
962 */
963int addMapsArrayToMaps(maps** pmsOut,maps* pmsIn,char* pcType){
964  maps* pmsTmp=pmsIn;
965  maps* pmsCursor=getMaps(*pmsOut,pmsTmp->name);
966  char acLen[10];
967  int iLen=1;
968  char *acV[14]={
969    (char*)"size",
970    (char*)"value",
971    (char*)"uom",
972    (char*)"Reference",
973    (char*)"Order",
974    (char*)"cache_file",
975    (char*)"fmimeType",
976    (char*)"xlink:href",
977    pcType,
978    (char*)"schema",
979    (char*)"encoding",
980    (char*)"isCached",
981    (char*)"LowerCorner",
982    (char*)"UpperCorner"
983  };
984  int iCounter=0;
985  map* pmLength;
986 
987  if(pmsCursor==NULL)
988    return -1;
989
990  pmLength=getMap(pmsCursor->content,"length");
991  if(pmLength!=NULL){
992    iLen=atoi(pmLength->value);
993  }
994
995  sprintf(acLen,"%d",iLen+1);
996  addToMap(pmsCursor->content,"length",acLen);
997  for(iCounter=0;iCounter<14;iCounter++){
998    map* pmTmp=getMap(pmsTmp->content,acV[iCounter]);
999    if(pmTmp!=NULL){
1000#ifdef DEBUG
1001      fprintf(stderr,"%s = %s\n",pmTmp[iCounter],pmTmp->value);
1002#endif
1003      setMapArray(pmsCursor->content,acV[iCounter],iLen,pmTmp->value);
1004    }
1005  }
1006   
1007  addToMap(pmsCursor->content,"isArray","true");
1008  return 0;
1009}
1010
1011/**
1012 * Set a key value pair to a map contained in a Maps
1013 *
1014 * @param pmsMaps the maps
1015 * @param pccKey the maps name
1016 * @param pccSubkey the map name included in the maps corresponding to key
1017 * @param pccValue the corresponding value to add in the map
1018 */
1019void setMapInMaps(maps* pmsMaps,const char* pccKey,const char* pccSubkey,const char *pccValue){
1020  maps* pmsTmp=getMaps(pmsMaps,pccKey);
1021  if(pmsTmp!=NULL){
1022    map* pmTmpSub=getMap(pmsTmp->content,pccSubkey);
1023    if(pmTmpSub!=NULL){
1024      if(pmTmpSub->value!=NULL)
1025        free(pmTmpSub->value);
1026      pmTmpSub->value=zStrdup(pccValue);
1027    }else{
1028      maps *pmsToAdd=createMaps(pccKey);
1029      pmsToAdd->content=createMap(pccSubkey,pccValue);
1030      addMapsToMaps(&pmsTmp,pmsToAdd);
1031      freeMaps(&pmsToAdd);
1032      free(pmsToAdd);
1033    }
1034  }else{
1035    maps *pmsToAdd=createMaps(pccKey);
1036    pmsToAdd->content=createMap(pccSubkey,pccValue);
1037    addMapsToMaps(&pmsMaps,pmsToAdd);
1038    freeMaps(&pmsToAdd);
1039    free(pmsToAdd);
1040  }
1041}
1042
1043/**
1044 * Create an empty elements
1045 *
1046 * @return a pointer to the allocated elements
1047 */
1048elements* createEmptyElements(){
1049  elements* peRes=(elements*)malloc(ELEMENTS_SIZE);
1050  peRes->name=NULL;
1051  peRes->content=NULL;
1052  peRes->metadata=NULL;
1053  peRes->additional_parameters=NULL; 
1054  peRes->format=NULL;
1055  peRes->defaults=NULL;
1056  peRes->supported=NULL;
1057  peRes->child=NULL;
1058  peRes->next=NULL;
1059  return peRes;
1060}
1061
1062/**
1063 * Create a named elements
1064 *
1065 * @param pcName the elements name
1066 * @return a pointer to the allocated elements
1067 */
1068elements* createElements(const char* pcName){
1069  elements* peRes=(elements*)malloc(ELEMENTS_SIZE);
1070  peRes->name=zStrdup(pcName);
1071  peRes->content=NULL;
1072  peRes->metadata=NULL;
1073  peRes->additional_parameters=NULL;
1074  peRes->format=NULL;
1075  peRes->defaults=NULL;
1076  peRes->supported=NULL;
1077  peRes->child=NULL;
1078  peRes->next=NULL;
1079  return peRes;
1080}
1081
1082/**
1083 * Set the name of an elements
1084 *
1085 * @param peElem the elements to modify
1086 * @param pcName the elements name
1087 * @return a pointer to the allocated elements
1088 */
1089void setElementsName(elements** ppeElem,char* pcName){
1090  elements* peRes=*ppeElem;
1091  peRes->name=zStrdup(pcName);
1092  peRes->content=NULL;
1093  peRes->metadata=NULL;
1094  peRes->format=NULL;
1095  peRes->defaults=NULL;
1096  peRes->supported=NULL;
1097  peRes->child=NULL;
1098  peRes->next=NULL;
1099}
1100
1101/**
1102 * Dump an elements on stderr
1103 *
1104 * @param peElem the elements to dump
1105 */
1106void dumpElements(elements* peElem){
1107  elements* peTmp=peElem;
1108  while(peTmp!=NULL){
1109    iotype* piotTmp=peTmp->defaults;
1110    int ioc=0;
1111    fprintf(stderr,"ELEMENT [%s]\n",peTmp->name);
1112    fprintf(stderr," > CONTENT [%s]\n",peTmp->name);
1113    dumpMap(peTmp->content);
1114    fprintf(stderr," > METADATA [%s]\n",peTmp->name);
1115    dumpMap(peTmp->metadata);
1116    fprintf(stderr," > ADDITIONAL PARAMETERS [%s]\n",peTmp->name);
1117    dumpMap(peTmp->additional_parameters);
1118    fprintf(stderr," > FORMAT [%s]\n",peTmp->format);
1119    while(piotTmp!=NULL){
1120      fprintf(stderr," > DEFAULTS [%s] (%i)\n",peTmp->name,ioc);
1121      dumpMap(piotTmp->content);
1122      piotTmp=piotTmp->next;
1123      ioc++;
1124    }
1125    piotTmp=peTmp->supported;
1126    ioc=0;
1127    while(piotTmp!=NULL){
1128      fprintf(stderr," > SUPPORTED [%s] (%i)\n",peTmp->name,ioc);
1129      dumpMap(piotTmp->content);
1130      piotTmp=piotTmp->next;
1131      ioc++;
1132    }
1133    if(peTmp->child!=NULL){
1134      fprintf(stderr," > CHILD \n");
1135      dumpElements(peTmp->child);
1136    }
1137    fprintf(stderr,"------------------\n");
1138    peTmp=peTmp->next;
1139  }
1140}
1141
1142/**
1143 * Dump an elements on stderr using the YAML syntaxe
1144 *
1145 * @param peElem the elements to dump
1146 * @param iLevel the current level
1147 */
1148void dumpElementsAsYAML(elements* peElem,int iLevel){
1149  elements* peTmp=peElem;
1150  int i;
1151  while(peTmp!=NULL){
1152    map* pmCurs=peTmp->content;
1153    int ioc=0;
1154    iotype* piotTmp;
1155    for(i=0;i<2+(4*iLevel);i++)
1156      fprintf(stderr," ");
1157    fprintf(stderr,"%s:\n",peTmp->name);
1158    while(pmCurs!=NULL){
1159      for(i=0;i<4+(4*iLevel);i++)
1160        fprintf(stderr," ");
1161      _dumpMap(pmCurs);
1162      pmCurs=pmCurs->next;
1163    }
1164    pmCurs=peTmp->metadata;
1165    if(pmCurs!=NULL){
1166      for(i=0;i<4+(4*iLevel);i++)
1167        fprintf(stderr," ");
1168      fprintf(stderr,"MetaData:\n");
1169      while(pmCurs!=NULL){
1170        for(i=0;i<6+(4*iLevel);i++)
1171          fprintf(stderr," ");
1172        _dumpMap(pmCurs);
1173        pmCurs=pmCurs->next;
1174      }
1175    }
1176    for(i=0;i<4+(4*iLevel);i++)
1177      fprintf(stderr," ");
1178    if(peTmp->format!=NULL)
1179      fprintf(stderr,"%s:\n",peTmp->format);
1180    else{
1181      fprintf(stderr,"Child:\n");
1182      if(peTmp->child!=NULL)
1183        dumpElementsAsYAML(peTmp->child,iLevel+1);
1184    }
1185    piotTmp=peTmp->defaults;
1186    while(piotTmp!=NULL){
1187      for(i=0;i<6+(4*iLevel);i++)
1188        fprintf(stderr," ");
1189      fprintf(stderr,"default:\n");
1190      pmCurs=piotTmp->content;
1191      while(pmCurs!=NULL){
1192        for(i=0;i<8+(4*iLevel);i++)
1193          fprintf(stderr," ");
1194        if(strcasecmp(pmCurs->name,"range")==0){
1195          fprintf(stderr,"range: \"%s\"\n",pmCurs->value);
1196        }else
1197          _dumpMap(pmCurs);
1198        pmCurs=pmCurs->next;
1199      }
1200      piotTmp=piotTmp->next;
1201      ioc++;
1202    }
1203    piotTmp=peTmp->supported;
1204    ioc=0;
1205    while(piotTmp!=NULL){
1206      for(i=0;i<6+(4*iLevel);i++)
1207        fprintf(stderr," ");
1208      fprintf(stderr,"supported:\n");
1209      pmCurs=piotTmp->content;
1210      while(pmCurs!=NULL){
1211        for(i=0;i<8+(4*iLevel);i++)
1212          fprintf(stderr," ");
1213        if(strcasecmp(pmCurs->name,"range")==0){
1214          fprintf(stderr,"range: \"%s\"\n",pmCurs->value);
1215        }else
1216          _dumpMap(pmCurs);
1217        pmCurs=pmCurs->next;
1218      }
1219      piotTmp=piotTmp->next;
1220      ioc++;
1221    }
1222    peTmp=peTmp->next;
1223  }
1224}
1225
1226/**
1227 * Duplicate an elements
1228 *
1229 * @param peElem the elements to clone
1230 * @return the allocated elements containing a copy of the elements e
1231 */
1232elements* dupElements(elements* peElem){
1233  elements* peCursor=peElem;
1234  elements* peTmp=NULL;
1235  if(peCursor!=NULL && peCursor->name!=NULL){
1236#ifdef DEBUG
1237    fprintf(stderr,">> %s %i\n",__FILE__,__LINE__);
1238    dumpElements(e);
1239    fprintf(stderr,">> %s %i\n",__FILE__,__LINE__);
1240#endif
1241    peTmp=(elements*)malloc(ELEMENTS_SIZE);
1242    peTmp->name=zStrdup(peCursor->name);
1243    peTmp->content=NULL;
1244    addMapToMap(&peTmp->content,peCursor->content);
1245    peTmp->metadata=NULL;
1246    addMapToMap(&peTmp->metadata,peCursor->metadata);
1247    peTmp->additional_parameters=NULL;
1248    addMapToMap(&peTmp->additional_parameters,peCursor->additional_parameters);
1249    if(peCursor->format!=NULL)
1250      peTmp->format=zStrdup(peCursor->format);
1251    else
1252      peTmp->format=NULL;
1253    if(peCursor->defaults!=NULL){
1254      peTmp->defaults=(iotype*)malloc(IOTYPE_SIZE);
1255      peTmp->defaults->content=NULL;
1256      addMapToMap(&peTmp->defaults->content,peCursor->defaults->content);
1257      peTmp->defaults->next=NULL;
1258#ifdef DEBUG
1259      fprintf(stderr,">> %s %i\n",__FILE__,__LINE__);
1260      dumpMap(peTmp->defaults->content);
1261#endif
1262    }else
1263      peTmp->defaults=NULL;
1264    if(peCursor->supported!=NULL && peCursor->supported->content!=NULL){
1265      iotype *piotTmp=peCursor->supported->next;
1266      peTmp->supported=(iotype*)malloc(IOTYPE_SIZE);
1267      peTmp->supported->content=NULL;
1268      addMapToMap(&peTmp->supported->content,peCursor->supported->content);
1269      peTmp->supported->next=NULL;
1270            while(piotTmp!=NULL){
1271        addMapToIoType(&peTmp->supported,piotTmp->content);
1272#ifdef DEBUG
1273        fprintf(stderr,">> %s %i\n",__FILE__,__LINE__);
1274        dumpMap(peTmp->defaults->content);
1275#endif
1276        piotTmp=piotTmp->next;
1277      }
1278    }
1279    else
1280      peTmp->supported=NULL;
1281    if(peCursor->child!=NULL)
1282      peTmp->child=dupElements(peCursor->child);
1283    else
1284      peTmp->child=NULL;
1285    if(peCursor->next!=NULL)
1286      peTmp->next=dupElements(peCursor->next);
1287    else
1288      peTmp->next=NULL;
1289  }
1290  return peTmp;
1291}
1292
1293/**
1294 * Add an elements to another elements.
1295 *
1296 * @see dupElements
1297 * @param ppeElem the elements to add the e
1298 * @param peELem the elements to be added to m
1299 */
1300void addToElements(elements** ppeElem,elements* peELem){
1301  elements* peTmp=peELem;
1302  if(*ppeElem==NULL){
1303    (*ppeElem)=dupElements(peTmp);
1304  }else{
1305    addToElements(&(*ppeElem)->next,peTmp);
1306  }
1307}
1308
1309/**
1310 * Set the name of a service
1311 *
1312 * @param ppsServ the service
1313 * @param pcName the service name
1314 */
1315void setServiceName(service** ppsServ,char* pcName){
1316  service* psRes=*ppsServ;
1317  psRes->name=zStrdup(pcName);
1318  psRes->content=NULL;
1319  psRes->metadata=NULL;
1320  psRes->inputs=NULL;
1321  psRes->outputs=NULL;
1322}
1323
1324/**
1325 * Dump a service on stderr
1326 *
1327 * @param psServ the service to dump
1328 */
1329void dumpService(service* psServ){
1330  if(psServ==NULL)
1331    return;
1332  fprintf(stderr,"++++++++++++++++++\nSERVICE [%s]\n++++++++++++++++++\n",psServ->name);
1333  if(psServ->content!=NULL){
1334    fprintf(stderr,"CONTENT MAP\n");
1335    dumpMap(psServ->content);
1336    if(psServ->metadata!=NULL)
1337      fprintf(stderr,"CONTENT METADATA\n");
1338    dumpMap(psServ->metadata);
1339    if(psServ->additional_parameters!=NULL)
1340      fprintf(stderr,"CONTENT AdditionalParameters\n");
1341    dumpMap(psServ->additional_parameters);
1342  }
1343  if(psServ->inputs!=NULL){
1344    fprintf(stderr,"INPUT ELEMENTS [%s]\n------------------\n",psServ->name);
1345    dumpElements(psServ->inputs);
1346  }
1347  if(psServ->outputs!=NULL){
1348    fprintf(stderr,"OUTPUT ELEMENTS [%s]\n------------------\n",psServ->name);
1349    dumpElements(psServ->outputs);
1350  }
1351  fprintf(stderr,"++++++++++++++++++\n");
1352}
1353
1354/**
1355 * Dump a service on stderr using the YAML syntaxe
1356 *
1357 * @param psServ the service to dump
1358 */
1359void dumpServiceAsYAML(service* psServ){
1360  int i;
1361  fprintf(stderr,"# %s\n\n",psServ->name);
1362  if(psServ->content!=NULL){
1363    map* pmCurs=psServ->content;
1364    dumpMap(pmCurs);
1365    pmCurs=psServ->metadata;
1366    if(pmCurs!=NULL){
1367      fprintf(stderr,"MetaData:\n");
1368      while(pmCurs!=NULL){
1369        for(i=0;i<2;i++)
1370          fprintf(stderr," ");
1371        _dumpMap(pmCurs);
1372        pmCurs=pmCurs->next;
1373      }
1374    }
1375  }
1376  if(psServ->inputs!=NULL){
1377    fprintf(stderr,"\ninputs:\n");
1378    dumpElementsAsYAML(psServ->inputs,0);
1379  }
1380  if(psServ->outputs!=NULL){
1381    fprintf(stderr,"\noutputs:\n");
1382    dumpElementsAsYAML(psServ->outputs,0);
1383  }
1384}
1385
1386/**
1387 * Duplicate a service
1388 *
1389 * @param psServ the service to clone
1390 * @return the allocated service containing a copy of the serfvice s
1391 */
1392service* dupService(service* psServ){
1393  service *psRes=(service*)malloc(SERVICE_SIZE);
1394  psRes->name=zStrdup(psServ->name);
1395  psRes->content=NULL;
1396  addMapToMap(&psRes->content,psServ->content);
1397  psRes->metadata=NULL;
1398  addMapToMap(&psRes->metadata,psServ->metadata);
1399  psRes->additional_parameters=NULL;
1400  addMapToMap(&psRes->additional_parameters,psServ->additional_parameters);
1401  psRes->inputs=dupElements(psServ->inputs);
1402  psRes->outputs=dupElements(psServ->outputs);
1403  return psRes;
1404}
1405
1406/**
1407 * Print the registry on stderr.
1408 *
1409 * @param prReg the registry
1410 */
1411void dumpRegistry(registry* prReg){
1412  registry* prCurs=prReg;
1413  while(prCurs!=NULL){
1414    services* psServ=prCurs->content;
1415    fprintf(stderr,"%s \n",prCurs->name);
1416    psServ=prCurs->content;
1417    while(psServ!=NULL){
1418      dumpService(psServ->content);
1419      psServ=psServ->next;
1420    }
1421    prCurs=prCurs->next;
1422  }
1423}
1424
1425/**
1426 * Add a service to the registry
1427 *
1428 * @param prReg the resgitry to add the service
1429 * @param pcName the registry name to update
1430 * @param psContent the service to add
1431 */
1432bool addServiceToRegistry(registry** prReg,char* pcName,service* psContent){
1433  registry *l=*prReg;
1434  int isInitial=-1;
1435  if(l==NULL){
1436    l=(registry*)malloc(REGISTRY_SIZE);
1437    isInitial=1;
1438  }
1439  if(l!=NULL){
1440    int hasLevel=-1;
1441    while(isInitial<0 && l!=NULL){
1442      if(l->name!=NULL && strcasecmp(pcName,l->name)==0){
1443        hasLevel=1;
1444        break;
1445      }
1446      l=l->next;
1447    }
1448    if(hasLevel<0){
1449      if(isInitial<0)
1450        l=(registry*)malloc(REGISTRY_SIZE);
1451      l->name=zStrdup(pcName);
1452      l->content=NULL;
1453      l->next=NULL;
1454    }
1455    if(l->content==NULL){
1456      l->content=(services*)malloc(SERVICES_SIZE);
1457      l->content->content=dupService(psContent);
1458      l->content->next=NULL;
1459    }
1460    else{
1461      services* psServ=l->content;
1462      while(psServ->next!=NULL)
1463        psServ=psServ->next;
1464      psServ->next=(services*)malloc(SERVICES_SIZE);
1465      psServ->next->content=dupService(psContent);
1466      psServ->next->next=NULL;
1467    }
1468    l->next=NULL;
1469    if(isInitial>0)
1470      *prReg=l;
1471    else{
1472      registry *prCurs=*prReg;
1473      while(prCurs->next!=NULL)
1474        prCurs=prCurs->next;
1475      prCurs->next=l;
1476      prCurs->next->next=NULL;
1477    }
1478    return true;
1479  }
1480  else
1481    return false;
1482}
1483
1484/**
1485 * Free memory allocated for the registry
1486 *
1487 * @param prReg the registry
1488 */
1489void freeRegistry(registry** prReg){
1490  registry* prLocalRef=*prReg;
1491  while(prLocalRef!=NULL){
1492    services* psServ=prLocalRef->content;
1493    free(prLocalRef->name);
1494    while(psServ!=NULL){
1495      service* psServ1=psServ->content;
1496      psServ=psServ->next;
1497      if(psServ1!=NULL){
1498        freeService(&psServ1);
1499        free(psServ1);
1500        psServ1=NULL;
1501      }
1502    }
1503    prLocalRef=prLocalRef->next;
1504  }   
1505}
1506
1507/**
1508 * Access a service in the registry
1509 *
1510 * @param prReg the registry
1511 * @param pcLevel the regitry to search ("concept", "generic" or "implementation")
1512 * @param pcName the service name
1513 * @return the service pointer if a corresponding service was found or NULL
1514 */
1515service* getServiceFromRegistry(registry* prReg,char  *pcLevel,char* pcName){
1516  registry *prLocalRef=prReg;
1517  while(prLocalRef!=NULL){
1518    if(strcasecmp(prLocalRef->name,pcLevel)==0){
1519      services* psServ=prLocalRef->content;
1520      while(psServ!=NULL){
1521        if(psServ->content!=NULL && strcasecmp(psServ->content->name,pcName)==0)
1522          return psServ->content;
1523        psServ=psServ->next;
1524      }
1525      break;
1526    }
1527    prLocalRef=prLocalRef->next;
1528  }
1529  return NULL;
1530}
1531
1532/**
1533 * Apply inheritance to an out map from a reference in map
1534 *
1535 * @param ppmOut the map to update
1536 * @param pmIn the reference map (containing inherited properties)
1537 */
1538void inheritMap(map** ppmOut,map* pmIn){
1539  map* pmContent=pmIn;
1540  if((*ppmOut)==NULL){
1541    addMapToMap(ppmOut,pmIn);
1542    return;
1543  }
1544  while(pmContent!=NULL){
1545    map* pmCurrent=getMap(*ppmOut,pmContent->name);
1546    if(pmCurrent==NULL)
1547      addToMap(*ppmOut,pmCurrent->name,pmCurrent->value);
1548    pmCurrent=pmCurrent->next;
1549  }
1550}
1551
1552/**
1553 * Apply inheritance to an out iotype from a reference in iotype
1554 *
1555 * @param ppiotOut the iotype to update
1556 * @param piotIn the reference iotype (containing inherited properties)
1557 */
1558void inheritIOType(iotype** ppiotOut,iotype* piotIn){
1559  iotype* piotInCurosor=piotIn;
1560  iotype* ppiotOutCursor=*ppiotOut;
1561  if(piotInCurosor!=NULL){
1562    if(*ppiotOut==NULL){
1563      *ppiotOut=(iotype*)malloc(IOTYPE_SIZE);
1564      (*ppiotOut)->content=NULL;
1565      addMapToMap(&(*ppiotOut)->content,piotInCurosor->content);
1566      (*ppiotOut)->next=NULL;
1567      ppiotOutCursor=*ppiotOut;
1568      inheritIOType(&ppiotOutCursor->next,piotInCurosor->next);
1569    }else{
1570      inheritIOType(&ppiotOutCursor->next,piotInCurosor->next);
1571    }
1572  }
1573}
1574
1575/**
1576 * Apply inheritance to an out elements from a reference in elements
1577 *
1578 * @param ppeOut the elements to update
1579 * @param peIn the reference elements (containing inherited properties)
1580 */
1581void inheritElements(elements** ppeOut,elements* peIn){
1582  elements* peContent=peIn;
1583  while(peContent!=NULL && *ppeOut!=NULL){
1584    elements* peCurrent=getElements(*ppeOut,peContent->name);
1585    if(peCurrent==NULL)
1586      addToElements(ppeOut,peContent);
1587    else{
1588      inheritMap(&peCurrent->content,peContent->content);
1589      inheritMap(&peCurrent->metadata,peContent->metadata);
1590      if(peCurrent->format==NULL && peContent->format!=NULL)
1591        peCurrent->format=zStrdup(peContent->format);
1592      inheritIOType(&peCurrent->defaults,peContent->defaults);
1593      if(peCurrent->supported==NULL)
1594        inheritIOType(&peCurrent->supported,peContent->supported);
1595      else{
1596        iotype* piotTmp=peContent->supported;
1597        while(piotTmp!=NULL){
1598          addMapToIoType(&peCurrent->supported,piotTmp->content);
1599          piotTmp=piotTmp->next;
1600        }
1601      }
1602    }
1603    peContent=peContent->next;
1604  }
1605}
1606
1607/**
1608 * Apply inheritance to a service based on a registry
1609 *
1610 * @param prReg the registry storing profiles hierarchy
1611 * @param psServ the service to update depending on its inheritance
1612 */
1613void inheritance(registry *prReg,service** psServ){
1614  service* psCursor=*psServ;
1615  map *profile,*level;
1616  if(prReg==NULL)
1617    return;
1618  if(psCursor==NULL || psCursor->content==NULL)
1619    return;
1620  profile=getMap(psCursor->content,"extend");
1621  level=getMap(psCursor->content,"level");
1622  if(profile!=NULL&&level!=NULL){
1623    service* s1;
1624    if(strncasecmp(level->value,"profile",7)==0)
1625      s1=getServiceFromRegistry(prReg,(char*)"generic",profile->value);
1626    else
1627      s1=getServiceFromRegistry(prReg,level->value,profile->value);
1628     
1629    inheritMap(&psCursor->content,s1->content);
1630    inheritMap(&psCursor->metadata,s1->metadata);
1631    if(psCursor->inputs==NULL && s1->inputs!=NULL){
1632      psCursor->inputs=dupElements(s1->inputs);
1633    }else{
1634      inheritElements(&psCursor->inputs,s1->inputs);
1635    }
1636    if(psCursor->outputs==NULL && s1->outputs!=NULL){
1637      psCursor->outputs=dupElements(s1->outputs);
1638    }else
1639      inheritElements(&psCursor->outputs,s1->outputs);
1640  }
1641}
1642
1643/**
1644 * Convert a maps to a char*** (only used for Fortran support)
1645 *
1646 * @param pmsMap the maps to convert
1647 * @param pppcValues the resulting array
1648 */
1649void mapsToCharXXX(maps* pmsMap,char*** pppcValues){
1650  maps* pmsCursor=pmsMap;
1651  int i=0;
1652  int j=0;
1653  char aaacTmp[10][30][1024];
1654  memset(aaacTmp,0,1024*10*10);
1655  while(pmsCursor!=NULL){
1656    map* pmContent=pmsCursor->content;
1657    if(i>=10)
1658      break;
1659    strcpy(aaacTmp[i][j],"name");
1660    j++;
1661    strcpy(aaacTmp[i][j],pmsCursor->name);
1662    j++;
1663    while(pmContent!=NULL){
1664      if(j>=30)
1665        break;
1666      strcpy(aaacTmp[i][j],pmContent->name);
1667      j++;
1668      strcpy(aaacTmp[i][j],pmContent->value);
1669      j++;
1670      pmContent=pmContent->next;
1671    }
1672    pmsCursor=pmsCursor->next;
1673    j=0;
1674    i++;
1675  }
1676  memcpy(pppcValues,aaacTmp,10*10*1024);
1677}
1678
1679/**
1680 * Convert a char*** to a maps (only used for Fortran support)
1681 *
1682 * @param pppcValues the array to convert
1683 * @param ppmsMaps the resulting maps
1684 */
1685void charxxxToMaps(char*** pppcValues,maps** ppmsMaps){
1686  maps* pmsCursor=*ppmsMaps;
1687  int i,j;
1688  char aaaTmp[10][30][1024];
1689  memcpy(aaaTmp,pppcValues,10*30*1024);
1690  for(i=0;i<10;i++){
1691    if(strlen(aaaTmp[i][1])==0)
1692      break;
1693    pmsCursor->name=aaaTmp[i][1];
1694    pmsCursor->content=NULL;
1695    pmsCursor->next=NULL;
1696    for(j=2;j<29;j+=2){
1697      if(strlen(aaaTmp[i][j+1])==0)
1698        break;
1699      if(pmsCursor->content==NULL)
1700        pmsCursor->content=createMap(aaaTmp[i][j],aaaTmp[i][j+1]);
1701      else
1702        addToMap(pmsCursor->content,aaaTmp[i][j],aaaTmp[i][j+1]);
1703    }
1704    pmsCursor=pmsCursor->next;
1705  }
1706  ppmsMaps=&pmsCursor;
1707}
1708
1709/**
1710 * Verify that a map has a value
1711 *
1712 * @param pmMap pointer to map that should be checked
1713 * @return true if map has a value or false if value is missing/empty/NULL
1714 */
1715bool nonempty(map* pmMap) {
1716  return (pmMap != NULL && pmMap->value != NULL && strlen(pmMap->value) > 0 && strcmp(pmMap->value, "NULL") != 0);
1717}
1718
1719/**
1720 * Verify that a particular map value exists in a maps
1721 * data structure, and obtain that value
1722 *
1723 * @param pmsSource pointer to maps structure
1724 * @param pccNode name of maps node to search
1725 * @param pccKey name of map node to find
1726 * @param ppmKvp address to the map* if it exists, otherwise NULL
1727 * @return true if map has a value or false if value is missing/NULL
1728 *
1729 * @note The map assigned to kvp is owned by the source maps
1730 */
1731bool hasvalue(maps* pmsSource, const char* pccNode, const char* pccKey, map** ppmKvp) {
1732  *ppmKvp = getMapFromMaps(pmsSource, pccNode, pccKey);
1733  return (*ppmKvp != NULL && (*ppmKvp)->value != NULL &&
1734          strlen((*ppmKvp)->value) > 0 && strcmp((*ppmKvp)->value, "NULL") != 0);
1735}
1736
1737/*
1738 * Set error message in configuration maps
1739 *
1740 * @param pmsaConf reference to configuration maps
1741 * @param pccService name of service
1742 * @param weExc WPSException code
1743 * @param pccMessage exception text (default: exception text in WPS specification)
1744 */
1745void setErrorMessage(maps*& pmsaConf, const char* pccService, WPSException weExc, const char* pccMessage) {
1746  if (pccMessage == NULL) {
1747    pccMessage = WPSExceptionText[weExc];
1748  }
1749  size_t len = strlen(pccService) + strlen(": ") + strlen(pccMessage) + strlen(": ") + strlen(WPSExceptionCode[weExc]) + 16;
1750  char* pcMsg = (char*)malloc(len * sizeof(char));
1751  if (pcMsg != NULL) {
1752    snprintf(pcMsg, len * sizeof(char), "\n%s: %s: %s\n", pccService, pccMessage, WPSExceptionCode[weExc]);
1753    setMapInMaps(pmsaConf, "lenv", "message", pcMsg);
1754    free(pcMsg);
1755  }
1756}
1757
1758/**
1759 * Print debug message
1760 *
1761 * @param pccSource the file invoking the function
1762 * @param pccFunction the function calling for logMessage
1763 * @param iLine the line number
1764 * @param pccFile the file to log informations
1765 * @param pccMessage the message to be print
1766 */
1767void logMessage(const char* pccSource, const char* pccFunction, int iLne, const char* pccFile, const char* pccMessage) { //, const char* source, const char* function, int line) {
1768
1769  size_t msglen = 512;
1770  const char empty[] = "";
1771
1772  FILE* pfLog;
1773
1774  // system time, process time [nanoseconds]   
1775  unsigned long long sys_t, proc_t;
1776
1777  // processor time consumed by the program:
1778  clock_t t = clock();
1779
1780  // system time:
1781  std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
1782
1783  std::time_t now_t = std::chrono::system_clock::to_time_t(now);
1784  std::tm* tm = localtime(&now_t);
1785  char* pcStr = asctime(tm);
1786  pcStr[strlen(pcStr) - 1] = '\0'; // remove newline
1787
1788  sys_t = std::chrono::duration_cast<std::chrono::nanoseconds>(now.time_since_epoch()).count();
1789  //proc_t = (unsigned long long)(1.0e9*t/CLOCKS_PER_SEC);
1790  proc_t = t;
1791
1792  if (pccMessage != NULL) {
1793    msglen += strlen(pccMessage);
1794  }
1795  else {
1796    pccMessage = empty;
1797  }
1798  //getLastErrorMessage(); // cgiScriptName 
1799  char* pcText = (char*)malloc(sizeof(char)*msglen);
1800
1801  snprintf(pcText, msglen, "pid: %d %s line %d %s() %s systime: %lld ns ticks: %lld %s\n",
1802           zGetpid(), pccSource, iLne, pccFunction, pcStr, sys_t, proc_t, pccMessage); // __FILE__ __LINE__ __func__ //
1803
1804  if (pccFile != NULL && (pfLog = fopen(pccFile, "a+")) != NULL) {
1805    fputs(pcText, pfLog);
1806    fclose(pfLog);
1807  }
1808  else {
1809#ifdef MSG_LOG_FILE
1810    if ((pfLog = fopen(MSG_LOG_FILE, "a+")) != NULL) {
1811      fputs(pcText, pfLog);
1812      fclose(pfLog);
1813    }
1814#endif
1815  }
1816
1817  if (pcText != NULL) free(pcText);
1818}
1819
1820// knut:
1821// Example:
1822// zooLog;
1823// zooLogMsg(NULL, getLastErrorMessage());
1824// zooLogMsg("log.txt", getLastErrorMessage());
1825
1826#ifdef WIN32
1827#ifndef USE_MS
1828char *strcasestr (char const *pccA, char const *pccB)
1829  {
1830    char *pcX = zStrdup (pccA);
1831    char *pcY = zStrdup (pccB);
1832 
1833      pcX = _strlwr (pcX);
1834      pcY = _strlwr (pcY);
1835    char *pos = strstr (pcX, pcY);
1836    char *ret = pos == NULL ? NULL : (char *) (pccA + (pos - pcX));
1837      free (pcX);
1838      free (pcY);
1839      return ret;
1840  };
1841#else
1842   ;
1843#endif
1844#endif
1845
1846/*
1847 * Dynamically allocate memory for a map value
1848 *
1849 * @param node the map for which the value buffer should be allocated
1850 * @param num_bytes the number of bytes to allocate
1851 * @return pointer to the allocated memory buffer
1852 *
1853 * This function will free, and hence delete, any existing value in the map.
1854 * The memory should be deallocated by calling freeMap.
1855 */
1856char* allocateMapValue(map* pmNode, size_t sNumBytes)
1857{
1858  if (pmNode == NULL) {
1859    return NULL;
1860  }
1861
1862  if (pmNode->value != NULL) {
1863    free(pmNode->value);
1864  }
1865  pmNode->value = (char*) malloc(sNumBytes);
1866               
1867  return pmNode->value;
1868}
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