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

Last change on this file was 984, checked in by djay, 8 months ago

Take into account building ZOO-Project on ubuntu focal (cf. https://trac.osgeo.org/osgeolive/ticket/2282). Add the OTB and SAGA support to the Dockerfile to make the corresponding demos using docker WPS server. Add OGC API - Processes demo to the demos list.

  • 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        return;
841      }
842      else{
843        addMapToMap(&pmsTmp1->content,pmsTmp->content);
844        if(pmsTmp->child!=NULL)
845          pmsTmp1->child=dupMaps(&pmsTmp->child);
846        else
847          pmsTmp1->child=NULL;
848      }
849      pmsCursor=*ppmsOut;
850    }
851    pmsTmp=pmsTmp->next;
852  }
853}
854
855/**
856 * Access a specific map array element
857 *
858 * @param pmMap the map to search for the key
859 * @param pccKey the key to search in the map
860 * @param iIndex of the MapArray
861 * @return a pointer on the map found or NULL if not found
862 */
863map* getMapArray(map* pmMap,const char* pccKey,int iIndex){
864  char acTmp[1024];
865  map* pmTmp;
866  if(iIndex>0)
867    sprintf(acTmp,"%s_%d",pccKey,iIndex);
868  else
869    sprintf(acTmp,"%s",pccKey);
870#ifdef DEBUG
871  fprintf(stderr,"** KEY %s\n",acTmp);
872#endif
873  pmTmp=getMap(pmMap,acTmp);
874#ifdef DEBUG
875  if(pmTmp!=NULL)
876    dumpMap(pmTmp);
877#endif
878  return pmTmp;
879}
880
881/**
882 * Add a key value in a MapArray for a specific index
883 *
884 * @param pmMap the map to search for the key
885 * @param pccKey the key to search in the map
886 * @param iIndex the index of the MapArray
887 * @param pccValue the value to set in the MapArray
888 * @return a pointer on the map found or NULL if not found
889 */
890void setMapArray(map* pmMap,const char* pccKey,int iIndex,const char* pccValue){
891  char acTmp[1024];
892  map* pmSize;
893  if(iIndex>0){
894    map* pmLen=getMap(pmMap,"length");
895    sprintf(acTmp,"%s_%d",pccKey,iIndex);
896    if((pmLen!=NULL && atoi(pmLen->value)<iIndex+1) || pmLen==NULL){
897      char acTmp0[5];
898      sprintf(acTmp0,"%d",iIndex+1);
899      addToMap(pmMap,"length",acTmp0);
900    }
901  }
902  else{
903    sprintf(acTmp,"%s",pccKey);
904    addToMap(pmMap,"length","1");
905  }
906  pmSize=getMapArray(pmMap,"size",iIndex);
907  if(pmSize!=NULL && strncasecmp(pccKey,"value",5)==0){
908    map* pmPtr=getMapOrFill(&pmMap,acTmp,(char *)"");
909#ifdef DEBUG
910    fprintf(stderr,"%s\n",pmSize->value);
911#endif
912    free(pmPtr->value);
913    pmPtr->value=(char*)malloc((atoi(pmSize->value)+1)*sizeof(char));
914    memcpy(pmPtr->value,pccValue,atoi(pmSize->value)); 
915  }
916  else
917    addToMap(pmMap,acTmp,pccValue);
918}
919
920/**
921 * Add a key and an integer value to an existing map array.
922 *
923 * @param pmMap the map to add the KVP
924 * @param pccName the key to add
925 * @param iIndex the index of the MapArray
926 * @param icValue the corresponding value to add
927 */
928void addIntToMapArray(map* pmMap,const char* pccName,int iIndex,const int icValue){
929  char acValue[10];
930  sprintf(acValue,"%d",icValue);
931  setMapArray(pmMap,pccName,iIndex,acValue);
932}
933
934/**
935 * Access the map "type"
936 *
937 * @param pmMap the map
938 * @return a pointer on the map for mimeType/dataType/CRS if found, NULL in
939 *  other case
940 */
941map* getMapType(map* pmMap){
942  map* pmMime=getMap(pmMap,(char *)"mimeType");
943  if(pmMime==NULL){
944    pmMime=getMap(pmMap,"dataType");
945    if(pmMime==NULL){
946      pmMime=getMap(pmMap,"CRS");
947    }
948  }
949#ifdef DEBUG
950  dumpMap(pmMime);
951#endif
952  return pmMime;
953}
954
955/**
956 * Add a Maps containing a MapArray to a Maps
957 *
958 * @see getMapType
959 * @param pmsOut the maps
960 * @param pmsIn the maps
961 * @param pcType the map "type"
962 * @return
963 */
964int addMapsArrayToMaps(maps** pmsOut,maps* pmsIn,char* pcType){
965  maps* pmsTmp=pmsIn;
966  maps* pmsCursor=getMaps(*pmsOut,pmsTmp->name);
967  char acLen[10];
968  int iLen=1;
969  char *acV[14]={
970    (char*)"size",
971    (char*)"value",
972    (char*)"uom",
973    (char*)"Reference",
974    (char*)"Order",
975    (char*)"cache_file",
976    (char*)"fmimeType",
977    (char*)"xlink:href",
978    pcType,
979    (char*)"schema",
980    (char*)"encoding",
981    (char*)"isCached",
982    (char*)"LowerCorner",
983    (char*)"UpperCorner"
984  };
985  int iCounter=0;
986  map* pmLength;
987 
988  if(pmsCursor==NULL)
989    return -1;
990
991  pmLength=getMap(pmsCursor->content,"length");
992  if(pmLength!=NULL){
993    iLen=atoi(pmLength->value);
994  }
995
996  sprintf(acLen,"%d",iLen+1);
997  addToMap(pmsCursor->content,"length",acLen);
998  for(iCounter=0;iCounter<14;iCounter++){
999    map* pmTmp=getMap(pmsTmp->content,acV[iCounter]);
1000    if(pmTmp!=NULL){
1001#ifdef DEBUG
1002      fprintf(stderr,"%s = %s\n",pmTmp[iCounter],pmTmp->value);
1003#endif
1004      setMapArray(pmsCursor->content,acV[iCounter],iLen,pmTmp->value);
1005    }
1006  }
1007   
1008  addToMap(pmsCursor->content,"isArray","true");
1009  return 0;
1010}
1011
1012/**
1013 * Set a key value pair to a map contained in a Maps
1014 *
1015 * @param pmsMaps the maps
1016 * @param pccKey the maps name
1017 * @param pccSubkey the map name included in the maps corresponding to key
1018 * @param pccValue the corresponding value to add in the map
1019 */
1020void setMapInMaps(maps* pmsMaps,const char* pccKey,const char* pccSubkey,const char *pccValue){
1021  maps* pmsTmp=getMaps(pmsMaps,pccKey);
1022  if(pmsTmp!=NULL){
1023    map* pmTmpSub=getMap(pmsTmp->content,pccSubkey);
1024    if(pmTmpSub!=NULL){
1025      if(pmTmpSub->value!=NULL)
1026        free(pmTmpSub->value);
1027      pmTmpSub->value=zStrdup(pccValue);
1028    }else{
1029      maps *pmsToAdd=createMaps(pccKey);
1030      pmsToAdd->content=createMap(pccSubkey,pccValue);
1031      addMapsToMaps(&pmsTmp,pmsToAdd);
1032      freeMaps(&pmsToAdd);
1033      free(pmsToAdd);
1034    }
1035  }else{
1036    maps *pmsToAdd=createMaps(pccKey);
1037    pmsToAdd->content=createMap(pccSubkey,pccValue);
1038    addMapsToMaps(&pmsMaps,pmsToAdd);
1039    freeMaps(&pmsToAdd);
1040    free(pmsToAdd);
1041  }
1042}
1043
1044/**
1045 * Create an empty elements
1046 *
1047 * @return a pointer to the allocated elements
1048 */
1049elements* createEmptyElements(){
1050  elements* peRes=(elements*)malloc(ELEMENTS_SIZE);
1051  peRes->name=NULL;
1052  peRes->content=NULL;
1053  peRes->metadata=NULL;
1054  peRes->additional_parameters=NULL; 
1055  peRes->format=NULL;
1056  peRes->defaults=NULL;
1057  peRes->supported=NULL;
1058  peRes->child=NULL;
1059  peRes->next=NULL;
1060  return peRes;
1061}
1062
1063/**
1064 * Create a named elements
1065 *
1066 * @param pcName the elements name
1067 * @return a pointer to the allocated elements
1068 */
1069elements* createElements(const char* pcName){
1070  elements* peRes=(elements*)malloc(ELEMENTS_SIZE);
1071  peRes->name=zStrdup(pcName);
1072  peRes->content=NULL;
1073  peRes->metadata=NULL;
1074  peRes->additional_parameters=NULL;
1075  peRes->format=NULL;
1076  peRes->defaults=NULL;
1077  peRes->supported=NULL;
1078  peRes->child=NULL;
1079  peRes->next=NULL;
1080  return peRes;
1081}
1082
1083/**
1084 * Set the name of an elements
1085 *
1086 * @param peElem the elements to modify
1087 * @param pcName the elements name
1088 * @return a pointer to the allocated elements
1089 */
1090void setElementsName(elements** ppeElem,char* pcName){
1091  elements* peRes=*ppeElem;
1092  peRes->name=zStrdup(pcName);
1093  peRes->content=NULL;
1094  peRes->metadata=NULL;
1095  peRes->format=NULL;
1096  peRes->defaults=NULL;
1097  peRes->supported=NULL;
1098  peRes->child=NULL;
1099  peRes->next=NULL;
1100}
1101
1102/**
1103 * Dump an elements on stderr
1104 *
1105 * @param peElem the elements to dump
1106 */
1107void dumpElements(elements* peElem){
1108  elements* peTmp=peElem;
1109  while(peTmp!=NULL){
1110    iotype* piotTmp=peTmp->defaults;
1111    int ioc=0;
1112    fprintf(stderr,"ELEMENT [%s]\n",peTmp->name);
1113    fprintf(stderr," > CONTENT [%s]\n",peTmp->name);
1114    dumpMap(peTmp->content);
1115    fprintf(stderr," > METADATA [%s]\n",peTmp->name);
1116    dumpMap(peTmp->metadata);
1117    fprintf(stderr," > ADDITIONAL PARAMETERS [%s]\n",peTmp->name);
1118    dumpMap(peTmp->additional_parameters);
1119    fprintf(stderr," > FORMAT [%s]\n",peTmp->format);
1120    while(piotTmp!=NULL){
1121      fprintf(stderr," > DEFAULTS [%s] (%i)\n",peTmp->name,ioc);
1122      dumpMap(piotTmp->content);
1123      piotTmp=piotTmp->next;
1124      ioc++;
1125    }
1126    piotTmp=peTmp->supported;
1127    ioc=0;
1128    while(piotTmp!=NULL){
1129      fprintf(stderr," > SUPPORTED [%s] (%i)\n",peTmp->name,ioc);
1130      dumpMap(piotTmp->content);
1131      piotTmp=piotTmp->next;
1132      ioc++;
1133    }
1134    if(peTmp->child!=NULL){
1135      fprintf(stderr," > CHILD \n");
1136      dumpElements(peTmp->child);
1137    }
1138    fprintf(stderr,"------------------\n");
1139    peTmp=peTmp->next;
1140  }
1141}
1142
1143/**
1144 * Dump an elements on stderr using the YAML syntaxe
1145 *
1146 * @param peElem the elements to dump
1147 * @param iLevel the current level
1148 */
1149void dumpElementsAsYAML(elements* peElem,int iLevel){
1150  elements* peTmp=peElem;
1151  int i;
1152  while(peTmp!=NULL){
1153    map* pmCurs=peTmp->content;
1154    int ioc=0;
1155    iotype* piotTmp;
1156    for(i=0;i<2+(4*iLevel);i++)
1157      fprintf(stderr," ");
1158    fprintf(stderr,"%s:\n",peTmp->name);
1159    while(pmCurs!=NULL){
1160      for(i=0;i<4+(4*iLevel);i++)
1161        fprintf(stderr," ");
1162      _dumpMap(pmCurs);
1163      pmCurs=pmCurs->next;
1164    }
1165    pmCurs=peTmp->metadata;
1166    if(pmCurs!=NULL){
1167      for(i=0;i<4+(4*iLevel);i++)
1168        fprintf(stderr," ");
1169      fprintf(stderr,"MetaData:\n");
1170      while(pmCurs!=NULL){
1171        for(i=0;i<6+(4*iLevel);i++)
1172          fprintf(stderr," ");
1173        _dumpMap(pmCurs);
1174        pmCurs=pmCurs->next;
1175      }
1176    }
1177    for(i=0;i<4+(4*iLevel);i++)
1178      fprintf(stderr," ");
1179    if(peTmp->format!=NULL)
1180      fprintf(stderr,"%s:\n",peTmp->format);
1181    else{
1182      fprintf(stderr,"Child:\n");
1183      if(peTmp->child!=NULL)
1184        dumpElementsAsYAML(peTmp->child,iLevel+1);
1185    }
1186    piotTmp=peTmp->defaults;
1187    while(piotTmp!=NULL){
1188      for(i=0;i<6+(4*iLevel);i++)
1189        fprintf(stderr," ");
1190      fprintf(stderr,"default:\n");
1191      pmCurs=piotTmp->content;
1192      while(pmCurs!=NULL){
1193        for(i=0;i<8+(4*iLevel);i++)
1194          fprintf(stderr," ");
1195        if(strcasecmp(pmCurs->name,"range")==0){
1196          fprintf(stderr,"range: \"%s\"\n",pmCurs->value);
1197        }else
1198          _dumpMap(pmCurs);
1199        pmCurs=pmCurs->next;
1200      }
1201      piotTmp=piotTmp->next;
1202      ioc++;
1203    }
1204    piotTmp=peTmp->supported;
1205    ioc=0;
1206    while(piotTmp!=NULL){
1207      for(i=0;i<6+(4*iLevel);i++)
1208        fprintf(stderr," ");
1209      fprintf(stderr,"supported:\n");
1210      pmCurs=piotTmp->content;
1211      while(pmCurs!=NULL){
1212        for(i=0;i<8+(4*iLevel);i++)
1213          fprintf(stderr," ");
1214        if(strcasecmp(pmCurs->name,"range")==0){
1215          fprintf(stderr,"range: \"%s\"\n",pmCurs->value);
1216        }else
1217          _dumpMap(pmCurs);
1218        pmCurs=pmCurs->next;
1219      }
1220      piotTmp=piotTmp->next;
1221      ioc++;
1222    }
1223    peTmp=peTmp->next;
1224  }
1225}
1226
1227/**
1228 * Duplicate an elements
1229 *
1230 * @param peElem the elements to clone
1231 * @return the allocated elements containing a copy of the elements e
1232 */
1233elements* dupElements(elements* peElem){
1234  elements* peCursor=peElem;
1235  elements* peTmp=NULL;
1236  if(peCursor!=NULL && peCursor->name!=NULL){
1237#ifdef DEBUG
1238    fprintf(stderr,">> %s %i\n",__FILE__,__LINE__);
1239    dumpElements(e);
1240    fprintf(stderr,">> %s %i\n",__FILE__,__LINE__);
1241#endif
1242    peTmp=(elements*)malloc(ELEMENTS_SIZE);
1243    peTmp->name=zStrdup(peCursor->name);
1244    peTmp->content=NULL;
1245    addMapToMap(&peTmp->content,peCursor->content);
1246    peTmp->metadata=NULL;
1247    addMapToMap(&peTmp->metadata,peCursor->metadata);
1248    peTmp->additional_parameters=NULL;
1249    addMapToMap(&peTmp->additional_parameters,peCursor->additional_parameters);
1250    if(peCursor->format!=NULL)
1251      peTmp->format=zStrdup(peCursor->format);
1252    else
1253      peTmp->format=NULL;
1254    if(peCursor->defaults!=NULL){
1255      peTmp->defaults=(iotype*)malloc(IOTYPE_SIZE);
1256      peTmp->defaults->content=NULL;
1257      addMapToMap(&peTmp->defaults->content,peCursor->defaults->content);
1258      peTmp->defaults->next=NULL;
1259#ifdef DEBUG
1260      fprintf(stderr,">> %s %i\n",__FILE__,__LINE__);
1261      dumpMap(peTmp->defaults->content);
1262#endif
1263    }else
1264      peTmp->defaults=NULL;
1265    if(peCursor->supported!=NULL && peCursor->supported->content!=NULL){
1266      iotype *piotTmp=peCursor->supported->next;
1267      peTmp->supported=(iotype*)malloc(IOTYPE_SIZE);
1268      peTmp->supported->content=NULL;
1269      addMapToMap(&peTmp->supported->content,peCursor->supported->content);
1270      peTmp->supported->next=NULL;
1271            while(piotTmp!=NULL){
1272        addMapToIoType(&peTmp->supported,piotTmp->content);
1273#ifdef DEBUG
1274        fprintf(stderr,">> %s %i\n",__FILE__,__LINE__);
1275        dumpMap(peTmp->defaults->content);
1276#endif
1277        piotTmp=piotTmp->next;
1278      }
1279    }
1280    else
1281      peTmp->supported=NULL;
1282    if(peCursor->child!=NULL)
1283      peTmp->child=dupElements(peCursor->child);
1284    else
1285      peTmp->child=NULL;
1286    if(peCursor->next!=NULL)
1287      peTmp->next=dupElements(peCursor->next);
1288    else
1289      peTmp->next=NULL;
1290  }
1291  return peTmp;
1292}
1293
1294/**
1295 * Add an elements to another elements.
1296 *
1297 * @see dupElements
1298 * @param ppeElem the elements to add the e
1299 * @param peELem the elements to be added to m
1300 */
1301void addToElements(elements** ppeElem,elements* peELem){
1302  elements* peTmp=peELem;
1303  if(*ppeElem==NULL){
1304    (*ppeElem)=dupElements(peTmp);
1305  }else{
1306    addToElements(&(*ppeElem)->next,peTmp);
1307  }
1308}
1309
1310/**
1311 * Set the name of a service
1312 *
1313 * @param ppsServ the service
1314 * @param pcName the service name
1315 */
1316void setServiceName(service** ppsServ,char* pcName){
1317  service* psRes=*ppsServ;
1318  psRes->name=zStrdup(pcName);
1319  psRes->content=NULL;
1320  psRes->metadata=NULL;
1321  psRes->inputs=NULL;
1322  psRes->outputs=NULL;
1323}
1324
1325/**
1326 * Dump a service on stderr
1327 *
1328 * @param psServ the service to dump
1329 */
1330void dumpService(service* psServ){
1331  if(psServ==NULL)
1332    return;
1333  fprintf(stderr,"++++++++++++++++++\nSERVICE [%s]\n++++++++++++++++++\n",psServ->name);
1334  if(psServ->content!=NULL){
1335    fprintf(stderr,"CONTENT MAP\n");
1336    dumpMap(psServ->content);
1337    if(psServ->metadata!=NULL)
1338      fprintf(stderr,"CONTENT METADATA\n");
1339    dumpMap(psServ->metadata);
1340    if(psServ->additional_parameters!=NULL)
1341      fprintf(stderr,"CONTENT AdditionalParameters\n");
1342    dumpMap(psServ->additional_parameters);
1343  }
1344  if(psServ->inputs!=NULL){
1345    fprintf(stderr,"INPUT ELEMENTS [%s]\n------------------\n",psServ->name);
1346    dumpElements(psServ->inputs);
1347  }
1348  if(psServ->outputs!=NULL){
1349    fprintf(stderr,"OUTPUT ELEMENTS [%s]\n------------------\n",psServ->name);
1350    dumpElements(psServ->outputs);
1351  }
1352  fprintf(stderr,"++++++++++++++++++\n");
1353}
1354
1355/**
1356 * Dump a service on stderr using the YAML syntaxe
1357 *
1358 * @param psServ the service to dump
1359 */
1360void dumpServiceAsYAML(service* psServ){
1361  int i;
1362  fprintf(stderr,"# %s\n\n",psServ->name);
1363  if(psServ->content!=NULL){
1364    map* pmCurs=psServ->content;
1365    dumpMap(pmCurs);
1366    pmCurs=psServ->metadata;
1367    if(pmCurs!=NULL){
1368      fprintf(stderr,"MetaData:\n");
1369      while(pmCurs!=NULL){
1370        for(i=0;i<2;i++)
1371          fprintf(stderr," ");
1372        _dumpMap(pmCurs);
1373        pmCurs=pmCurs->next;
1374      }
1375    }
1376  }
1377  if(psServ->inputs!=NULL){
1378    fprintf(stderr,"\ninputs:\n");
1379    dumpElementsAsYAML(psServ->inputs,0);
1380  }
1381  if(psServ->outputs!=NULL){
1382    fprintf(stderr,"\noutputs:\n");
1383    dumpElementsAsYAML(psServ->outputs,0);
1384  }
1385}
1386
1387/**
1388 * Duplicate a service
1389 *
1390 * @param psServ the service to clone
1391 * @return the allocated service containing a copy of the serfvice s
1392 */
1393service* dupService(service* psServ){
1394  service *psRes=(service*)malloc(SERVICE_SIZE);
1395  psRes->name=zStrdup(psServ->name);
1396  psRes->content=NULL;
1397  addMapToMap(&psRes->content,psServ->content);
1398  psRes->metadata=NULL;
1399  addMapToMap(&psRes->metadata,psServ->metadata);
1400  psRes->additional_parameters=NULL;
1401  addMapToMap(&psRes->additional_parameters,psServ->additional_parameters);
1402  psRes->inputs=dupElements(psServ->inputs);
1403  psRes->outputs=dupElements(psServ->outputs);
1404  return psRes;
1405}
1406
1407/**
1408 * Print the registry on stderr.
1409 *
1410 * @param prReg the registry
1411 */
1412void dumpRegistry(registry* prReg){
1413  registry* prCurs=prReg;
1414  while(prCurs!=NULL){
1415    services* psServ=prCurs->content;
1416    fprintf(stderr,"%s \n",prCurs->name);
1417    psServ=prCurs->content;
1418    while(psServ!=NULL){
1419      dumpService(psServ->content);
1420      psServ=psServ->next;
1421    }
1422    prCurs=prCurs->next;
1423  }
1424}
1425
1426/**
1427 * Add a service to the registry
1428 *
1429 * @param prReg the resgitry to add the service
1430 * @param pcName the registry name to update
1431 * @param psContent the service to add
1432 */
1433bool addServiceToRegistry(registry** prReg,char* pcName,service* psContent){
1434  registry *l=*prReg;
1435  int isInitial=-1;
1436  if(l==NULL){
1437    l=(registry*)malloc(REGISTRY_SIZE);
1438    isInitial=1;
1439  }
1440  if(l!=NULL){
1441    int hasLevel=-1;
1442    while(isInitial<0 && l!=NULL){
1443      if(l->name!=NULL && strcasecmp(pcName,l->name)==0){
1444        hasLevel=1;
1445        break;
1446      }
1447      l=l->next;
1448    }
1449    if(hasLevel<0){
1450      if(isInitial<0)
1451        l=(registry*)malloc(REGISTRY_SIZE);
1452      l->name=zStrdup(pcName);
1453      l->content=NULL;
1454      l->next=NULL;
1455    }
1456    if(l->content==NULL){
1457      l->content=(services*)malloc(SERVICES_SIZE);
1458      l->content->content=dupService(psContent);
1459      l->content->next=NULL;
1460    }
1461    else{
1462      services* psServ=l->content;
1463      while(psServ->next!=NULL)
1464        psServ=psServ->next;
1465      psServ->next=(services*)malloc(SERVICES_SIZE);
1466      psServ->next->content=dupService(psContent);
1467      psServ->next->next=NULL;
1468    }
1469    l->next=NULL;
1470    if(isInitial>0)
1471      *prReg=l;
1472    else{
1473      registry *prCurs=*prReg;
1474      while(prCurs->next!=NULL)
1475        prCurs=prCurs->next;
1476      prCurs->next=l;
1477      prCurs->next->next=NULL;
1478    }
1479    return true;
1480  }
1481  else
1482    return false;
1483}
1484
1485/**
1486 * Free memory allocated for the registry
1487 *
1488 * @param prReg the registry
1489 */
1490void freeRegistry(registry** prReg){
1491  registry* prLocalRef=*prReg;
1492  while(prLocalRef!=NULL){
1493    services* psServ=prLocalRef->content;
1494    free(prLocalRef->name);
1495    while(psServ!=NULL){
1496      service* psServ1=psServ->content;
1497      psServ=psServ->next;
1498      if(psServ1!=NULL){
1499        freeService(&psServ1);
1500        free(psServ1);
1501        psServ1=NULL;
1502      }
1503    }
1504    prLocalRef=prLocalRef->next;
1505  }   
1506}
1507
1508/**
1509 * Access a service in the registry
1510 *
1511 * @param prReg the registry
1512 * @param pcLevel the regitry to search ("concept", "generic" or "implementation")
1513 * @param pcName the service name
1514 * @return the service pointer if a corresponding service was found or NULL
1515 */
1516service* getServiceFromRegistry(registry* prReg,char  *pcLevel,char* pcName){
1517  registry *prLocalRef=prReg;
1518  while(prLocalRef!=NULL){
1519    if(strcasecmp(prLocalRef->name,pcLevel)==0){
1520      services* psServ=prLocalRef->content;
1521      while(psServ!=NULL){
1522        if(psServ->content!=NULL && strcasecmp(psServ->content->name,pcName)==0)
1523          return psServ->content;
1524        psServ=psServ->next;
1525      }
1526      break;
1527    }
1528    prLocalRef=prLocalRef->next;
1529  }
1530  return NULL;
1531}
1532
1533/**
1534 * Apply inheritance to an out map from a reference in map
1535 *
1536 * @param ppmOut the map to update
1537 * @param pmIn the reference map (containing inherited properties)
1538 */
1539void inheritMap(map** ppmOut,map* pmIn){
1540  map* pmContent=pmIn;
1541  if((*ppmOut)==NULL){
1542    addMapToMap(ppmOut,pmIn);
1543    return;
1544  }
1545  while(pmContent!=NULL){
1546    map* pmCurrent=getMap(*ppmOut,pmContent->name);
1547    if(pmCurrent==NULL)
1548      addToMap(*ppmOut,pmCurrent->name,pmCurrent->value);
1549    pmCurrent=pmCurrent->next;
1550  }
1551}
1552
1553/**
1554 * Apply inheritance to an out iotype from a reference in iotype
1555 *
1556 * @param ppiotOut the iotype to update
1557 * @param piotIn the reference iotype (containing inherited properties)
1558 */
1559void inheritIOType(iotype** ppiotOut,iotype* piotIn){
1560  iotype* piotInCurosor=piotIn;
1561  iotype* ppiotOutCursor=*ppiotOut;
1562  if(piotInCurosor!=NULL){
1563    if(*ppiotOut==NULL){
1564      *ppiotOut=(iotype*)malloc(IOTYPE_SIZE);
1565      (*ppiotOut)->content=NULL;
1566      addMapToMap(&(*ppiotOut)->content,piotInCurosor->content);
1567      (*ppiotOut)->next=NULL;
1568      ppiotOutCursor=*ppiotOut;
1569      inheritIOType(&ppiotOutCursor->next,piotInCurosor->next);
1570    }else{
1571      inheritIOType(&ppiotOutCursor->next,piotInCurosor->next);
1572    }
1573  }
1574}
1575
1576/**
1577 * Apply inheritance to an out elements from a reference in elements
1578 *
1579 * @param ppeOut the elements to update
1580 * @param peIn the reference elements (containing inherited properties)
1581 */
1582void inheritElements(elements** ppeOut,elements* peIn){
1583  elements* peContent=peIn;
1584  while(peContent!=NULL && *ppeOut!=NULL){
1585    elements* peCurrent=getElements(*ppeOut,peContent->name);
1586    if(peCurrent==NULL)
1587      addToElements(ppeOut,peContent);
1588    else{
1589      inheritMap(&peCurrent->content,peContent->content);
1590      inheritMap(&peCurrent->metadata,peContent->metadata);
1591      if(peCurrent->format==NULL && peContent->format!=NULL)
1592        peCurrent->format=zStrdup(peContent->format);
1593      inheritIOType(&peCurrent->defaults,peContent->defaults);
1594      if(peCurrent->supported==NULL)
1595        inheritIOType(&peCurrent->supported,peContent->supported);
1596      else{
1597        iotype* piotTmp=peContent->supported;
1598        while(piotTmp!=NULL){
1599          addMapToIoType(&peCurrent->supported,piotTmp->content);
1600          piotTmp=piotTmp->next;
1601        }
1602      }
1603    }
1604    peContent=peContent->next;
1605  }
1606}
1607
1608/**
1609 * Apply inheritance to a service based on a registry
1610 *
1611 * @param prReg the registry storing profiles hierarchy
1612 * @param psServ the service to update depending on its inheritance
1613 */
1614void inheritance(registry *prReg,service** psServ){
1615  service* psCursor=*psServ;
1616  map *profile,*level;
1617  if(prReg==NULL)
1618    return;
1619  if(psCursor==NULL || psCursor->content==NULL)
1620    return;
1621  profile=getMap(psCursor->content,"extend");
1622  level=getMap(psCursor->content,"level");
1623  if(profile!=NULL&&level!=NULL){
1624    service* s1;
1625    if(strncasecmp(level->value,"profile",7)==0)
1626      s1=getServiceFromRegistry(prReg,(char*)"generic",profile->value);
1627    else
1628      s1=getServiceFromRegistry(prReg,level->value,profile->value);
1629     
1630    inheritMap(&psCursor->content,s1->content);
1631    inheritMap(&psCursor->metadata,s1->metadata);
1632    if(psCursor->inputs==NULL && s1->inputs!=NULL){
1633      psCursor->inputs=dupElements(s1->inputs);
1634    }else{
1635      inheritElements(&psCursor->inputs,s1->inputs);
1636    }
1637    if(psCursor->outputs==NULL && s1->outputs!=NULL){
1638      psCursor->outputs=dupElements(s1->outputs);
1639    }else
1640      inheritElements(&psCursor->outputs,s1->outputs);
1641  }
1642}
1643
1644/**
1645 * Convert a maps to a char*** (only used for Fortran support)
1646 *
1647 * @param pmsMap the maps to convert
1648 * @param pppcValues the resulting array
1649 */
1650void mapsToCharXXX(maps* pmsMap,char*** pppcValues){
1651  maps* pmsCursor=pmsMap;
1652  int i=0;
1653  int j=0;
1654  char aaacTmp[10][30][1024];
1655  memset(aaacTmp,0,1024*10*10);
1656  while(pmsCursor!=NULL){
1657    map* pmContent=pmsCursor->content;
1658    if(i>=10)
1659      break;
1660    strcpy(aaacTmp[i][j],"name");
1661    j++;
1662    strcpy(aaacTmp[i][j],pmsCursor->name);
1663    j++;
1664    while(pmContent!=NULL){
1665      if(j>=30)
1666        break;
1667      strcpy(aaacTmp[i][j],pmContent->name);
1668      j++;
1669      strcpy(aaacTmp[i][j],pmContent->value);
1670      j++;
1671      pmContent=pmContent->next;
1672    }
1673    pmsCursor=pmsCursor->next;
1674    j=0;
1675    i++;
1676  }
1677  memcpy(pppcValues,aaacTmp,10*10*1024);
1678}
1679
1680/**
1681 * Convert a char*** to a maps (only used for Fortran support)
1682 *
1683 * @param pppcValues the array to convert
1684 * @param ppmsMaps the resulting maps
1685 */
1686void charxxxToMaps(char*** pppcValues,maps** ppmsMaps){
1687  maps* pmsCursor=*ppmsMaps;
1688  int i,j;
1689  char aaaTmp[10][30][1024];
1690  memcpy(aaaTmp,pppcValues,10*30*1024);
1691  for(i=0;i<10;i++){
1692    if(strlen(aaaTmp[i][1])==0)
1693      break;
1694    pmsCursor->name=aaaTmp[i][1];
1695    pmsCursor->content=NULL;
1696    pmsCursor->next=NULL;
1697    for(j=2;j<29;j+=2){
1698      if(strlen(aaaTmp[i][j+1])==0)
1699        break;
1700      if(pmsCursor->content==NULL)
1701        pmsCursor->content=createMap(aaaTmp[i][j],aaaTmp[i][j+1]);
1702      else
1703        addToMap(pmsCursor->content,aaaTmp[i][j],aaaTmp[i][j+1]);
1704    }
1705    pmsCursor=pmsCursor->next;
1706  }
1707  ppmsMaps=&pmsCursor;
1708}
1709
1710/**
1711 * Verify that a map has a value
1712 *
1713 * @param pmMap pointer to map that should be checked
1714 * @return true if map has a value or false if value is missing/empty/NULL
1715 */
1716bool nonempty(map* pmMap) {
1717  return (pmMap != NULL && pmMap->value != NULL && strlen(pmMap->value) > 0 && strcmp(pmMap->value, "NULL") != 0);
1718}
1719
1720/**
1721 * Verify that a particular map value exists in a maps
1722 * data structure, and obtain that value
1723 *
1724 * @param pmsSource pointer to maps structure
1725 * @param pccNode name of maps node to search
1726 * @param pccKey name of map node to find
1727 * @param ppmKvp address to the map* if it exists, otherwise NULL
1728 * @return true if map has a value or false if value is missing/NULL
1729 *
1730 * @note The map assigned to kvp is owned by the source maps
1731 */
1732bool hasvalue(maps* pmsSource, const char* pccNode, const char* pccKey, map** ppmKvp) {
1733  *ppmKvp = getMapFromMaps(pmsSource, pccNode, pccKey);
1734  return (*ppmKvp != NULL && (*ppmKvp)->value != NULL &&
1735          strlen((*ppmKvp)->value) > 0 && strcmp((*ppmKvp)->value, "NULL") != 0);
1736}
1737
1738/*
1739 * Set error message in configuration maps
1740 *
1741 * @param pmsaConf reference to configuration maps
1742 * @param pccService name of service
1743 * @param weExc WPSException code
1744 * @param pccMessage exception text (default: exception text in WPS specification)
1745 */
1746void setErrorMessage(maps*& pmsaConf, const char* pccService, WPSException weExc, const char* pccMessage) {
1747  if (pccMessage == NULL) {
1748    pccMessage = WPSExceptionText[weExc];
1749  }
1750  size_t len = strlen(pccService) + strlen(": ") + strlen(pccMessage) + strlen(": ") + strlen(WPSExceptionCode[weExc]) + 16;
1751  char* pcMsg = (char*)malloc(len * sizeof(char));
1752  if (pcMsg != NULL) {
1753    snprintf(pcMsg, len * sizeof(char), "\n%s: %s: %s\n", pccService, pccMessage, WPSExceptionCode[weExc]);
1754    setMapInMaps(pmsaConf, "lenv", "message", pcMsg);
1755    free(pcMsg);
1756  }
1757}
1758
1759/**
1760 * Print debug message
1761 *
1762 * @param pccSource the file invoking the function
1763 * @param pccFunction the function calling for logMessage
1764 * @param iLine the line number
1765 * @param pccFile the file to log informations
1766 * @param pccMessage the message to be print
1767 */
1768void logMessage(const char* pccSource, const char* pccFunction, int iLne, const char* pccFile, const char* pccMessage) { //, const char* source, const char* function, int line) {
1769
1770  size_t msglen = 512;
1771  const char empty[] = "";
1772
1773  FILE* pfLog;
1774
1775  // system time, process time [nanoseconds]   
1776  unsigned long long sys_t, proc_t;
1777
1778  // processor time consumed by the program:
1779  clock_t t = clock();
1780
1781  // system time:
1782  std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
1783
1784  std::time_t now_t = std::chrono::system_clock::to_time_t(now);
1785  std::tm* tm = localtime(&now_t);
1786  char* pcStr = asctime(tm);
1787  pcStr[strlen(pcStr) - 1] = '\0'; // remove newline
1788
1789  sys_t = std::chrono::duration_cast<std::chrono::nanoseconds>(now.time_since_epoch()).count();
1790  //proc_t = (unsigned long long)(1.0e9*t/CLOCKS_PER_SEC);
1791  proc_t = t;
1792
1793  if (pccMessage != NULL) {
1794    msglen += strlen(pccMessage);
1795  }
1796  else {
1797    pccMessage = empty;
1798  }
1799  //getLastErrorMessage(); // cgiScriptName 
1800  char* pcText = (char*)malloc(sizeof(char)*msglen);
1801
1802  snprintf(pcText, msglen, "pid: %d %s line %d %s() %s systime: %lld ns ticks: %lld %s\n",
1803           zGetpid(), pccSource, iLne, pccFunction, pcStr, sys_t, proc_t, pccMessage); // __FILE__ __LINE__ __func__ //
1804
1805  if (pccFile != NULL && (pfLog = fopen(pccFile, "a+")) != NULL) {
1806    fputs(pcText, pfLog);
1807    fclose(pfLog);
1808  }
1809  else {
1810#ifdef MSG_LOG_FILE
1811    if ((pfLog = fopen(MSG_LOG_FILE, "a+")) != NULL) {
1812      fputs(pcText, pfLog);
1813      fclose(pfLog);
1814    }
1815#endif
1816  }
1817
1818  if (pcText != NULL) free(pcText);
1819}
1820
1821// knut:
1822// Example:
1823// zooLog;
1824// zooLogMsg(NULL, getLastErrorMessage());
1825// zooLogMsg("log.txt", getLastErrorMessage());
1826
1827#ifdef WIN32
1828#ifndef USE_MS
1829char *strcasestr (char const *pccA, char const *pccB)
1830  {
1831    char *pcX = zStrdup (pccA);
1832    char *pcY = zStrdup (pccB);
1833 
1834      pcX = _strlwr (pcX);
1835      pcY = _strlwr (pcY);
1836    char *pos = strstr (pcX, pcY);
1837    char *ret = pos == NULL ? NULL : (char *) (pccA + (pos - pcX));
1838      free (pcX);
1839      free (pcY);
1840      return ret;
1841  };
1842#else
1843   ;
1844#endif
1845#endif
1846
1847/*
1848 * Dynamically allocate memory for a map value
1849 *
1850 * @param node the map for which the value buffer should be allocated
1851 * @param num_bytes the number of bytes to allocate
1852 * @return pointer to the allocated memory buffer
1853 *
1854 * This function will free, and hence delete, any existing value in the map.
1855 * The memory should be deallocated by calling freeMap.
1856 */
1857char* allocateMapValue(map* pmNode, size_t sNumBytes)
1858{
1859  if (pmNode == NULL) {
1860    return NULL;
1861  }
1862
1863  if (pmNode->value != NULL) {
1864    free(pmNode->value);
1865  }
1866  pmNode->value = (char*) malloc(sNumBytes);
1867               
1868  return pmNode->value;
1869}
Note: See TracBrowser for help on using the repository browser.

Search

Context Navigation

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