NMD
|
00001 #include <stdlib.h> 00002 #include "memory.h" 00003 #include "nmd.h" 00004 #include "nmd_impl.h" 00005 00006 /*! \page componentfunctions Metadata component manipulation 00007 00008 Categories have components, much like metadata objects have 00009 categories. Most of the component functions work on a 00010 metadata object, and specify both category and component name. 00011 00012 See 00013 NMDCategoryAllocateNewComponent(), NMDCategoryGetOrCreateComponent(), 00014 NMDObjectHasCategoryComponent(), NMDCategoryTryGetComponent(), 00015 NMDCategoryGetComponent(), 00016 NMDGetCategoryIGetComponents() 00017 */ 00018 00019 #undef __FUNCT__ 00020 #define __FUNCT__ "NMDAllocateComponent" 00021 /*! An internal routine that only allocates the component 00022 data structure 00023 */ 00024 static NMDErrorCode NMDAllocateComponent(NMD_metadata_item *rcmp) 00025 { 00026 NMD_metadata_item cmp; 00027 NMD_MALLOC(cmp,1,struct NMD_metadata_item_,"component"); 00028 cmp->cookie = NMDCOOKIE; cmp->set = NMDFalse; 00029 *rcmp = cmp; 00030 CHKMEMQ; 00031 return 0; 00032 } 00033 00034 #undef __FUNCT__ 00035 #define __FUNCT__ "NMDCategoryAllocateNewComponent" 00036 /*! Create a new component by name in an existing category object. 00037 If a component pointer is supplied, the new component object is returned, 00038 but this pointer is allowed to be NULL. 00039 */ 00040 NMDErrorCode NMDCategoryAllocateNewComponent 00041 (NMD_metadata_category cat,const char *cmp,NMDDataType type,NMD_metadata_item *rcpt) 00042 { 00043 NMD_metadata_item cpt; int idx; NMDErrorCode ierr; 00044 /* 00045 * if we are about to overflow, 00046 * reallocate the components in this category 00047 */ 00048 if (cat->ncmp >= cat->alloc) { 00049 NMD_metadata_item* newcmps; int newalloc; 00050 newalloc = 2*cat->alloc; 00051 ierr = PetscMalloc 00052 (newalloc*sizeof(struct NMD_metadata_item_),&newcmps); CHKERRQ(ierr); 00053 for (idx=0; idx<cat->ncmp; idx++) 00054 newcmps[idx] = cat->cmps[idx]; 00055 ierr = PetscFree(cat->cmps); CHKERRQ(ierr); 00056 cat->cmps = newcmps; cat->alloc = newalloc; 00057 } 00058 /* 00059 * with space guaranteed, create the component 00060 */ 00061 idx = cat->ncmp++; 00062 ierr = NMDAllocateComponent(&cpt); NMD_ERR_RETURN(ierr); 00063 NMD_STRDUP(cmp,cpt->name); cpt->t = type; cpt->set = NMDFalse; 00064 cat->cmps[idx] = cpt; 00065 if (rcpt) *rcpt = cpt; 00066 CHKMEMQ; 00067 return 0; 00068 } 00069 00070 #undef __FUNCT__ 00071 #define __FUNCT__ "NMDComponentDestroy" 00072 NMDErrorCode NMDComponentDestroy(NMD_metadata_item cmp) 00073 { 00074 switch (cmp->t) { 00075 case NMDIntarray : 00076 if (cmp->ii) { 00077 struct NMD_intarray_struct *arraystruct = 00078 (struct NMD_intarray_struct *)(cmp->ii); 00079 if (arraystruct->length>0 && arraystruct->unique==1) 00080 NMD_FREE(arraystruct->data); 00081 NMD_FREE(cmp->ii); 00082 } ; 00083 break; 00084 case NMDRealarray : 00085 if (cmp->rr) { 00086 struct NMD_realarray_struct *arraystruct = 00087 (struct NMD_realarray_struct *)(cmp->rr); 00088 if (arraystruct->length>0 && arraystruct->unique==1) 00089 NMD_FREE(arraystruct->data); 00090 NMD_FREE(cmp->rr); 00091 } ; 00092 break; 00093 case NMDString : NMD_FREE(cmp->cc); 00094 break; 00095 default : /* other components need no destructor */ 00096 break; 00097 } 00098 NMD_FREE(cmp->name); 00099 NMD_FREE(cmp); 00100 return 0; 00101 } 00102 00103 #undef __FUNCT__ 00104 #define __FUNCT__ "NMDCategoryGetOrCreateComponent" 00105 /*! Retrieve a component, creating it if it doesn't already exist. 00106 */ 00107 NMDErrorCode NMDCategoryGetOrCreateComponent 00108 (NMD_metadata_category cat,const char *cmp,NMDDataType type,NMD_metadata_item *cpt) 00109 { 00110 NMD_metadata_item cnew; NMDTruth flg; NMDErrorCode ierr; 00111 CHECKHASNMDCOOKIE(cat); 00112 ierr = NMDCategoryTryGetComponent(cat,cmp,&cnew,&flg); NMD_ERR_RETURN(ierr); 00113 if (flg) { 00114 if (type!=cnew->t) 00115 NMD_ERR_REPORTii 00116 ("Type incompatibility: old/new",(int)(cnew->t),(int)type); 00117 if (cpt) *cpt = cnew; 00118 } else { 00119 ierr = NMDCategoryAllocateNewComponent 00120 (cat,cmp,type,cpt); NMD_ERR_RETURN(ierr); 00121 } 00122 CHKMEMQ; 00123 return 0; 00124 } 00125 00126 #undef __FUNCT__ 00127 #define __FUNCT__ "NMDObjectEnsureCategoryComponent" 00128 /* Make sure an NMD object has a specified category and component. 00129 If the component already exists, a type check is performed. 00130 A truth parameter returns whether the component was allocated 00131 by this routine. 00132 */ 00133 NMDErrorCode NMDObjectEnsureCategoryComponent 00134 (NMD_metadata obj,const char *cat,const char *cmp,NMDDataType type,NMDTruth *nnew) 00135 { 00136 NMD_metadata_category ctg; NMD_metadata_item cpt; 00137 NMDTruth flg; NMDErrorCode ierr; 00138 CHECKHASNMDCOOKIE(obj); 00139 ierr = NMDObjectTryGetCategory(obj,cat,&ctg,&flg); NMD_ERR_RETURN(ierr); 00140 if (!flg) { 00141 ierr = NMDObjectAllocateNewCategory(obj,cat,&ctg); NMD_ERR_RETURN(ierr); 00142 } 00143 ierr = NMDCategoryTryGetComponent(ctg,cmp,&cpt,&flg); NMD_ERR_RETURN(ierr); 00144 if (flg) { 00145 if (nnew) *nnew = NMDFalse; 00146 if (type!=cpt->t) 00147 NMD_ERR_REPORTii 00148 ("Type incompatibility: old/new",(int)(cpt->t),(int)type); 00149 } else { 00150 if (nnew) *nnew = NMDTrue; 00151 ierr = NMDCategoryAllocateNewComponent 00152 (ctg,cmp,type,NULL); NMD_ERR_RETURN(ierr); 00153 } 00154 CHKMEMQ; 00155 return 0; 00156 } 00157 00158 #undef __FUNCT__ 00159 #define __FUNCT__ "NMDObjectHasCategoryComponent" 00160 NMDErrorCode NMDObjectHasCategoryComponent 00161 (NMD_metadata obj,const char *cat,const char *cmp,NMDTruth *f) 00162 { 00163 NMD_metadata_category ctg; NMDErrorCode ierr; 00164 CHECKHASNMDCOOKIE(obj); 00165 ierr = NMDObjectTryGetCategory(obj,cat,&ctg,f); NMD_ERR_RETURN(ierr); 00166 if (*f) { 00167 ierr = NMDCategoryTryGetComponent(ctg,cmp,NULL,f); NMD_ERR_RETURN(ierr); 00168 } 00169 CHKMEMQ; 00170 return 0; 00171 } 00172 00173 #undef __FUNCT__ 00174 #define __FUNCT__ "NMDCategoryTryGetComponent" 00175 /*! Test whether a metadata category has a certain component. 00176 */ 00177 NMDErrorCode NMDCategoryTryGetComponent 00178 (NMD_metadata_category cat,const char *cmp, NMD_metadata_item *rcpt,NMDTruth *f) 00179 { 00180 int icmp; 00181 CHECKHASNMDCOOKIE(cat); 00182 *f = NMDFalse; 00183 for (icmp=0; icmp<cat->ncmp; icmp++) { 00184 NMD_metadata_item cpt = cat->cmps[icmp]; 00185 CHECKHASNMDCOOKIE(cpt); 00186 if (strcmp(cmp,cpt->name)==0) { 00187 *f = NMDTrue; 00188 if (rcpt) *rcpt = cpt; 00189 break; 00190 } 00191 } 00192 CHKMEMQ; 00193 return 0; 00194 } 00195 00196 #undef __FUNCT__ 00197 #define __FUNCT__ "NMDCategoryGetComponents" 00198 /*! Get a list of all component names and types in a category. 00199 All three output arguments are optional. The names and types arrays 00200 are allocated and should be freed by the user by NMD_FREE(). The names 00201 in the name array points to the strings in the database object, so they 00202 do not need to be freed. 00203 */ 00204 NMDErrorCode NMDCategoryGetComponents 00205 (NMD_metadata obj,const char* cat,int *ncmp,const char ***cmps,NMDDataType **typs) 00206 { 00207 NMD_metadata_category catobj; int icmp; 00208 const char **names; NMDDataType *types; NMDErrorCode ierr; 00209 CHECKHASNMDCOOKIE(obj); 00210 ierr = NMDObjectGetCategory(obj,cat,&catobj); CHKERRQ(ierr); 00211 if (ncmp) *ncmp = catobj->ncmp; 00212 if (cmps) { 00213 NMD_MALLOC(names,catobj->ncmp,char*,"name array"); 00214 for (icmp=0; icmp<catobj->ncmp; icmp++) 00215 names[icmp] = catobj->cmps[icmp]->name; 00216 *cmps = names; 00217 } 00218 if (typs) { 00219 NMD_MALLOC(types,catobj->ncmp,NMDDataType,"type array"); 00220 for (icmp=0; icmp<catobj->ncmp; icmp++) 00221 types[icmp] = catobj->cmps[icmp]->t; 00222 *typs = types; 00223 } 00224 CHKMEMQ; 00225 return 0; 00226 } 00227 00228 #undef __FUNCT__ 00229 #define __FUNCT__ "NMDCategoryGetComponent" 00230 /*! Test whether a metadata category has a certain component. 00231 The component has to exist. 00232 */ 00233 NMDErrorCode NMDCategoryGetComponent 00234 (NMD_metadata_category cat,const char *cmp,NMD_metadata_item *cpt) 00235 { 00236 NMDTruth flg; NMDErrorCode ierr; 00237 CHECKHASNMDCOOKIE(cat); 00238 ierr = NMDCategoryTryGetComponent 00239 (cat,cmp,cpt,&flg); NMD_ERR_RETURN(ierr); 00240 if (!flg) NMD_ERR_REPORTss("Could not find component in category",cmp,cat->name); 00241 CHKMEMQ; 00242 return 0; 00243 } 00244 00245 #undef __FUNCT__ 00246 #define __FUNCT__ "NMDGetCategoryIGetComponents" 00247 /*! For a given category, get the number of components and their names. 00248 00249 All output arguments can be NULL. 00250 The names array is allocated; the user needs to free it. The names themselves 00251 are pointers to the strings in the metadata object, so they do not need to 00252 be freed. The types array is also allocated and needs to be freed. 00253 */ 00254 NMDErrorCode NMDGetCategoryIGetComponents 00255 (NMD_metadata obj,int icat,int *ncmp,char ***cmps,NMDDataType **typs) 00256 { 00257 NMD_metadata_category cat; 00258 CHECKHASNMDCOOKIE(obj); 00259 cat = obj->cats[icat]; 00260 if (ncmp) *ncmp = cat->ncmp; 00261 if (cat->ncmp && (cmps || typs) ) { 00262 NMDDataType *types; char **names; int icmp; 00263 if (cmps) 00264 NMD_MALLOC(names,cat->ncmp,char*,"name array"); 00265 if (typs) 00266 NMD_MALLOC(types,cat->ncmp,NMDDataType,"name array"); 00267 for (icmp=0; icmp<cat->ncmp; icmp++) { 00268 if (cmps) names[icmp] = cat->cmps[icmp]->name; 00269 if (typs) types[icmp] = cat->cmps[icmp]->t; 00270 } 00271 if (cmps) *cmps = names; if (typs) *typs = types; 00272 } 00273 return 0; 00274 } 00275 00276 #undef __FUNCT__ 00277 #define __FUNCT__ "NMDComponentSetValue" 00278 NMDErrorCode NMDComponentSetValue(NMD_metadata_item cpt,NMDDataType t,void *v) 00279 { 00280 CHECKHASNMDCOOKIE(cpt); 00281 if (t!=cpt->t) NMD_ERR_REPORT("Type conflict"); 00282 switch (cpt->t) { 00283 case NMDInt : cpt->i = *(int*)v; break; 00284 case NMDReal : cpt->r = *(double*)v; break; 00285 case NMDString : NMD_STRDUP((char*)v,cpt->cc); break; 00286 case NMDIntarray : 00287 case NMDRealarray : 00288 NMD_ERR_REPORT("Please use NMDSetArrayValue"); break; 00289 default : NMD_ERR_REPORTi("Unknown type",(int)t); break; 00290 } 00291 cpt->set = NMDTrue; 00292 return 0; 00293 } 00294 00295 #undef __FUNCT__ 00296 #define __FUNCT__ "NMDComponentUnsetValue" 00297 NMDErrorCode NMDComponentUnsetValue(NMD_metadata_item cpt) 00298 { 00299 CHECKHASNMDCOOKIE(cpt); 00300 switch (cpt->t) { 00301 case NMDInt : 00302 case NMDReal : break; 00303 case NMDString : NMD_FREE(cpt->cc); break; 00304 case NMDIntarray : { 00305 struct NMD_intarray_struct* iistruct = cpt->ii; 00306 NMD_FREE(iistruct->data); 00307 NMD_FREE(iistruct); 00308 break;} 00309 case NMDRealarray : { 00310 struct NMD_realarray_struct* rrstruct = cpt->rr; 00311 NMD_FREE(rrstruct->data); 00312 NMD_FREE(rrstruct); 00313 break;} 00314 default : NMD_ERR_REPORTi("Unknown type",cpt->t); break; 00315 } 00316 cpt->set = NMDFalse; 00317 return 0; 00318 } 00319 00320 #undef __FUNCT__ 00321 #define __FUNCT__ "NMDComponentSetArrayValue" 00322 NMDErrorCode NMDComponentSetArrayValue 00323 (NMD_metadata_item cpt,NMDDataType t,void *v,int l) 00324 { 00325 NMDErrorCode ierr; 00326 CHECKHASNMDCOOKIE(cpt); 00327 switch (cpt->t) { 00328 case NMDInt : 00329 case NMDReal : 00330 case NMDString : 00331 ierr = NMDComponentSetValue(cpt,cpt->t,v); NMD_ERR_RETURN(ierr); 00332 break; 00333 case NMDIntarray : { 00334 struct NMD_intarray_struct* iistruct; 00335 NMD_MALLOC(iistruct,1,struct NMD_intarray_struct,"int array struct"); 00336 iistruct->unique = 0; iistruct->length = l; 00337 iistruct->data = *(int**)v; 00338 cpt->ii = iistruct; 00339 break;} 00340 case NMDRealarray : { 00341 struct NMD_realarray_struct* rrstruct; 00342 NMD_MALLOC(rrstruct,1,struct NMD_realarray_struct,"real array struct"); 00343 rrstruct->unique = 0; rrstruct->length = l; 00344 rrstruct->data = *(NMDRealtype**)v; 00345 cpt->rr = rrstruct; 00346 break;} 00347 default : 00348 NMD_ERR_REPORTi("Unknown type",(int)t) 00349 } 00350 cpt->set = NMDTrue; 00351 return 0; 00352 } 00353 00354 #undef __FUNCT__ 00355 #define __FUNCT__ "NMDCopyItemValues" 00356 /*! Copy data between two item structures. If the original has unique 00357 data, so does the clone. 00358 */ 00359 PetscErrorCode NMDCopyItemValues(NMD_metadata_item src,NMD_metadata_item tar) 00360 { 00361 tar->set = src->set; if (!src->set) goto done; 00362 switch (src->t) { 00363 case NMDInt : tar->i = src->i; break; 00364 case NMDReal : tar->r = src->r ; break; 00365 case NMDString : NMD_STRDUP(src->cc,tar->cc); break; 00366 case NMDIntarray : 00367 { 00368 struct NMD_intarray_struct *tarstruct,*srcstruct = src->ii; 00369 int length=srcstruct->length; 00370 NMD_MALLOC(tarstruct,1,struct NMD_intarray_struct,"copied int array"); 00371 tarstruct->length = length; tarstruct->unique = srcstruct->unique; 00372 if (srcstruct->unique) { 00373 int *a1=srcstruct->data,*a2; int i; 00374 NMD_MALLOC(a2,length,int,"int array data"); 00375 for (i=0; i<length; i++) a2[i] = a1[i]; 00376 tarstruct->data = a2; 00377 } else 00378 tarstruct->data = srcstruct->data; 00379 tar->ii = tarstruct; 00380 } ; 00381 break; 00382 case NMDRealarray : 00383 { 00384 struct NMD_realarray_struct *tarstruct,*srcstruct = src->rr; 00385 int length=srcstruct->length; 00386 NMD_MALLOC(tarstruct,1,struct NMD_realarray_struct,"copied real array"); 00387 tarstruct->length = length; tarstruct->unique = srcstruct->unique; 00388 if (srcstruct->unique) { 00389 NMDRealtype *a1=srcstruct->data,*a2; int i; 00390 NMD_MALLOC(a2,length,NMDRealtype,"real array data"); 00391 for (i=0; i<length; i++) a2[i] = a1[i]; 00392 tarstruct->data = a2; 00393 } else 00394 tarstruct->data = srcstruct->data; 00395 tar->rr = tarstruct; 00396 } ; 00397 break; 00398 default : NMD_ERR_REPORTi("Can not copy items of type",(int)(src->t)); 00399 break; 00400 } 00401 done: 00402 CHKMEMQ; 00403 return 0; 00404 } 00405