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
RevLine 
[645]1/*
2 * Author : Gérald FENOY
3 *
[917]4 * Copyright (c) 2015-2019 GeoLabs SARL
[645]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
[889]27// knut: time utilities required for new log function (logMessage)
28#include <ctime>
29#include <chrono>
[917]30#ifdef WIN32
[889]31#include <process.h>
[917]32#endif
[757]33
34#if defined(_MSC_VER) && _MSC_VER < 1800
[712]35#include <stdarg.h>
[645]36/**
[712]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 */
[967]41int snprintf(char *pcBuffer, size_t n, const char *pccFormat, ...)
[712]42{
43  va_list argp;
44  int ret;
[967]45  va_start(argp, pccFormat);
46  ret = _vscprintf(pccFormat, argp);
47  vsnprintf_s(pcBuffer, n, _TRUNCATE, pccFormat, argp);
[712]48  va_end(argp);
49  return ret;
50}
51#endif
52
53/**
[645]54 * Dump a map on stderr
55 *
[967]56 * @param pmMap the map to dump
[645]57 */
[967]58void _dumpMap(map* pmMap){
59  if(pmMap!=NULL){
60    fprintf(stderr,"%s: %s\n",pmMap->name,pmMap->value);
[645]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 *
[967]71 * @param pmMap the map to dump
[645]72 */
[967]73void dumpMap(map* pmMap){
74  map* pmTmp=pmMap;
75  while(pmTmp!=NULL){
76    _dumpMap(pmTmp);
77    pmTmp=pmTmp->next;
[645]78  }
79}
80
81/**
[790]82 * Dump a map to a file
[645]83 *
[967]84 * @param pmMap the map to dump to file
85 * @param pfFile the file pointer to store the map
[645]86 */
[967]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;
[645]92  }
93}
94
95/**
96 * Dump a maps on stderr, see dumpMap().
97 *
[967]98 * @param pmMap the map to dump
[645]99 */
[967]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);
[917]110    }
[967]111    pmTmp=pmTmp->next;
[645]112  }
113}
114
115/**
116 * Dump a maps to a file, see dumpMapToFile().
117 *
[967]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)
[645]121 */
[967]122void _dumpMapsToFile(maps* pmsMaps,FILE* psFile,int iLimit){
123  maps* tmp=pmsMaps;
[682]124  int cnt=0;
[652]125  while(tmp!=NULL){
[967]126    fprintf(psFile,"[%s]\n",tmp->name);
[790]127    if(tmp->child!=NULL){
[967]128      _dumpMapsToFile(tmp->child,psFile,iLimit);
[790]129    }else
[967]130      dumpMapToFile(tmp->content,psFile);
131    fflush(psFile);
[652]132    tmp=tmp->next;
[955]133    cnt++;
[967]134    if(iLimit>=0 && cnt==iLimit)
[682]135      tmp=NULL;
[645]136  }
[967]137  fflush(psFile);
[790]138}
139
140/**
141 * Dump a maps to a file, see _dumpMapsToFile().
142 *
[967]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)
[790]146 */
[967]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);
[652]152}
[680]153
[645]154/**
[917]155 * Create a new iotype*
156 *
157 * @return a pointer to the allocated iotype
158 */
159iotype* createIoType(){
[967]160  iotype* pioIO=(iotype*)malloc(IOTYPE_SIZE);
161  pioIO->content=NULL;
162  pioIO->next=NULL;
163  return pioIO;
[917]164}
165
166/**
[645]167 * Create a new map
168 *
[967]169 * @param pccName the key to add to the map
170 * @param pccValue the corresponding value to add to the map
[790]171 * @return a pointer to the allocated map
[645]172 */
[967]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;
[645]179}
180
181/**
[790]182 * Create a new maps with the given name
183 *
[967]184 * @param pccName of the maps
[790]185 * @return the allocated map
186 */
[967]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;
[790]194}
195
196/**
[645]197 * Count number of map in a map
198 *
[967]199 * @param pmMap the map to count
[645]200 * @return number of map in a map
201 */
[967]202int count(map* pmMap){
203  map* pmTmp=pmMap;
[645]204  int c=0;
[967]205  while(pmTmp!=NULL){
[645]206    c++;
[967]207    pmTmp=pmTmp->next;
[645]208  }
209  return c;
210}
211
212/**
[917]213 * Count number of maps in a maps
214 *
[967]215 * @param pmMap the maps to count
[917]216 * @return number of maps in a maps
217 */
[967]218int maps_length(maps* pmMap){
219  maps* pmTmp=pmMap;
[917]220  int c=0;
[967]221  while(pmTmp!=NULL){
[917]222    c++;
[967]223    pmTmp=pmTmp->next;
[917]224  }
225  return c;
226}
227
228/**
[645]229 * Verify if a key exist in a map
230 *
[967]231 * @param pmMap the map to search for the key
232 * @param pccKey the key to search in the map
[645]233 * @return true if the key wwas found, false in other case
234 */
[967]235bool hasKey(map* pmMap,const char *pccKey){
236  map* pmTmp=pmMap;
237  while(pmTmp!=NULL){
238    if(strcasecmp(pmTmp->name,pccKey)==0)
[645]239      return true;
[967]240    pmTmp=pmTmp->next;
[645]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 *
[967]251 * @param pmMap the maps to search for the key
252 * @param pccKey the key to search in the maps
[645]253 * @return a pointer on the maps found or NULL if not found
254 */
[967]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;
[645]260    }
[967]261    pmTmp=pmTmp->next;
[645]262  }
263  return NULL;
264}
265
266/**
267 * Access a specific map
268 *
[967]269 * @param pmMap the map to search for the key
270 * @param pccKey the key to search in the map
[645]271 * @return a pointer on the map found or NULL if not found
272 */
[967]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;
[645]278    }
[967]279    pmTmp=pmTmp->next;
[645]280  }
281  return NULL;
282}
283
284
285/**
286 * Access the last map
287 *
[967]288 * @param pmMap the map to search for the lastest map
[645]289 * @return a pointer on the lastest map found or NULL if not found
290 */
[967]291map* getLastMap(map* pmMap){
292  map* pmTmp=pmMap;
293  while(pmTmp!=NULL){
294    if(pmTmp->next==NULL){
295      return pmTmp;
[645]296    }
[967]297    pmTmp=pmTmp->next;
[645]298  }
299  return NULL;
300}
301
302/**
303 * Access a specific map from a maps
304 *
[967]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)
[645]308 * @return a pointer on the map found or NULL if not found
309 */
[967]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;
[645]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 *
[967]323 * @param pmMap the map to free
[645]324 */
[967]325void freeMap(map** pmMap){
326  map* pmCursor=*pmMap;
327  if(pmCursor!=NULL){
[645]328#ifdef DEBUG
329    fprintf(stderr,"freeMap\n");
330#endif
[967]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);
[645]339    }
340  }
341}
342
343/**
344 * Free allocated memory of a maps.
345 * Require to call free on mo after calling this function.
346 *
[967]347 * @param pmMap the maps to free
[645]348 */
[967]349void freeMaps(maps** pmMap){
350  maps* pmCursor=*pmMap;
351  if(pmCursor && pmCursor!=NULL){
[645]352#ifdef DEBUG
353    fprintf(stderr,"freeMaps\n");
354#endif
[967]355    free(pmCursor->name);
356    if(pmCursor->content!=NULL){
357      freeMap(&pmCursor->content);
358      free(pmCursor->content);
[645]359    }
[967]360    if(pmCursor->child!=NULL){
361      freeMaps(&pmCursor->child);
362      free(pmCursor->child);
[790]363    }
[967]364    if(pmCursor->next!=NULL){
365      freeMaps(&pmCursor->next);
366      free(pmCursor->next);
[645]367    }
368  }
369}
370
371/**
372 * Verify if an elements contains a name equal to the given key.
373 *
[967]374 * @param peElem the elements to search for the key
375 * @param pccKey the elements name to search
[645]376 * @return true if the elements contains the name, false in other cases.
377 */ 
[967]378bool hasElement(elements* peElem,const char* pccKey){
379  elements* peTmp=peElem;
380  while(peTmp!=NULL){
381    if(strcasecmp(pccKey,peTmp->name)==0)
[645]382      return true;
[967]383    peTmp=peTmp->next;
[645]384  }
385  return false;
386}
387
388/**
389 * Access a specific elements named key.
390 *
[967]391 * @param peElem the elements to search
392 * @param pccKey the elements name to search
[645]393 * @return a pointer to the specific element if found, NULL in other case.
394 */ 
[967]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;
[645]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 *
[967]409 * @param piotIO the iotype to free
[645]410 */
[967]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);
[645]417    }
[967]418    freeMap(&piotCursor->content);
419    free(piotCursor->content);
[645]420  }
421}
422
423/**
424 * Free allocated memory of an elements.
425 * Require to call free on e after calling this function.
426 *
[967]427 * @param peElem the iotype to free
[645]428 */
[967]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);
[790]448    }
[967]449    if(peTmp->defaults!=NULL){
450      freeIOType(&peTmp->defaults);
451      free(peTmp->defaults);
[917]452    }
[967]453    if(peTmp->supported!=NULL){
454      freeIOType(&peTmp->supported);
455      free(peTmp->supported);
[645]456    }
[967]457    if(peTmp->next!=NULL){
458      freeElements(&peTmp->next);
459      free(peTmp->next);
[917]460    }
[645]461  }
462}
463
[917]464
[645]465/**
[917]466 * Allocate memory for a service.
467 * Require to call free after calling this function.
468 *
469 * @return the service
470 */
471service* createService(){
[967]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;
[917]480}
481
482/**
[645]483 * Free allocated memory of a service.
[917]484 * Require to be invoked for every createService call.
[645]485 *
[967]486 * @param psService the service to free
[645]487 */
[967]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);
[645]508  }
509}
510
511/**
512 * Add key value pair to an existing map.
513 *
[967]514 * @param pMap the map to add the KVP
515 * @param pccName the key to add
516 * @param pccValue the corresponding value to add
[645]517 */
[967]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);
[645]526    }
[967]527    else {
528      map *tmp = getMap(pMap, pccName);
529      if (tmp->value != NULL)
530        free(tmp->value);
531      tmp->value = zStrdup(pccValue);
532    }
533  }
[645]534}
535
536/**
537 * Add a key and an integer value to an existing map.
538 *
[967]539 * @param pMap the map to add the KVP
540 * @param pccName the key to add
541 * @param iValue the corresponding value to add
[645]542 */
[967]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;
[645]550    }
[967]551    pmCursor->next=createMap(pccName,acValue);
[645]552  }
553  else{
[967]554    map *pmTmp=getMap(pMap,pccName);
555    if(pmTmp->value!=NULL)
556      free(pmTmp->value);
557    pmTmp->value=zStrdup(acValue);
[645]558  }
559}
560
561/**
562 * Add a key and a binary value to an existing map.
563 *
[967]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
[738]568 * @return a pointer to the updated map m
[645]569 */
[967]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;
[645]576    if(_cursor!=NULL){
[967]577      addToMap(pMap,pccName,"");
[645]578    }else{
[967]579      pMap=createMap(pccName,"");
[645]580    }
581  }
[967]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;
[645]594}
595
596/**
597 * Add a map at the end of another map.
598 *
[967]599 * @param pmMapOut the map to add pmMapIn to
600 * @param pmMapIn the map to add to pmMapOut
[645]601 */
[967]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;
[645]609    }
610    else{
[967]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);
[645]616      }
617      else{
[967]618        addToMap(*pmMapOut,pmTmp->name,pmTmp->value);
[645]619      }
620    }
[967]621    pmCursor=*pmMapOut;
622    pmTmp=pmTmp->next;
[645]623  }
624}
625
626/**
627 * Add a map to iotype.
628 *
[967]629 * @param piotType the iotype to add the map
630 * @param pmMap the map to add to io
[645]631 */
[967]632void addMapToIoType(iotype** piotType,map* pmMap){
633  iotype* piotTmp=*piotType;
634  while(piotTmp->next!=NULL){
635    piotTmp=piotTmp->next;
[645]636  }
[967]637  piotTmp->next=(iotype*)malloc(IOTYPE_SIZE);
638  piotTmp->next->content=NULL;
639  addMapToMap(&piotTmp->next->content,pmMap);
640  piotTmp->next->next=NULL;
[645]641}
642
643/**
644 * Access a specific map or set its value.
645 *
[967]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
[645]649 * @return a pointer on the map found or NULL if not found
650 */
[967]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);
[645]657    }
658    else
[967]659      (*ppmMap)=createMap(pccKey,pccValue);
660    pmTmp1=getMap(*ppmMap,pccKey);
[645]661  }
[967]662  return pmTmp1;
[645]663}
664
665/**
666 * Verify if a map is contained in another map.
667 *
[967]668 * @param pmMap the map to search for i
669 * @param pmSearch the map to search in m
[645]670 * @return true if i was found in m, false in other case
671 */
[967]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){
[645]678      map *tmp;
[967]679      if(hasKey(pmMap,pmSearch->name) &&
680         (tmp=getMap(pmMap,pmSearch->name))!=NULL && 
681         strcasecmp(pmSearch->value,tmp->value)!=0)
[645]682        return false;
683    }
[967]684    pmSearch=pmSearch->next;
[645]685  }
686  return true;
687}
688
689/**
690 * Access a specific iotype from an elements.
691 *
[967]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
[645]695 *  supported content of the elements e
696 * @return a pointer on the iotype found or NULL if not found
697 */
[967]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;
[790]705        else{
[967]706          iotype* tmp=peCursor->supported;
[790]707          while(tmp!=NULL){
[967]708            if(contains(tmp->content,pcValues)==true)
[790]709              return tmp;           
710            tmp=tmp->next;
711          }
[645]712        }
713      }
[967]714      peCursor=peCursor->next;
[645]715    }
[805]716  }else{
[967]717    while(peCursor!=NULL){
718      if(strcasecmp(peCursor->name,pcName)==0 && peCursor->defaults!=NULL){
719        return peCursor->defaults;
[805]720      }
[967]721      peCursor=peCursor->next;
[805]722    }
723  }
[645]724  return NULL;
725}
726
727/**
728 * Load binary values from a map (in) and add them to another map (out)
729 *
[967]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")
[645]733 */
[967]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){
[645]739    char tmp[11];
[967]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;
[645]749  }else{
[967]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;
[645]757    }
758  }
759}
[967]760
[645]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 *
[967]766 * @param ppmOut the map to add binaries values
767 * @param pmIn the map containing the binary values to add ti out
[645]768 */
[967]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){
[917]774#ifdef DEBUG
775    fprintf(stderr,"NO LOAD %s %d \n",__FILE__,__LINE__);
776#endif
777    return ;
778  }
[967]779  if(pmLength!=NULL){
780    int len=atoi(pmLength->value);
[645]781    int i=0;
782    for(i=0;i<len;i++){
[967]783      loadMapBinary(ppmOut,pmIn,i);
[645]784    }
785  }
786  else
[967]787    if(pmSize!=NULL)
788      loadMapBinary(ppmOut,pmIn,-1);
[645]789}
790
791/**
792 * Duplicate a Maps
793 *
[967]794 * @param ppmsOut the maps to clone
[645]795 * @return the allocated maps containing a copy of the mo maps
796 */
[967]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);
[645]807    }
[967]808    if(pmsChild!=NULL){
809      pmRes->child=dupMaps(&pmsChild);
[790]810    }
[967]811    pmRes->next=dupMaps(&pmsCursor->next);
[645]812  }
[967]813  return pmRes;
[645]814}
815
816/**
817 * Add a maps at the end of another maps.
818 *
819 * @see addMapToMap, dupMaps, getMaps
[967]820 * @param ppmsOut the maps to add mi
821 * @param pmIn the maps to add to mo
[645]822 */
[967]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);
[645]829    }
830    else{
[967]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);
[790]838        else
[967]839          pmsCursor->next->child=NULL;
[790]840      }
841      else{
[967]842        addMapToMap(&pmsTmp1->content,pmsTmp->content);
843        if(pmsTmp->child!=NULL)
844          pmsTmp1->child=dupMaps(&pmsTmp->child);
[790]845        else
[967]846          pmsTmp1->child=NULL;
[790]847      }
[967]848      pmsCursor=*ppmsOut;
[645]849    }
[967]850    pmsTmp=pmsTmp->next;
[645]851  }
852}
853
854/**
855 * Access a specific map array element
856 *
[967]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
[645]860 * @return a pointer on the map found or NULL if not found
861 */
[967]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);
[645]867  else
[967]868    sprintf(acTmp,"%s",pccKey);
[645]869#ifdef DEBUG
[967]870  fprintf(stderr,"** KEY %s\n",acTmp);
[645]871#endif
[967]872  pmTmp=getMap(pmMap,acTmp);
[645]873#ifdef DEBUG
[967]874  if(pmTmp!=NULL)
875    dumpMap(pmTmp);
[645]876#endif
[967]877  return pmTmp;
[645]878}
879
880/**
881 * Add a key value in a MapArray for a specific index
882 *
[967]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
[645]887 * @return a pointer on the map found or NULL if not found
888 */
[967]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);
[645]899    }
900  }
[917]901  else{
[967]902    sprintf(acTmp,"%s",pccKey);
903    addToMap(pmMap,"length","1");
[917]904  }
[967]905  pmSize=getMapArray(pmMap,"size",iIndex);
906  if(pmSize!=NULL && strncasecmp(pccKey,"value",5)==0){
907    map* pmPtr=getMapOrFill(&pmMap,acTmp,(char *)"");
[645]908#ifdef DEBUG
[967]909    fprintf(stderr,"%s\n",pmSize->value);
[645]910#endif
[967]911    free(pmPtr->value);
912    pmPtr->value=(char*)malloc((atoi(pmSize->value)+1)*sizeof(char));
913    memcpy(pmPtr->value,pccValue,atoi(pmSize->value)); 
[645]914  }
915  else
[967]916    addToMap(pmMap,acTmp,pccValue);
[645]917}
918
919/**
[917]920 * Add a key and an integer value to an existing map array.
921 *
[967]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
[917]926 */
[967]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);
[917]931}
932
933/**
[645]934 * Access the map "type"
935 *
[967]936 * @param pmMap the map
[645]937 * @return a pointer on the map for mimeType/dataType/CRS if found, NULL in
938 *  other case
939 */
[967]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");
[645]946    }
947  }
948#ifdef DEBUG
[967]949  dumpMap(pmMime);
[645]950#endif
[967]951  return pmMime;
[645]952}
953
954/**
955 * Add a Maps containing a MapArray to a Maps
956 *
957 * @see getMapType
[967]958 * @param pmsOut the maps
959 * @param pmsIn the maps
960 * @param pcType the map "type"
[645]961 * @return
962 */
[967]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]={
[645]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",
[967]977    pcType,
[645]978    (char*)"schema",
979    (char*)"encoding",
[868]980    (char*)"isCached",
981    (char*)"LowerCorner",
[917]982    (char*)"UpperCorner"
[645]983  };
[967]984  int iCounter=0;
985  map* pmLength;
[917]986 
[967]987  if(pmsCursor==NULL)
[917]988    return -1;
989
[967]990  pmLength=getMap(pmsCursor->content,"length");
991  if(pmLength!=NULL){
992    iLen=atoi(pmLength->value);
[917]993  }
994
[967]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){
[645]1000#ifdef DEBUG
[967]1001      fprintf(stderr,"%s = %s\n",pmTmp[iCounter],pmTmp->value);
[645]1002#endif
[967]1003      setMapArray(pmsCursor->content,acV[iCounter],iLen,pmTmp->value);
[645]1004    }
1005  }
1006   
[967]1007  addToMap(pmsCursor->content,"isArray","true");
[645]1008  return 0;
1009}
1010
1011/**
1012 * Set a key value pair to a map contained in a Maps
1013 *
[967]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
[645]1018 */
[967]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);
[645]1027    }else{
[967]1028      maps *pmsToAdd=createMaps(pccKey);
1029      pmsToAdd->content=createMap(pccSubkey,pccValue);
1030      addMapsToMaps(&pmsTmp,pmsToAdd);
1031      freeMaps(&pmsToAdd);
1032      free(pmsToAdd);
[645]1033    }
1034  }else{
[967]1035    maps *pmsToAdd=createMaps(pccKey);
1036    pmsToAdd->content=createMap(pccSubkey,pccValue);
1037    addMapsToMaps(&pmsMaps,pmsToAdd);
1038    freeMaps(&pmsToAdd);
1039    free(pmsToAdd);
[645]1040  }
1041}
1042
1043/**
[790]1044 * Create an empty elements
1045 *
1046 * @return a pointer to the allocated elements
1047 */
1048elements* createEmptyElements(){
[967]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;
[790]1060}
1061
1062/**
1063 * Create a named elements
1064 *
[967]1065 * @param pcName the elements name
[790]1066 * @return a pointer to the allocated elements
1067 */
[967]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;
[790]1080}
1081
1082/**
1083 * Set the name of an elements
1084 *
[967]1085 * @param peElem the elements to modify
1086 * @param pcName the elements name
[790]1087 * @return a pointer to the allocated elements
1088 */
[967]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;
[790]1099}
1100
1101/**
[645]1102 * Dump an elements on stderr
1103 *
[967]1104 * @param peElem the elements to dump
[645]1105 */
[967]1106void dumpElements(elements* peElem){
1107  elements* peTmp=peElem;
1108  while(peTmp!=NULL){
1109    iotype* piotTmp=peTmp->defaults;
[917]1110    int ioc=0;
[967]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;
[645]1123      ioc++;
1124    }
[967]1125    piotTmp=peTmp->supported;
[645]1126    ioc=0;
[967]1127    while(piotTmp!=NULL){
1128      fprintf(stderr," > SUPPORTED [%s] (%i)\n",peTmp->name,ioc);
1129      dumpMap(piotTmp->content);
1130      piotTmp=piotTmp->next;
[645]1131      ioc++;
1132    }
[967]1133    if(peTmp->child!=NULL){
[790]1134      fprintf(stderr," > CHILD \n");
[967]1135      dumpElements(peTmp->child);
[790]1136    }
[645]1137    fprintf(stderr,"------------------\n");
[967]1138    peTmp=peTmp->next;
[645]1139  }
1140}
1141
1142/**
1143 * Dump an elements on stderr using the YAML syntaxe
1144 *
[967]1145 * @param peElem the elements to dump
1146 * @param iLevel the current level
[645]1147 */
[967]1148void dumpElementsAsYAML(elements* peElem,int iLevel){
1149  elements* peTmp=peElem;
[645]1150  int i;
[967]1151  while(peTmp!=NULL){
1152    map* pmCurs=peTmp->content;
[917]1153    int ioc=0;
[967]1154    iotype* piotTmp;
1155    for(i=0;i<2+(4*iLevel);i++)
[645]1156      fprintf(stderr," ");
[967]1157    fprintf(stderr,"%s:\n",peTmp->name);
1158    while(pmCurs!=NULL){
1159      for(i=0;i<4+(4*iLevel);i++)
[645]1160        fprintf(stderr," ");
[967]1161      _dumpMap(pmCurs);
1162      pmCurs=pmCurs->next;
[645]1163    }
[967]1164    pmCurs=peTmp->metadata;
1165    if(pmCurs!=NULL){
1166      for(i=0;i<4+(4*iLevel);i++)
[645]1167        fprintf(stderr," ");
1168      fprintf(stderr,"MetaData:\n");
[967]1169      while(pmCurs!=NULL){
1170        for(i=0;i<6+(4*iLevel);i++)
[645]1171          fprintf(stderr," ");
[967]1172        _dumpMap(pmCurs);
1173        pmCurs=pmCurs->next;
[645]1174      }
1175    }
[967]1176    for(i=0;i<4+(4*iLevel);i++)
[645]1177      fprintf(stderr," ");
[967]1178    if(peTmp->format!=NULL)
1179      fprintf(stderr,"%s:\n",peTmp->format);
[790]1180    else{
1181      fprintf(stderr,"Child:\n");
[967]1182      if(peTmp->child!=NULL)
1183        dumpElementsAsYAML(peTmp->child,iLevel+1);
[790]1184    }
[967]1185    piotTmp=peTmp->defaults;
1186    while(piotTmp!=NULL){
1187      for(i=0;i<6+(4*iLevel);i++)
[645]1188        fprintf(stderr," ");
1189      fprintf(stderr,"default:\n");
[967]1190      pmCurs=piotTmp->content;
1191      while(pmCurs!=NULL){
1192        for(i=0;i<8+(4*iLevel);i++)
[645]1193          fprintf(stderr," ");
[967]1194        if(strcasecmp(pmCurs->name,"range")==0){
1195          fprintf(stderr,"range: \"%s\"\n",pmCurs->value);
[645]1196        }else
[967]1197          _dumpMap(pmCurs);
1198        pmCurs=pmCurs->next;
[645]1199      }
[967]1200      piotTmp=piotTmp->next;
[645]1201      ioc++;
1202    }
[967]1203    piotTmp=peTmp->supported;
[645]1204    ioc=0;
[967]1205    while(piotTmp!=NULL){
1206      for(i=0;i<6+(4*iLevel);i++)
[645]1207        fprintf(stderr," ");
1208      fprintf(stderr,"supported:\n");
[967]1209      pmCurs=piotTmp->content;
1210      while(pmCurs!=NULL){
1211        for(i=0;i<8+(4*iLevel);i++)
[645]1212          fprintf(stderr," ");
[967]1213        if(strcasecmp(pmCurs->name,"range")==0){
1214          fprintf(stderr,"range: \"%s\"\n",pmCurs->value);
[645]1215        }else
[967]1216          _dumpMap(pmCurs);
1217        pmCurs=pmCurs->next;
[645]1218      }
[967]1219      piotTmp=piotTmp->next;
[645]1220      ioc++;
1221    }
[967]1222    peTmp=peTmp->next;
[645]1223  }
1224}
1225
1226/**
1227 * Duplicate an elements
1228 *
[967]1229 * @param peElem the elements to clone
[645]1230 * @return the allocated elements containing a copy of the elements e
1231 */
[967]1232elements* dupElements(elements* peElem){
1233  elements* peCursor=peElem;
1234  elements* peTmp=NULL;
1235  if(peCursor!=NULL && peCursor->name!=NULL){
[645]1236#ifdef DEBUG
1237    fprintf(stderr,">> %s %i\n",__FILE__,__LINE__);
1238    dumpElements(e);
1239    fprintf(stderr,">> %s %i\n",__FILE__,__LINE__);
1240#endif
[967]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);
[645]1251    else
[967]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;
[645]1258#ifdef DEBUG
1259      fprintf(stderr,">> %s %i\n",__FILE__,__LINE__);
[967]1260      dumpMap(peTmp->defaults->content);
[645]1261#endif
1262    }else
[967]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);
[645]1272#ifdef DEBUG
1273        fprintf(stderr,">> %s %i\n",__FILE__,__LINE__);
[967]1274        dumpMap(peTmp->defaults->content);
[645]1275#endif
[967]1276        piotTmp=piotTmp->next;
[645]1277      }
1278    }
1279    else
[967]1280      peTmp->supported=NULL;
1281    if(peCursor->child!=NULL)
1282      peTmp->child=dupElements(peCursor->child);
[790]1283    else
[967]1284      peTmp->child=NULL;
1285    if(peCursor->next!=NULL)
1286      peTmp->next=dupElements(peCursor->next);
[917]1287    else
[967]1288      peTmp->next=NULL;
[645]1289  }
[967]1290  return peTmp;
[645]1291}
1292
1293/**
1294 * Add an elements to another elements.
1295 *
1296 * @see dupElements
[967]1297 * @param ppeElem the elements to add the e
1298 * @param peELem the elements to be added to m
[645]1299 */
[967]1300void addToElements(elements** ppeElem,elements* peELem){
1301  elements* peTmp=peELem;
1302  if(*ppeElem==NULL){
1303    (*ppeElem)=dupElements(peTmp);
[645]1304  }else{
[967]1305    addToElements(&(*ppeElem)->next,peTmp);
[645]1306  }
1307}
[790]1308
[645]1309/**
[790]1310 * Set the name of a service
1311 *
[967]1312 * @param ppsServ the service
1313 * @param pcName the service name
[790]1314 */
[967]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;
[790]1322}
1323
1324/**
[645]1325 * Dump a service on stderr
1326 *
[967]1327 * @param psServ the service to dump
[645]1328 */
[967]1329void dumpService(service* psServ){
1330  if(psServ==NULL)
[645]1331    return;
[967]1332  fprintf(stderr,"++++++++++++++++++\nSERVICE [%s]\n++++++++++++++++++\n",psServ->name);
1333  if(psServ->content!=NULL){
[645]1334    fprintf(stderr,"CONTENT MAP\n");
[967]1335    dumpMap(psServ->content);
1336    if(psServ->metadata!=NULL)
[917]1337      fprintf(stderr,"CONTENT METADATA\n");
[967]1338    dumpMap(psServ->metadata);
1339    if(psServ->additional_parameters!=NULL)
[917]1340      fprintf(stderr,"CONTENT AdditionalParameters\n");
[967]1341    dumpMap(psServ->additional_parameters);
[645]1342  }
[967]1343  if(psServ->inputs!=NULL){
1344    fprintf(stderr,"INPUT ELEMENTS [%s]\n------------------\n",psServ->name);
1345    dumpElements(psServ->inputs);
[645]1346  }
[967]1347  if(psServ->outputs!=NULL){
1348    fprintf(stderr,"OUTPUT ELEMENTS [%s]\n------------------\n",psServ->name);
1349    dumpElements(psServ->outputs);
[645]1350  }
1351  fprintf(stderr,"++++++++++++++++++\n");
1352}
1353
1354/**
1355 * Dump a service on stderr using the YAML syntaxe
1356 *
[967]1357 * @param psServ the service to dump
[645]1358 */
[967]1359void dumpServiceAsYAML(service* psServ){
[645]1360  int i;
[967]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){
[645]1367      fprintf(stderr,"MetaData:\n");
[967]1368      while(pmCurs!=NULL){
[645]1369        for(i=0;i<2;i++)
1370          fprintf(stderr," ");
[967]1371        _dumpMap(pmCurs);
1372        pmCurs=pmCurs->next;
[645]1373      }
1374    }
1375  }
[967]1376  if(psServ->inputs!=NULL){
[645]1377    fprintf(stderr,"\ninputs:\n");
[967]1378    dumpElementsAsYAML(psServ->inputs,0);
[645]1379  }
[967]1380  if(psServ->outputs!=NULL){
[645]1381    fprintf(stderr,"\noutputs:\n");
[967]1382    dumpElementsAsYAML(psServ->outputs,0);
[645]1383  }
1384}
1385
1386/**
1387 * Duplicate a service
1388 *
[967]1389 * @param psServ the service to clone
[645]1390 * @return the allocated service containing a copy of the serfvice s
1391 */
[967]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;
[645]1404}
1405
1406/**
1407 * Print the registry on stderr.
1408 *
[967]1409 * @param prReg the registry
[645]1410 */
[967]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;
[645]1420    }
[967]1421    prCurs=prCurs->next;
[645]1422  }
1423}
1424
1425/**
1426 * Add a service to the registry
1427 *
[967]1428 * @param prReg the resgitry to add the service
1429 * @param pcName the registry name to update
1430 * @param psContent the service to add
[645]1431 */
[967]1432bool addServiceToRegistry(registry** prReg,char* pcName,service* psContent){
1433  registry *l=*prReg;
[645]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){
[967]1442      if(l->name!=NULL && strcasecmp(pcName,l->name)==0){
[645]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);
[967]1451      l->name=zStrdup(pcName);
[645]1452      l->content=NULL;
1453      l->next=NULL;
1454    }
1455    if(l->content==NULL){
1456      l->content=(services*)malloc(SERVICES_SIZE);
[967]1457      l->content->content=dupService(psContent);
[645]1458      l->content->next=NULL;
1459    }
1460    else{
[967]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;
[645]1467    }
1468    l->next=NULL;
1469    if(isInitial>0)
[967]1470      *prReg=l;
[645]1471    else{
[967]1472      registry *prCurs=*prReg;
1473      while(prCurs->next!=NULL)
1474        prCurs=prCurs->next;
1475      prCurs->next=l;
1476      prCurs->next->next=NULL;
[645]1477    }
1478    return true;
1479  }
1480  else
1481    return false;
1482}
1483
1484/**
1485 * Free memory allocated for the registry
1486 *
[967]1487 * @param prReg the registry
[645]1488 */
[967]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;
[645]1501      }
1502    }
[967]1503    prLocalRef=prLocalRef->next;
[645]1504  }   
1505}
1506
1507/**
1508 * Access a service in the registry
1509 *
[967]1510 * @param prReg the registry
1511 * @param pcLevel the regitry to search ("concept", "generic" or "implementation")
1512 * @param pcName the service name
[645]1513 * @return the service pointer if a corresponding service was found or NULL
1514 */
[967]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;
[645]1524      }
1525      break;
1526    }
[967]1527    prLocalRef=prLocalRef->next;
[645]1528  }
1529  return NULL;
1530}
1531
1532/**
1533 * Apply inheritance to an out map from a reference in map
1534 *
[967]1535 * @param ppmOut the map to update
1536 * @param pmIn the reference map (containing inherited properties)
[645]1537 */
[967]1538void inheritMap(map** ppmOut,map* pmIn){
1539  map* pmContent=pmIn;
1540  if((*ppmOut)==NULL){
1541    addMapToMap(ppmOut,pmIn);
[676]1542    return;
1543  }
[967]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;
[645]1549  }
1550}
1551
1552/**
1553 * Apply inheritance to an out iotype from a reference in iotype
1554 *
[967]1555 * @param ppiotOut the iotype to update
1556 * @param piotIn the reference iotype (containing inherited properties)
[645]1557 */
[967]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);
[645]1569    }else{
[967]1570      inheritIOType(&ppiotOutCursor->next,piotInCurosor->next);
[645]1571    }
1572  }
1573}
1574
1575/**
1576 * Apply inheritance to an out elements from a reference in elements
1577 *
[967]1578 * @param ppeOut the elements to update
1579 * @param peIn the reference elements (containing inherited properties)
[645]1580 */
[967]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);
[645]1587    else{
[967]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);
[645]1595      else{
[967]1596        iotype* piotTmp=peContent->supported;
1597        while(piotTmp!=NULL){
1598          addMapToIoType(&peCurrent->supported,piotTmp->content);
1599          piotTmp=piotTmp->next;
[645]1600        }
1601      }
1602    }
[967]1603    peContent=peContent->next;
[645]1604  }
1605}
1606
1607/**
1608 * Apply inheritance to a service based on a registry
1609 *
[967]1610 * @param prReg the registry storing profiles hierarchy
1611 * @param psServ the service to update depending on its inheritance
[645]1612 */
[967]1613void inheritance(registry *prReg,service** psServ){
1614  service* psCursor=*psServ;
[917]1615  map *profile,*level;
[967]1616  if(prReg==NULL)
[645]1617    return;
[967]1618  if(psCursor==NULL || psCursor->content==NULL)
[645]1619    return;
[967]1620  profile=getMap(psCursor->content,"extend");
1621  level=getMap(psCursor->content,"level");
[645]1622  if(profile!=NULL&&level!=NULL){
1623    service* s1;
1624    if(strncasecmp(level->value,"profile",7)==0)
[967]1625      s1=getServiceFromRegistry(prReg,(char*)"generic",profile->value);
[645]1626    else
[967]1627      s1=getServiceFromRegistry(prReg,level->value,profile->value);
[645]1628     
[967]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);
[645]1633    }else{
[967]1634      inheritElements(&psCursor->inputs,s1->inputs);
[645]1635    }
[967]1636    if(psCursor->outputs==NULL && s1->outputs!=NULL){
1637      psCursor->outputs=dupElements(s1->outputs);
[645]1638    }else
[967]1639      inheritElements(&psCursor->outputs,s1->outputs);
[645]1640  }
1641}
1642
1643/**
1644 * Convert a maps to a char*** (only used for Fortran support)
1645 *
[967]1646 * @param pmsMap the maps to convert
1647 * @param pppcValues the resulting array
[645]1648 */
[967]1649void mapsToCharXXX(maps* pmsMap,char*** pppcValues){
1650  maps* pmsCursor=pmsMap;
[645]1651  int i=0;
1652  int j=0;
[967]1653  char aaacTmp[10][30][1024];
1654  memset(aaacTmp,0,1024*10*10);
1655  while(pmsCursor!=NULL){
1656    map* pmContent=pmsCursor->content;
[645]1657    if(i>=10)
1658      break;
[967]1659    strcpy(aaacTmp[i][j],"name");
[645]1660    j++;
[967]1661    strcpy(aaacTmp[i][j],pmsCursor->name);
[645]1662    j++;
[967]1663    while(pmContent!=NULL){
[645]1664      if(j>=30)
1665        break;
[967]1666      strcpy(aaacTmp[i][j],pmContent->name);
[645]1667      j++;
[967]1668      strcpy(aaacTmp[i][j],pmContent->value);
[645]1669      j++;
[967]1670      pmContent=pmContent->next;
[645]1671    }
[967]1672    pmsCursor=pmsCursor->next;
[645]1673    j=0;
1674    i++;
1675  }
[967]1676  memcpy(pppcValues,aaacTmp,10*10*1024);
[645]1677}
1678
1679/**
1680 * Convert a char*** to a maps (only used for Fortran support)
1681 *
[967]1682 * @param pppcValues the array to convert
1683 * @param ppmsMaps the resulting maps
[645]1684 */
[967]1685void charxxxToMaps(char*** pppcValues,maps** ppmsMaps){
1686  maps* pmsCursor=*ppmsMaps;
[645]1687  int i,j;
[967]1688  char aaaTmp[10][30][1024];
1689  memcpy(aaaTmp,pppcValues,10*30*1024);
[645]1690  for(i=0;i<10;i++){
[967]1691    if(strlen(aaaTmp[i][1])==0)
[645]1692      break;
[967]1693    pmsCursor->name=aaaTmp[i][1];
1694    pmsCursor->content=NULL;
1695    pmsCursor->next=NULL;
[645]1696    for(j=2;j<29;j+=2){
[967]1697      if(strlen(aaaTmp[i][j+1])==0)
[645]1698        break;
[967]1699      if(pmsCursor->content==NULL)
1700        pmsCursor->content=createMap(aaaTmp[i][j],aaaTmp[i][j+1]);
[645]1701      else
[967]1702        addToMap(pmsCursor->content,aaaTmp[i][j],aaaTmp[i][j+1]);
[645]1703    }
[967]1704    pmsCursor=pmsCursor->next;
[645]1705  }
[967]1706  ppmsMaps=&pmsCursor;
[645]1707}
[843]1708
[889]1709/**
1710 * Verify that a map has a value
1711 *
[967]1712 * @param pmMap pointer to map that should be checked
[889]1713 * @return true if map has a value or false if value is missing/empty/NULL
1714 */
[967]1715bool nonempty(map* pmMap) {
1716  return (pmMap != NULL && pmMap->value != NULL && strlen(pmMap->value) > 0 && strcmp(pmMap->value, "NULL") != 0);
[889]1717}
1718
1719/**
[917]1720 * Verify that a particular map value exists in a maps
[889]1721 * data structure, and obtain that value
1722 *
[967]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
[889]1727 * @return true if map has a value or false if value is missing/NULL
[917]1728 *
1729 * @note The map assigned to kvp is owned by the source maps
[889]1730 */
[967]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);
[889]1735}
1736
1737/*
1738 * Set error message in configuration maps
1739 *
[967]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)
[889]1744 */
[967]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  }
[889]1756}
1757
[967]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) {
[917]1768
[967]1769  size_t msglen = 512;
1770  const char empty[] = "";
[917]1771
[967]1772  FILE* pfLog;
[917]1773
[967]1774  // system time, process time [nanoseconds]   
1775  unsigned long long sys_t, proc_t;
[917]1776
[967]1777  // processor time consumed by the program:
1778  clock_t t = clock();
[917]1779
[967]1780  // system time:
1781  std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
[917]1782
[967]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
[917]1787
[967]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;
[917]1791
[967]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);
[917]1800
[967]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__ //
[917]1803
[967]1804  if (pccFile != NULL && (pfLog = fopen(pccFile, "a+")) != NULL) {
1805    fputs(pcText, pfLog);
1806    fclose(pfLog);
1807  }
1808  else {
[917]1809#ifdef MSG_LOG_FILE
[967]1810    if ((pfLog = fopen(MSG_LOG_FILE, "a+")) != NULL) {
1811      fputs(pcText, pfLog);
1812      fclose(pfLog);
1813    }
[917]1814#endif
[967]1815  }
[917]1816
[967]1817  if (pcText != NULL) free(pcText);
[889]1818}
1819
1820// knut:
1821// Example:
1822// zooLog;
1823// zooLogMsg(NULL, getLastErrorMessage());
[917]1824// zooLogMsg("log.txt", getLastErrorMessage());
[943]1825
1826#ifdef WIN32
1827#ifndef USE_MS
[967]1828char *strcasestr (char const *pccA, char const *pccB)
[943]1829  {
[967]1830    char *pcX = zStrdup (pccA);
1831    char *pcY = zStrdup (pccB);
[943]1832 
[967]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);
[943]1839      return ret;
1840  };
1841#else
1842   ;
1843#endif
1844#endif
[957]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 */
[967]1856char* allocateMapValue(map* pmNode, size_t sNumBytes)
[957]1857{
[967]1858  if (pmNode == NULL) {
1859    return NULL;
1860  }
[957]1861
[967]1862  if (pmNode->value != NULL) {
1863    free(pmNode->value);
1864  }
1865  pmNode->value = (char*) malloc(sNumBytes);
[957]1866               
[967]1867  return pmNode->value;
[957]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