NMD
nmdcmp.c
Go to the documentation of this file.
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