NMD
|
00001 #include <stdlib.h> 00002 #include "string.h" 00003 #include "nmd.h" 00004 #include "nmd_impl.h" 00005 00006 #define CMPCHUNK 30 00007 00008 /*! \page categoryfunctions Metadata category manipulation 00009 00010 A metadata object contains a number of categories, each containing 00011 multiple component which store the actual metadata. Here are the 00012 routines for manipulation the categories. 00013 00014 See NMDObjectTryGetCategory(), NMDObjectGetCategory(), 00015 NMDAllocateCategory(), NMDObjectAllocateNewCategory(), 00016 NMDObjectGetOrCreateCategory(), 00017 NMDRemoveCategory(), NMDGetCategories(), NMDCopyCategory(). 00018 */ 00019 00020 #undef __FUNCT__ 00021 #define __FUNCT__ "NMDObjectTryGetCategory" 00022 /*! Test whether a metadata object has a certain category, if so 00023 yield up its pointer. 00024 00025 The category pointer parameter can be null, in which case only existence 00026 is tested. 00027 */ 00028 NMDErrorCode NMDObjectTryGetCategory 00029 (NMD_metadata obj,const char *cat,NMD_metadata_category *rctg,NMDTruth *f) 00030 { 00031 int icat; 00032 CHECKHASNMDCOOKIE(obj); 00033 *f = NMDFalse; 00034 for (icat=0; icat<obj->ncat; icat++) { 00035 NMD_metadata_category ctg = obj->cats[icat]; 00036 CHECKHASNMDCOOKIE(ctg); 00037 if (strcmp(cat,ctg->name)==0) { 00038 if (rctg) *rctg = ctg; *f = NMDTrue; break; 00039 } 00040 } 00041 return 0; 00042 } 00043 00044 #undef __FUNCT__ 00045 #define __FUNCT__ "NMDObjectGetCategory" 00046 /*! Retrieve a category from a metadata object. The category has to exist. 00047 */ 00048 NMDErrorCode NMDObjectGetCategory 00049 (NMD_metadata obj,const char *cat,NMD_metadata_category *ctg) 00050 { 00051 NMDTruth flg; NMDErrorCode ierr; 00052 CHECKHASNMDCOOKIE(obj); 00053 ierr = NMDObjectTryGetCategory(obj,cat,ctg,&flg); NMD_ERR_RETURN(ierr); 00054 if (!flg) NMD_ERR_REPORTs("Category not found",cat); 00055 return 0; 00056 } 00057 00058 #undef __FUNCT__ 00059 #define __FUNCT__ "NMDAllocateCategory" 00060 /*! This is an internal routine that merely allocates 00061 the data structure for storing a category. 00062 */ 00063 static NMDErrorCode NMDAllocateCategory(NMD_metadata_category *rcat) 00064 { 00065 NMD_metadata_category cat; 00066 NMD_MALLOC(cat,1,struct NMD_metadata_category_,"category"); 00067 cat->cookie = NMDCOOKIE; 00068 cat->alloc = CMPCHUNK; cat->ncmp = 0; 00069 NMD_MALLOC(cat->cmps,cat->alloc,NMD_metadata_item,"items array"); 00070 *rcat = cat; 00071 CHKMEMQ 00072 return 0; 00073 } 00074 00075 #undef __FUNCT__ 00076 #define __FUNCT__ "NMDObjectAllocateNewCategory" 00077 /*! Allocate a category in a metadata object. 00078 There is no testing whether the category name is already in use. 00079 00080 If a category pointer is supplied, the category is returned, 00081 but this pointer is allowed to be null. 00082 */ 00083 NMDErrorCode NMDObjectAllocateNewCategory 00084 (NMD_metadata obj,const char *cat,NMD_metadata_category *rctg) 00085 { 00086 NMD_metadata_category ctg; int idx; NMDErrorCode ierr; 00087 /* 00088 * if we are about to overflow, reallocate 00089 */ 00090 if (obj->ncat >= obj->alloc) { 00091 NMD_metadata_category* newcats; int newalloc; 00092 newalloc = 2*obj->alloc; 00093 ierr = PetscMalloc 00094 (newalloc*sizeof(struct NMD_metadata_category_),&newcats); CHKERRQ(ierr); 00095 for (idx=0; idx<obj->ncat; idx++) 00096 newcats[idx] = obj->cats[idx]; 00097 ierr = PetscFree(obj->cats); CHKERRQ(ierr); 00098 obj->cats = newcats; obj->alloc = newalloc; 00099 } 00100 /* 00101 * with space guaranteed, create the category 00102 */ 00103 idx = obj->ncat++; 00104 ierr = NMDAllocateCategory(&ctg); NMD_ERR_RETURN(ierr); 00105 NMD_STRDUP(cat,ctg->name); 00106 obj->cats[idx] = ctg; 00107 if (rctg) *rctg = ctg; 00108 CHKMEMQ 00109 return 0; 00110 } 00111 00112 #undef __FUNCT__ 00113 #define __FUNCT__ "NMDObjectGetOrCreateCategory" 00114 /*! Retrieve a category from a metadata object, or create it 00115 if it doesn't exist yet. 00116 */ 00117 NMDErrorCode NMDObjectGetOrCreateCategory 00118 (NMD_metadata obj,const char *cat,NMD_metadata_category *ctg) 00119 { 00120 NMDTruth flg; NMDErrorCode ierr; 00121 CHECKHASNMDCOOKIE(obj); 00122 ierr = NMDObjectTryGetCategory(obj,cat,ctg,&flg); NMD_ERR_RETURN(ierr); 00123 if (!flg) { 00124 ierr = NMDObjectAllocateNewCategory(obj,cat,ctg); NMD_ERR_RETURN(ierr); 00125 } 00126 CHKMEMQ 00127 return 0; 00128 } 00129 00130 #undef __FUNCT__ 00131 #define __FUNCT__ "NMDGetCategories" 00132 /*! Get the number of categories and their names. Both arguments can be NULL. 00133 The names array is allocated; the user needs to free it. The names themselves 00134 are pointers to the strings in the metadata object, so they do not need to 00135 be freed. 00136 */ 00137 NMDErrorCode NMDGetCategories(NMD_metadata obj,int *ncat,char ***cats) 00138 { 00139 CHECKHASNMDCOOKIE(obj); 00140 if (ncat) *ncat = obj->ncat; 00141 if (obj->ncat && cats) { 00142 char **names; int icat; 00143 NMD_MALLOC(names,obj->ncat,char*,"name array"); 00144 for (icat=0; icat<obj->ncat; icat++) 00145 names[icat] = obj->cats[icat]->name; 00146 *cats = names; 00147 } 00148 CHKMEMQ 00149 return 0; 00150 } 00151 00152 #undef __FUNCT__ 00153 #define __FUNCT__ "NMDRemoveCategory" 00154 /* Remove a category from an NMD object. This is done through setting its 00155 name to \c "invalid". Later we will do real deallocation. 00156 00157 The removed category still counts towards the number reported 00158 in NMDGetCategories(). 00159 */ 00160 NMDErrorCode NMDRemoveCategory(NMD_metadata obj,const char *cat) 00161 { 00162 NMD_metadata_category ctg; NMDErrorCode ierr; 00163 00164 CHECKHASNMDCOOKIE(obj); 00165 ierr = NMDObjectGetCategory(obj,(char*)cat,&ctg); NMD_ERR_RETURN(ierr); 00166 NMD_FREE(ctg->name); 00167 NMD_STRDUP("invalid",ctg->name); 00168 CHKMEMQ 00169 00170 return 0; 00171 } 00172 00173 #undef __FUNCT__ 00174 #define __FUNCT__ "NMDCopyCategory" 00175 /*! Copy category data from one metadata structure into another. 00176 This assumes that the category already exists in the target; 00177 see for instance NMDHasCategory(), NMDCloneObject(), 00178 NMDCloneObjectStructure(). 00179 */ 00180 NMDErrorCode NMDCopyCategory(NMD_metadata_category incat,NMD_metadata_category outcat) 00181 { 00182 int icmp; NMDErrorCode ierr; 00183 00184 CHECKHASNMDCOOKIE(incat); 00185 CHECKHASNMDCOOKIE(outcat); 00186 00187 for (icmp=0; icmp<incat->ncmp; icmp++) { 00188 NMD_metadata_item src = incat->cmps[icmp],tar; 00189 ierr = NMDCategoryGetOrCreateComponent 00190 (outcat,src->name,src->t,&tar); NMD_ERR_RETURN(ierr); 00191 ierr = NMDCopyItemValues(src,tar); NMD_ERR_RETURN(ierr); 00192 } 00193 CHKMEMQ 00194 00195 return 0; 00196 } 00197