NMD
|
00001 /*! \mainpage NMD: the Numerical MetaData library 00002 00003 The NMD library serves to store two-level data structures of 00004 numerical metadata. While this library was intended to be used with 00005 AnaMod in the Salsa project, it can be used on its own. Unlike other 00006 libraries in the Salsa project, it does not rely on Petsc. 00007 00008 \section general General notes 00009 00010 All routines in NMD return an error code of type \c NMDErrorCode. This 00011 is zero for success and anything else for failure. Return codes can be 00012 caught with \c NMD_ERR_RETURN(ierr) and generate with 00013 \c NMD_ERR_REPORT(msg). 00014 00015 \subpage objectfunctions 00016 00017 \subpage categoryfunctions 00018 00019 \subpage componentfunctions 00020 00021 \subpage values 00022 00023 \subpage viewing 00024 00025 \subpage installation 00026 00027 \author Victor Eijkhout 00028 \version 2.5 00029 \date unreleased 00030 00031 \section Change history 00032 2.5 changes 00033 - added routines: NMDUnsetValue(),NMDCategoryGetComponents(), 00034 NMDTypeGetMySQLName() 00035 - NMDReportObject() now takes delimiter arguments. This is useful 00036 for generating MySQL strings and such. 00037 00038 2.4 changes 00039 - minor 00040 00041 2.3 changes 00042 00043 - NMDGetValue now returns failure (instead of aborting) 00044 if cat/cmp do not exist 00045 - removed occurrences of Petsc's CHKERRQ 00046 - introduced NMDErrorCode 00047 - new files nmdcat.c nmdcmp.c 00048 - NMDGetValue and GetArrayValue now use NMDTruth 00049 - NMDSetValue and NMDSetArrayValue are now analogous: use ampersand 00050 for all types of data 00051 - NMDTrue and NMDFalse instead of 1 and 0 00052 - unit tests added 00053 00054 2.3 bug fixes 00055 00056 - NMDGetValue missing case of string value added 00057 - NMDTryGetCategory (and various other Get routines) were able to 00058 find non-existing category names. Fixed. 00059 - lots of memory leaks plugged 00060 00061 2.2 00062 - Completely revamped array handling; watch out for prototype changes 00063 - CFLAGS is now NMD_CFLAGS 00064 */ 00065 00066 /*! \page installation Installing NMD 00067 00068 Installing NMD takes the following steps: 00069 - edit the Make.inc file for: 00070 - compiler options, and settings for your \c ar and \c ranlib program 00071 - add \c "-DNMD_HAVE_PETSC" to the compile line if you are using NMD 00072 with Petsc (see NMDReportObject()) 00073 - \c NMD_LIB_DIR is the location where the library will be installed 00074 - do \c "make install" to generate the binaries 00075 00076 */ 00077 00078 #include <stdlib.h> 00079 #include <stdio.h> 00080 #include <string.h> 00081 #include "nmd_impl.h" 00082 #include "nmd.h" 00083 00084 const char *typenames[] = 00085 {"invalid","int","real","string","intarray","realarray"}; 00086 const char *mysqltypenames[] = 00087 {"VARCHAR(256)","INTEGER","DOUBLE","VARCHAR(1024)", 00088 "VARCHAR(1024)","VARCHAR(1024)"}; 00089 static const int nnmdtypenames = 6; 00090 00091 #define CATCHUNK 10 00092 00093 /*! \page objectfunctions Metadata object manipulation 00094 00095 Top level functions for manipulation metadata objects. 00096 00097 See NMDCreateObject(), NMDDestroyObject(), NMDBuildObjectStructure(), 00098 NMDCloneObject(), NMDCloneObjectStructure(), NMDViewObject() 00099 */ 00100 00101 #undef __FUNCT__ 00102 #define __FUNCT__ "NMDCreateObject" 00103 /*! 00104 This routine create an NMD_metadata object, and allocates enough 00105 space in it for 10 categories of 20 elements each. Currently this can not 00106 be reallocated. In the future we want to be a bit more flexible. 00107 */ 00108 NMDErrorCode NMDCreateObject(NMD_metadata *obj) 00109 { 00110 NMD_metadata nnew; 00111 00112 /* allocate the metadata object */ 00113 NMD_MALLOC(nnew,1,struct NMD_metadata_,"object"); 00114 nnew->cookie = NMDCOOKIE; 00115 *obj = nnew; 00116 00117 /* give it a basic array of categories */ 00118 nnew->alloc = CATCHUNK; nnew->ncat = 0; 00119 NMD_MALLOC(nnew->cats,nnew->alloc,NMD_metadata_category,"categories"); 00120 00121 CHKMEMQ 00122 return 0; 00123 } 00124 00125 #undef __FUNCT__ 00126 #define __FUNCT__ "NMDDestroyObject" 00127 /*! 00128 Deallocate all the data in a metadata object. 00129 */ 00130 NMDErrorCode NMDDestroyObject(NMD_metadata obj) 00131 { 00132 int i,j; NMDErrorCode ierr; 00133 00134 CHECKHASNMDCOOKIE(obj); 00135 for (i=0; i<obj->ncat; i++) { 00136 NMD_metadata_category cat = obj->cats[i]; 00137 for (j=0; j<cat->ncmp; j++) { 00138 NMD_metadata_item cmp = cat->cmps[j]; 00139 ierr = NMDComponentDestroy(cmp); NMD_ERR_RETURN(ierr); 00140 } 00141 NMD_FREE(cat->cmps); 00142 NMD_FREE(cat->name); 00143 NMD_FREE(cat); 00144 CHKMEMQ 00145 } 00146 NMD_FREE(obj->cats); 00147 NMD_FREE(obj); 00148 00149 return 0; 00150 } 00151 00152 #if 0 00153 #undef __FUNCT__ 00154 #define __FUNCT__ "NMDBuildObjectStructure" 00155 NMDErrorCode NMDBuildObjectStructure(NMD_metadata nmd) 00156 { 00157 char **categories; int ncat,icat; NMDErrorCode ierr; 00158 00159 ierr = NMDGetCategories(nmd,&ncat,&categories); NMD_ERR_RETURN(ierr); 00160 for (icat=0; icat<ncat; icat++) { 00161 NMDDataType *t; char **modules; int nmod,imod; 00162 ierr = NMDObjectGetOrCreateCategory(nmd,categories[icat]); NMD_ERR_RETURN(ierr); 00163 ierr = CategoryGetModules 00164 (categories[icat],&modules,&t,PETSC_NULL,&nmod); NMD_ERR_RETURN(ierr); 00165 for (imod=0; imod<nmod; imod++) { 00166 ierr = NMDCreateComponent 00167 (nmd,categories[icat],modules[imod],t[imod]); NMD_ERR_RETURN(ierr); 00168 } 00169 } 00170 return 0; 00171 } 00172 #endif 00173 00174 #undef __FUNCT__ 00175 #define __FUNCT__ "NMDCloneObjectStructure" 00176 /*! 00177 This routine creates an NMD_metadata object, and fills it in with 00178 the categories and components of a template object. Data is not copied; 00179 for that, see NMDCloneObject() and NMDCopyCategory(). 00180 */ 00181 NMDErrorCode NMDCloneObjectStructure(NMD_metadata old,NMD_metadata *ret) 00182 { 00183 NMD_metadata nnew; 00184 int icat,icmp; NMDErrorCode ierr; 00185 00186 CHECKHASNMDCOOKIE(old); 00187 ierr = NMDCreateObject(&nnew); NMD_ERR_RETURN(ierr); 00188 CHECKHASNMDCOOKIE(nnew); 00189 for (icat=0; icat<old->ncat; icat++) { 00190 NMD_metadata_category oldcat = old->cats[icat]; 00191 CHECKHASNMDCOOKIE(oldcat); 00192 for (icmp=0; icmp<oldcat->ncmp; icmp++) { 00193 NMD_metadata_item oldcmp = oldcat->cmps[icmp]; 00194 CHECKHASNMDCOOKIE(oldcmp); 00195 ierr = NMDObjectEnsureCategoryComponent 00196 (nnew,oldcat->name,oldcmp->name,oldcmp->t,NULL); NMD_ERR_RETURN(ierr); 00197 } 00198 } 00199 CHKMEMQ 00200 *ret = nnew; 00201 return 0; 00202 } 00203 00204 #undef __FUNCT__ 00205 #define __FUNCT__ "NMDCloneObject" 00206 /*! 00207 Given an already created NMD_metadata object, fill it with 00208 the data of a template object. See also NMDCloneObjectStructure(). 00209 */ 00210 NMDErrorCode NMDCloneObject(NMD_metadata old,NMD_metadata nnew) 00211 { 00212 int icat; NMDErrorCode ierr; 00213 00214 CHECKHASNMDCOOKIE(old); 00215 CHECKHASNMDCOOKIE(nnew); 00216 for (icat=0; icat<old->ncat; icat++) { 00217 /* loop over input categories by index; output categories 00218 are retrieved by label, or newly created */ 00219 NMD_metadata_category oldcat = old->cats[icat],newcat; int icmp; 00220 ierr = NMDObjectGetOrCreateCategory 00221 (nnew,oldcat->name,&newcat); NMD_ERR_RETURN(ierr); 00222 CHECKHASNMDCOOKIE(oldcat); 00223 for (icmp=0; icmp<oldcat->ncmp; icmp++) { 00224 NMD_metadata_item oldcmp = oldcat->cmps[icmp],newcmp; 00225 ierr = NMDCategoryGetOrCreateComponent 00226 (newcat,oldcmp->name,oldcmp->t,&newcmp); NMD_ERR_RETURN(ierr); 00227 ierr = NMDCopyItemValues(oldcmp,newcmp); NMD_ERR_RETURN(ierr); 00228 } 00229 } 00230 CHKMEMQ 00231 return 0; 00232 } 00233 00234 /*! \page viewing Viewing objects 00235 NMDViewObject() gives informal output; NMDReportObject() can be 00236 used for database records and such. 00237 */ 00238 #undef __FUNCT__ 00239 #define __FUNCT__ "NMDViewObject" 00240 /*! Print out an NMD object. 00241 00242 Currently only int, real, string fields are displayed, 00243 others are displayed as \c "***". 00244 */ 00245 NMDErrorCode NMDViewObject(NMD_metadata obj) 00246 { 00247 int icat,icmp; 00248 CHECKHASNMDCOOKIE(obj); 00249 printf("========\n"); 00250 for (icat=0; icat<obj->ncat; icat++) { 00251 NMD_metadata_category cat = obj->cats[icat]; 00252 CHECKHASNMDCOOKIE(cat); 00253 printf("Category: <%s>\n",cat->name); 00254 for (icmp=0; icmp<cat->ncmp; icmp++) { 00255 NMD_metadata_item cmp = cat->cmps[icmp]; 00256 CHECKHASNMDCOOKIE(cmp); 00257 printf(" <%s> : ",cmp->name); 00258 if (!cmp->set) { 00259 printf("(null)\n"); 00260 } else { 00261 switch (cmp->t) { 00262 case NMDInt : printf("<%d>\n",cmp->i); break; 00263 case NMDReal : printf("<%e>\n",cmp->r); break; 00264 case NMDString : printf("<<%s>>\n",cmp->cc); break; 00265 default : printf("****\n"); break; 00266 } 00267 } 00268 } 00269 } 00270 printf("========\n\n"); 00271 CHKMEMQ 00272 return 0; 00273 } 00274 00275 #undef __FUNCT__ 00276 #define __FUNCT__ "NMDReportObject" 00277 /*! Generate a delimited representation of a metadata object. 00278 00279 The returned strings are allocated in this routine and it is the user's 00280 responsibility to free them with NMD_FREE(). 00281 00282 Arguments: 00283 - obj : the metadata object 00284 - ar : boolean to indicate whether arrays need to be written out in full. 00285 If this is false, only the first and last couple of elements are given. 00286 - rkey : a string containing the names of the metadata items 00287 - rval : the metadata items 00288 - delim : delimiter character used in \c rkey and \c rval 00289 - itemdelim1 : an optional opening quote, used for both keys and values. 00290 (A NULL value will cause no delimiter to be printed, rather than a null 00291 character.) 00292 For instance, use the backquote when generating MySQL strings. 00293 - itemdelim2 : an optional closing quote 00294 00295 */ 00296 NMDErrorCode NMDReportObject 00297 (NMD_metadata obj,NMDTruth arrays,const char **rkey,const char **rval, 00298 const char delim,const char itemdelim1,const char itemdelim2) 00299 { 00300 int icat,icmp,write,keylen=0,vallen=0; char *key=NULL,*val=NULL, *scratch; 00301 CHECKHASNMDCOOKIE(obj); 00302 00303 /* 00304 * allocate and fill in the key and value strings 00305 */ 00306 #define CHKLEN 500 00307 NMD_MALLOC(scratch,CHKLEN,char,"scratch pad"); 00308 #define CHKSPACEFOR(ar,arlen,fmt,str) {int nr; memset(scratch,0,CHKLEN); sprintf(scratch,fmt,str); nr=strlen(scratch); if (write==0) {arlen = arlen+nr+2; } else {int l = strlen(ar); if (l+nr<arlen) {sprintf(ar+l,fmt,str);} else SETERRQ(1,"sprintf would overflow allocated buffer");}} 00309 write = 0; 00310 writeloop: 00311 if (write==0) { 00312 keylen=vallen=0; 00313 } else { 00314 if (rkey) NMD_MALLOC(key,keylen,char,"names array"); 00315 if (rval) NMD_MALLOC(val,vallen,char,"values array"); 00316 } 00317 for (icat=0; icat<obj->ncat; icat++) { 00318 NMD_metadata_category cat = obj->cats[icat]; 00319 CHECKHASNMDCOOKIE(cat); 00320 for (icmp=0; icmp<cat->ncmp; icmp++) { 00321 NMD_metadata_item cmp = cat->cmps[icmp]; 00322 CHECKHASNMDCOOKIE(cmp); 00323 if (rkey) { 00324 if (itemdelim1) CHKSPACEFOR(key,keylen,"%c",itemdelim1); 00325 CHKSPACEFOR(key,keylen,"%s:",cat->name); 00326 CHKSPACEFOR(key,keylen,"%s",cmp->name); 00327 if (itemdelim2) CHKSPACEFOR(key,keylen,"%c",itemdelim2); 00328 CHKSPACEFOR(key,keylen,"%c",delim); 00329 } 00330 if (rval) { 00331 if (itemdelim1) CHKSPACEFOR(val,vallen,"%c",itemdelim1); 00332 if (!cmp->set) goto delimiter; 00333 switch (cmp->t) { 00334 case NMDInt : { 00335 CHKSPACEFOR(val,vallen,"%8d",cmp->i); break;} 00336 case NMDReal : { 00337 CHKSPACEFOR(val,vallen,"%15.8e",cmp->r); break;} 00338 case NMDString : 00339 if (!cmp->cc) NMD_ERR_REPORT("Null string"); 00340 if (strlen(cmp->cc)>0) { 00341 if (strlen(cmp->cc)<=CHKLEN) { 00342 CHKSPACEFOR(val,vallen,"%s",cmp->cc); 00343 } else {CHKSPACEFOR(val,vallen,"%s","stringtoolong");} 00344 } else { 00345 CHKSPACEFOR(val,vallen,"%s","null"); 00346 } 00347 break; 00348 case NMDIntarray : { 00349 struct NMD_intarray_struct *arraystruct = 00350 (struct NMD_intarray_struct *)(cmp->ii); 00351 int n = arraystruct->length,i; 00352 if (arrays || n<=4) { 00353 for (i=0; i<n; i++) { 00354 if (i<n-1) { 00355 CHKSPACEFOR(val,vallen,"%8d,",arraystruct->data[i]); 00356 } else { 00357 CHKSPACEFOR(val,vallen,"%8d",arraystruct->data[i]); 00358 } 00359 } 00360 } else { 00361 CHKSPACEFOR(val,vallen,"%8d,",arraystruct->data[0]); 00362 CHKSPACEFOR(val,vallen,"%8d,",arraystruct->data[1]); 00363 CHKSPACEFOR(val,vallen,"%8d,",arraystruct->data[n-2]); 00364 CHKSPACEFOR(val,vallen,"%8d",arraystruct->data[n-1]); 00365 } 00366 } ; break; 00367 case NMDRealarray : { 00368 struct NMD_realarray_struct *arraystruct = 00369 (struct NMD_realarray_struct *)(cmp->rr); 00370 int n = arraystruct->length,i; 00371 if (arrays || n<=4) { 00372 for (i=0; i<n; i++) { 00373 if (i<n-1) { 00374 CHKSPACEFOR(val,vallen,"%11.4e,",arraystruct->data[i]); 00375 } else { 00376 CHKSPACEFOR(val,vallen,"%11.4e",arraystruct->data[i]); 00377 } 00378 } 00379 } else { 00380 CHKSPACEFOR(val,vallen,"%11.4e,",arraystruct->data[0]); 00381 CHKSPACEFOR(val,vallen,"%11.4e,",arraystruct->data[1]); 00382 CHKSPACEFOR(val,vallen,"%11.4e,",arraystruct->data[n-2]); 00383 CHKSPACEFOR(val,vallen,"%11.4e",arraystruct->data[n-1]); 00384 } 00385 } ; break; 00386 default : 00387 CHKSPACEFOR(val,vallen,"%s","==="); break; 00388 } 00389 delimiter: 00390 if (itemdelim2) CHKSPACEFOR(val,vallen,"%c",itemdelim2); 00391 CHKSPACEFOR(val,vallen,"%c",delim); 00392 } 00393 } 00394 } 00395 write += 1; 00396 if (write<=1) goto writeloop; 00397 NMD_FREE(scratch); 00398 CHKMEMQ; 00399 /* *rkey = key; *rval = val; */ 00400 if (key) { 00401 int l = strlen(key); 00402 if (l>keylen) 00403 NMD_ERR_REPORT("key string overrun"); 00404 *rkey = key; 00405 } 00406 if (val) { 00407 int l = strlen(val); 00408 if (l>vallen) 00409 NMD_ERR_REPORTii("val string overrun; alloc/actual",vallen,l); 00410 *rval = val; 00411 } 00412 00413 return 0; 00414 } 00415 00416 /*! \page values Value handling 00417 00418 NMD handles scalar and array values slightly differently. 00419 For scalar values use NMDSetValue() and NMDGetValue(); 00420 for array values use NMDSetArrayValue(), NMDGetArrayValue(), 00421 NMDCopyArrayValue(). The array routines take an extra parameter 00422 denoting the length of the array. 00423 00424 Note that scalar values have to be passed by reference: 00425 \code 00426 int i,*ii; 00427 NMDSetValue(nmd,....,&i); // use an ampersand here 00428 NMDSetValue(nmd,....,ii,length); // no ampersand needed here! 00429 NMDGetValue(nmd,....,&i); 00430 NMDGetValue(nmd,....,&ii,&length); 00431 \endcode 00432 00433 Furthermore, see NMDCopyItemValues(), NMDGetDataType(), 00434 NMDIsArrayType(). 00435 */ 00436 00437 #undef __FUNCT__ 00438 #define __FUNCT__ "NMDSetValue" 00439 /*! Set a metadata value, indexed by category and component name. 00440 00441 The value has to be passed by reference 00442 00443 String values are copied. (Reason: literal strings are treated 00444 differently from allocated, and Petsc has its own way of doing strings.) 00445 00446 This call can be used to create categories and components; there is 00447 no checking of slight misspellings. 00448 00449 See also \ref values. 00450 */ 00451 NMDErrorCode NMDSetValue(NMD_metadata obj,const char *cat,const char *cmp,NMDDataType t,void *v) 00452 { 00453 NMD_metadata_category ctg; NMD_metadata_item cpt; NMDErrorCode ierr; 00454 00455 CHECKHASNMDCOOKIE(obj); 00456 ierr = NMDObjectGetOrCreateCategory(obj,(char*)cat,&ctg); NMD_ERR_RETURN(ierr); 00457 ierr = NMDCategoryGetOrCreateComponent(ctg,(char*)cmp,t,&cpt); NMD_ERR_RETURN(ierr); 00458 ierr = NMDComponentSetValue(cpt,t,v); NMD_ERR_RETURN(ierr); 00459 CHKMEMQ 00460 00461 return 0; 00462 } 00463 00464 NMDErrorCode NMDUnsetValue(NMD_metadata obj,const char *cat,const char *cmp) 00465 { 00466 NMD_metadata_category ctg; NMD_metadata_item cpt; 00467 NMDTruth flg; NMDErrorCode ierr; 00468 00469 CHECKHASNMDCOOKIE(obj); 00470 ierr = NMDObjectTryGetCategory(obj,cat,&ctg,&flg); NMD_ERR_RETURN(ierr); 00471 if (!flg) return 0; 00472 ierr = NMDCategoryTryGetComponent(ctg,cmp,&cpt,&flg); NMD_ERR_RETURN(ierr); 00473 if (!flg) return 0; 00474 ierr = NMDComponentUnsetValue(cpt); NMD_ERR_RETURN(ierr); 00475 CHKMEMQ 00476 00477 return 0; 00478 } 00479 00480 #undef __FUNCT__ 00481 #define __FUNCT__ "NMDSetArrayValue" 00482 /*! Set a metadata value, if it is an array type. 00483 00484 The arrays are not copied, so the user is responsible for freeing the array. 00485 Use NMDCopyArrayValue() to have the array copied; NMD will then free the 00486 array when the metadata object is freed. 00487 00488 This call can be used to create categories and components; there is 00489 no checking of slight misspellings. 00490 00491 See also \ref values. 00492 */ 00493 NMDErrorCode NMDSetArrayValue 00494 (NMD_metadata obj,const char *cat,const char *cmp,NMDDataType t,void *v,int l) 00495 { 00496 NMD_metadata_category ctg; NMD_metadata_item cpt; NMDErrorCode ierr; 00497 00498 CHECKHASNMDCOOKIE(obj); 00499 ierr = NMDObjectGetOrCreateCategory(obj,(char*)cat,&ctg); NMD_ERR_RETURN(ierr); 00500 ierr = NMDCategoryGetOrCreateComponent(ctg,(char*)cmp,t,&cpt); NMD_ERR_RETURN(ierr); 00501 ierr = NMDComponentSetArrayValue(cpt,t,v,l); NMD_ERR_RETURN(ierr); 00502 CHKMEMQ 00503 00504 return 0; 00505 } 00506 00507 #undef __FUNCT__ 00508 #define __FUNCT__ "NMDCopyArrayValue" 00509 /*! Set a metadata array value; the user array is 00510 copied. 00511 00512 This call can be used to create categories and components; there is 00513 no checking of slight misspellings. 00514 00515 See also \ref values. 00516 */ 00517 NMDErrorCode NMDCopyArrayValue 00518 (NMD_metadata obj,const char *cat,const char *cmp,NMDDataType t,void *v,int l) 00519 { 00520 NMD_metadata_category ctg; NMD_metadata_item cpt; NMDErrorCode ierr; 00521 00522 CHECKHASNMDCOOKIE(obj); 00523 ierr = NMDObjectGetOrCreateCategory(obj,(char*)cat,&ctg); NMD_ERR_RETURN(ierr); 00524 ierr = NMDCategoryGetOrCreateComponent(ctg,(char*)cmp,t,&cpt); NMD_ERR_RETURN(ierr); 00525 00526 CHECKHASNMDCOOKIE(cpt); 00527 cpt->set = NMDTrue; 00528 switch (cpt->t) { 00529 case NMDInt : 00530 case NMDReal : 00531 case NMDString : 00532 ierr = NMDSetValue(obj,cat,cmp,t,v); NMD_ERR_RETURN(ierr); 00533 break; 00534 case NMDIntarray : { 00535 struct NMD_intarray_struct* iistruct; int *ii,i; 00536 NMD_MALLOC(iistruct,1,struct NMD_intarray_struct,"int array struct"); 00537 iistruct->unique = 1; iistruct->length = l; 00538 NMD_MALLOC(ii,l,sizeof(int),"copied int array"); 00539 for (i=0; i<l; i++) ii[i] = (*(int**)v)[i]; 00540 iistruct->data = ii; 00541 cpt->ii = iistruct; 00542 break;} 00543 case NMDRealarray : { 00544 struct NMD_realarray_struct* rrstruct; NMDRealtype *rr; int i; 00545 NMD_MALLOC(rrstruct,1,struct NMD_realarray_struct,"real array struct"); 00546 rrstruct->unique = 1; rrstruct->length = l; 00547 NMD_MALLOC(rr,l,NMDRealtype,"copied real array"); 00548 for (i=0; i<l; i++) rr[i] = (*(NMDRealtype**)v)[i]; 00549 rrstruct->data = rr; 00550 cpt->rr = rrstruct; 00551 break;} 00552 default : NMD_ERR_REPORTi("Unknown type",(int)t); break; 00553 } 00554 CHKMEMQ 00555 00556 return 0; 00557 } 00558 00559 #undef __FUNCT__ 00560 #define __FUNCT__ "NMDGetValue" 00561 /*! Retrieve a stored scalar value. 00562 If no value has been stored under the specified category and component, 00563 a zero flag is returned. The flag parameter can be null. 00564 00565 Null pointers can be passed for the datatype or value, for instance to 00566 test only for the existence of a set value. 00567 00568 See also \ref values. 00569 */ 00570 NMDErrorCode NMDGetValue 00571 (NMD_metadata obj,const char *cat,const char *cmp,NMDDataType *t,void *v,NMDTruth *f) 00572 { 00573 NMD_metadata_category ctg; NMD_metadata_item cpt; 00574 NMDTruth ff; NMDErrorCode ierr; 00575 00576 CHECKHASNMDCOOKIE(obj); 00577 ierr = NMDObjectTryGetCategory(obj,cat,&ctg,&ff); NMD_ERR_RETURN(ierr); 00578 if (!ff) { 00579 if (f) { 00580 *f = NMDFalse; return 0; 00581 } else NMD_ERR_REPORT 00582 ("Could not find category, but no flag given to report this"); 00583 } 00584 CHECKHASNMDCOOKIE(ctg); 00585 ierr = NMDCategoryTryGetComponent(ctg,cmp,&cpt,&ff); NMD_ERR_RETURN(ierr); 00586 if (!ff) { 00587 if (f) { 00588 *f = NMDFalse; return 0; 00589 } else NMD_ERR_REPORT 00590 ("Could not find component, but no flag given to report this"); 00591 } 00592 CHECKHASNMDCOOKIE(cpt); 00593 if (!cpt->set) { 00594 if (f) { 00595 *f = NMDFalse; return 0; 00596 } else NMD_ERR_REPORT 00597 ("Value not set, but no flag given to report this"); 00598 } 00599 if (t) *t = cpt->t; 00600 switch (cpt->t) { 00601 case NMDInt : 00602 if (v) *(int*)v = cpt->i; 00603 if (f) *f = NMDTrue; break; 00604 case NMDReal : 00605 if (v) *(double*)v = cpt->r; 00606 if (f) *f = NMDTrue; break; 00607 case NMDString : 00608 if (v) *(char**)v = cpt->cc; 00609 if (f) *f = NMDTrue; break; 00610 case NMDIntarray : 00611 case NMDRealarray : 00612 NMD_ERR_REPORT("Please use NMDGetArrayValue"); break; 00613 default : 00614 if (f) *f = NMDFalse; 00615 } 00616 CHKMEMQ 00617 return 0; 00618 } 00619 00620 #undef __FUNCT__ 00621 #define __FUNCT__ "NMDGetArrayValue" 00622 /*! Retrieve a stored value. 00623 If no value has been stored under the specified category and component, 00624 a zero flag is returned. The flag parameter can be null. 00625 00626 Null pointers can be passed for the datatype or value, for instance to 00627 test only for the existence of a set value. 00628 00629 See also \ref values. 00630 */ 00631 NMDErrorCode NMDGetArrayValue 00632 (NMD_metadata obj,const char *cat,const char *cmp, 00633 NMDDataType *t,void *v,int *len,NMDTruth *f) 00634 { 00635 NMD_metadata_category ctg; NMD_metadata_item cpt; NMDErrorCode ierr; 00636 00637 CHECKHASNMDCOOKIE(obj); 00638 ierr = NMDObjectGetCategory(obj,cat,&ctg); NMD_ERR_RETURN(ierr); 00639 CHECKHASNMDCOOKIE(ctg); 00640 ierr = NMDCategoryGetComponent(ctg,cmp,&cpt); NMD_ERR_RETURN(ierr); 00641 CHECKHASNMDCOOKIE(cpt); 00642 if (!cpt->set) { 00643 if (f) { 00644 *f = NMDFalse; return 0; 00645 } else NMD_ERR_REPORT 00646 ("Value not set, but no flag given to report this"); 00647 } 00648 if (t) *t = cpt->t; 00649 switch (cpt->t) { 00650 case NMDInt : 00651 case NMDReal : 00652 case NMDString : 00653 ierr = NMDGetValue(obj,cat,cmp,NULL,v,f); NMD_ERR_RETURN(ierr); 00654 break; 00655 case NMDIntarray : 00656 if (v || len) { 00657 struct NMD_intarray_struct *as = cpt->ii; 00658 if (v) *(int**)v = as->data; 00659 if (len) *len = as->length; 00660 } 00661 if (f) *f = NMDTrue; break; 00662 case NMDRealarray : 00663 if (v || len) { 00664 struct NMD_realarray_struct *as = cpt->rr; 00665 if (v) *(NMDRealtype**)v = as->data; 00666 if (len) *len = as->length; 00667 } 00668 if (f) *f = NMDTrue; break; 00669 default : 00670 if (f) *f = NMDFalse; 00671 } 00672 CHKMEMQ 00673 return 0; 00674 } 00675 00676 #if 0 00677 #undef __FUNCT__ 00678 #define __FUNCT__ "NMDGetValueByIndex" 00679 /*! Retrieve a stored value by index. As in NMDGetValue(), all output 00680 parameters can receive null pointers. 00681 */ 00682 NMDErrorCode NMDGetValueByIndex 00683 (NMD_metadata obj,int icat,int icmp,NMDDataType *t,void *v,int *f) 00684 { 00685 NMD_metadata_category cat; 00686 NMD_metadata_item cmp; 00687 NMDErrorCode ierr; 00688 00689 CHECKHASNMDCOOKIE(obj); 00690 if (icat<0 || icat>=obj->ncat) 00691 NMD_ERR_REPORTi("category index out of range",icat); 00692 cat = obj->cats[icat]; CHECKHASNMDCOOKIE(cat); 00693 if (icmp<0 || icmp>=obj->cats[icat]->ncmp) 00694 NMD_ERR_REPORTii("component index out of range",icat,icmp); 00695 00696 cmp = cat->cmps[icmp]; CHECKHASNMDCOOKIE(cmp); 00697 if (t) *t = cmp->t; 00698 switch (cmp->t) { 00699 case NMDInt : 00700 if (v) *(int*)v = cmp->i; 00701 if (f) *f = NMDTrue; break; 00702 case NMDReal : 00703 if (v) *(double*)v = cmp->r; 00704 if (f) *f = NMDTrue; break; 00705 case NMDIntarray : 00706 if (v) *(int**)v = cmp->ii; 00707 if (f) *f = NMDTrue; break; 00708 case NMDRealarray : 00709 if (v) *(double**)v = cmp->rr; 00710 if (f) *f = NMDTrue; break; 00711 default : 00712 if (f) *f = NMDFalse; 00713 } 00714 return 0; 00715 } 00716 #endif 00717 00718 #undef __FUNCT__ 00719 #define __FUNCT__ "NMDGetDataType" 00720 NMDErrorCode NMDGetDataType(NMD_metadata obj,const char *cat,const char *cmp,NMDDataType *t) 00721 { 00722 NMD_metadata_category ctg; NMD_metadata_item cpt; 00723 NMDErrorCode ierr; 00724 00725 CHECKHASNMDCOOKIE(obj); 00726 ierr = NMDObjectGetCategory(obj,cat,&ctg); NMD_ERR_RETURN(ierr); 00727 ierr = NMDCategoryGetComponent(ctg,cmp,&cpt); NMD_ERR_RETURN(ierr); 00728 CHECKHASNMDCOOKIE(cmp); 00729 *t = cpt->t; 00730 00731 return 0; 00732 } 00733 00734 #undef __FUNCT__ 00735 #define __FUNCT__ "NMDIsArrayType" 00736 /*! Test whether a data type is an array type */ 00737 NMDErrorCode NMDIsArrayType(NMDDataType type,NMDTruth *flg) 00738 { 00739 *flg = ( (type==NMDIntarray) || (type==NMDRealarray) ? NMDTrue : NMDFalse ) ; 00740 return 0; 00741 } 00742 00743 #undef __FUNCT__ 00744 #define __FUNCT__ "NMDGetTypeMySQLName" 00745 PetscErrorCode NMDGetTypeMySQLName(NMDDataType type,const char **name) 00746 { 00747 int itype = (int)(type); 00748 if (itype<0 || itype>=nnmdtypenames) 00749 NMD_ERR_REPORTi("Invalid type",itype); 00750 *name = (char*)mysqltypenames[itype]; 00751 return 0; 00752 } 00753