diff --git a/.gitattributes b/.gitattributes index 9df51a7..2fd175a 100644 --- a/.gitattributes +++ b/.gitattributes @@ -78,10 +78,6 @@ test/H5test.cc -text test/H5testF.f -text test/H5testFpar.f90 -text test/Makefile.am -text -tools/H5PartMerge/H5merge.cpp -text -tools/H5PartMerge/make.sh -text -tools/H5PartMerge/optparse.cpp -text -tools/H5PartMerge/optparse.h -text tools/Makefile.am -text tools/README -text tools/h5pAttrib.cc -text diff --git a/tools/H5PartMerge/H5merge.cpp b/tools/H5PartMerge/H5merge.cpp deleted file mode 100644 index 45aad9b..0000000 --- a/tools/H5PartMerge/H5merge.cpp +++ /dev/null @@ -1,1076 +0,0 @@ -/* Description - * - * This application merges and slices one, two or more H5Part files - * into a single one. The range of each file which should be merged/ - * sliced can be specified on the command line where each input file - * is handled similar to a python array. Negative indices are counted - * from the end of the file i.e. -1 signifies the last step. - * - * Copyright by Christof Kraus, 2007-2008, all rights reserved. - * - * \author Christof Kraus - * - * \date 2007 dec 27 - * - * \warning none - * - * \attention none required - * - * \bug this code is under permanent development. - * - * \todo ?? - */ -#include -#include -#include -#include -#include -#include "H5Part.h" -#include "optparse.h" - -#ifdef USE_BOOST -#include -#endif - -#define MAX_LEN 128 - -using namespace std; -struct strCmp { - bool operator()( const char* s1, const char* s2 ) const { - return strcmp( s1, s2 ) < 0; - } -}; - -struct StringCmp { - bool operator()( const string s1, const string s2 ) const { - return s1 < s2; - } -}; - -#ifdef USE_BOOST -using boost::any_cast; -typedef map StringAnyValueMap; -#endif - -typedef map StringIntMap; -typedef map StringInt64Map; - -h5part_int64_t copyFileAttribute(H5PartFile* In, H5PartFile* Out, string AttrName, h5part_int64_t Type, h5part_int64_t Num); -h5part_int64_t copyFileToStepAttribute(H5PartFile* In, H5PartFile* Out, string AttrName, h5part_int64_t Type, h5part_int64_t Num); - -#ifdef USE_BOOST -h5part_int64_t copyFileAttribute(H5PartFile* In, H5PartFile* Out, StringAnyValueMap &FileAttributes, string AttrName, h5part_int64_t Type, h5part_int64_t Num); -h5part_int64_t copyFileToStepAttribute(H5PartFile* In, H5PartFile* Out, StringAnyValueMap &FileAttributes, string AttrName, h5part_int64_t Type, h5part_int64_t Num); -#endif - -h5part_int64_t copyStepAttribute(H5PartFile* In, H5PartFile* Out, string AttrName, h5part_int64_t Type, h5part_int64_t Num); -h5part_int64_t copyDataset(H5PartFile* In, H5PartFile* Out, string SetName, h5part_int64_t Type, h5part_float64_t* FloatArray, h5part_int64_t* IntArray); - -int main(int argc, char **argv){ - - using optparse::STORE; - using optparse::STORE_TRUE; - using optparse::STORE_FALSE; - using optparse::STRING; - using optparse::BOOL; - using optparse::INT; - using optparse::DOUBLE; - - H5PartFile *H5OutFile, *H5InFile; - ifstream testopen; - - int NumInput = 0; - int effNumInput = 0; - string *InputFilenames = NULL; - string Input; - string Range; - string from_str; - int *from = NULL; - string to_str; - int *to = NULL; - - - string OutputFilename; - bool isOutputInput = false; - int OutputIsInput = 0; - - char AttrName[MAX_LEN]; - int NumFileAttr; - StringIntMap FileAttribName; - StringInt64Map FileAttribType; - StringInt64Map FileAttribNumType; - -#ifdef USE_BOOST - StringAnyValueMap FileAttributes; -#endif - - char SetName[MAX_LEN]; - int NumDataSets; - StringIntMap DataSetName; - StringInt64Map DataSetType; - - char StepAttrName[MAX_LEN]; - int NumStepAttr; - StringIntMap StepAttribName; - StringInt64Map StepAttribType; - StringInt64Map StepAttribNumType; - - StringIntMap::iterator itName; - StringInt64Map::iterator itType; - StringInt64Map::iterator itNumType; - - h5part_int64_t NumParticles = 0; - h5part_int64_t maxNumParticles = 0; - - h5part_int64_t NumSteps; - h5part_int64_t effStep = 0; - bool firstStepInput = true; - - h5part_float64_t* FloatValues = NULL; - h5part_int64_t* IntegerValues = NULL; - - h5part_int64_t Type; - h5part_int64_t SetType; - h5part_int64_t NumType; - h5part_int64_t SetNum; - - int verbosity = 0; - h5part_int64_t rc; - - string usage("H5merge\n\nmerges two or more H5Part files, but can also be used to slice a H5Part file\n\nUsage: H5merge [[options]] input1.h5[from1:to1] [input2.h5[from2:to2] ... inputN.h5[fromN:toN]] output.h5,\n where fromX and toX are the step numbers which determine the range to be merged.\n Negative values are counted from the end of the file\n\noptions:"); - optparse::OptionParser parser(usage); - - parser.add_option("-h", "--help", "help","Show this message",STORE_TRUE, BOOL, "0"); - parser.add_option("-v", "--verbose", "verbosity", "increase verbosity", STORE, INT, "0"); - parser.add_option("-r", "--replace", "replace", "If output file name is the same as input file replace the input file at the end", STORE_TRUE, BOOL, "0"); - parser.add_option("-f", "--intersect-file-attributes", "intersect-file-attributes", "merge only the intersection of file attributes from all input files", STORE_TRUE, BOOL, "0"); - parser.add_option("-s", "--intersect-step-attributes", "intersect-step-attributes", "merge only the intersection of step attributes from all steps in all input files", STORE_TRUE, BOOL, "0"); - parser.add_option("-d", "--intersect-datasets", "intersect-datasets", "merge only the intersection of datasets of all input files", STORE_TRUE, BOOL, "0"); - try { - parser.parse_args(argc, argv); - if (parser.get("help")) { - parser.help(cerr); - exit(0); - } - } - catch(optparse::OptionError e){ - cerr << e.what() << endl << endl; - parser.help(cerr); - exit(1); - } - - if (parser.arguments.size() < 2){ - cerr << "No output file found." << endl << endl; - parser.help(cerr); - exit(1); - } - - NumInput = parser.arguments.size(); //argc - 2; - InputFilenames = new string[NumInput]; - from = new int[NumInput]; - to = new int[NumInput]; - - verbosity = parser.get("verbosity"); - H5PartSetVerbosityLevel(verbosity); - - /**************************************************************\ - * Parse input file names and ranges to be merged - \**************************************************************/ - - for (int i = 0; i < NumInput - 1; ++i){ - Input = string(parser.arguments[i]); - - if (Input.find("[") != string::npos && Input.find("]") != string::npos){ - Range = Input; - Range.erase(0,Range.find_first_of("[")+1); - Range.erase(Range.find_first_of("]")); - if (Range.find(":") != string::npos){ - from_str = Range; - from_str.erase(from_str.find_first_of(":")); - if (from_str.length() == 0) - from[effNumInput] = 0; - else - from[effNumInput] = atoi(from_str.c_str()); - - to_str = Range; - to_str.erase(0,to_str.find_first_of(":")+1); - if (to_str.length() == 0) - to[effNumInput] = -1; - else - to[effNumInput] = atoi(to_str.c_str()); - }else{ - if (Range.length() > 0){ - from[effNumInput] = atoi(Range.c_str()); - to[effNumInput] = from[effNumInput]; - }else{ - from[effNumInput] = -1; - to[effNumInput] = 0; - } - } - Input.erase(Input.find_first_of("[")); - - }else{ - if (Input.find("[") != string::npos){ - Input.erase(Input.find_first_of("[")); - cerr << "error when assigning a range for file " << Input << endl; - exit(1); - } - if (Input.find("]") != string::npos){ - Input.erase(Input.find_first_of("]")); - cerr << "error when assigning a range for file " << Input << endl; - exit(1); - } - from[effNumInput] = 0; - to[effNumInput] = -1; - } - testopen.open(Input.c_str(),ios::in); - if (testopen.good()) - { - InputFilenames[effNumInput] = Input; - effNumInput++; - } - else - { - cerr << "Can't open " << Input << endl; - exit(1); - } - testopen.close(); - } - - OutputFilename = string(parser.arguments[NumInput - 1]); - - /**************************************************************\ - * check whether output file name is also an input filename; - * if true then append '_tmp' to the base name; - * rename it in the end - \**************************************************************/ - for (int i = 0; i < effNumInput; ++i){ - if (InputFilenames[i] == OutputFilename){ - if (!parser.get("replace")) - { - cout << "Do you really want to overwrite the input file " << InputFilenames[i] << "? [y/N] "; - char answer = '0'; - cin.get(answer); - - if (answer != 'y' && answer != 'Y') - { - cout << "Aborting..." << endl; - exit(1); - } - } - ostringstream tmp; - isOutputInput = true; - OutputIsInput = i; - OutputFilename.erase(OutputFilename.find_last_of(".")); - tmp << OutputFilename << "_tmp.h5"; - OutputFilename = tmp.str(); - break; - } - } - - /**************************************************************\ - * check whether output file allready exists - \**************************************************************/ - if (!isOutputInput) - { - testopen.open(OutputFilename.c_str(), ios::in); - if (testopen.good()) - { - testopen.close(); - if (!parser.get("replace")) - { - cout << "Do you really want to overwrite the file " << OutputFilename << "? [y/N] "; - char answer = '0'; - cin.get(answer); - - if (answer != 'y' && answer != 'Y') - { - cout << "Aborting..." << endl; - exit(1); - } - } - } - else if (parser.get("replace")) - { - cerr << "WARNING: option 'replace' chosen but output filename is not the same" << endl - << " as any of the input filenames" << endl; - } - } - - for (int i = 0; i < effNumInput; ++i) - { - H5InFile = H5PartOpenFile(InputFilenames[i].c_str(), H5PART_READ); - - /**************************************************************\ - * fix range if values are negative - \**************************************************************/ - int n_steps = H5PartGetNumSteps(H5InFile); - - if (from[i] >= n_steps) - from[i] = n_steps - 1; - else - while (from[i] < 0) - from[i] += n_steps; - - if (to[i] >= n_steps) - to[i] = n_steps - 1; - else - while (to[i] < 0) - to[i] += n_steps; - if (to[i] < from[i]) - { - int tmp; - tmp = to[i]; - to[i] = from[i]; - from[i] = tmp; - } - - NumSteps = to[i] - from[i] + 1; - - // cout << InputFilenames[i] << "[" << from[i] << ":" << to[i] << "]" << endl; - - for (int k = from[i]; k <= to[i]; ++k) - { - H5PartSetStep(H5InFile,k); - // cout << "Step set to " << k << endl; - - /**************************************************************\ - * determine maximum number of particles in all input files - * and all steps - \**************************************************************/ - h5part_int64_t localNumParticles = H5PartGetNumParticles(H5InFile); - if (localNumParticles > maxNumParticles) - maxNumParticles = localNumParticles; - } - - - /**************************************************************\ - * get the *intersection* of names of all file attributes - * --------------- " ------------------- step attributes - * --------------- " ------------------- datasets - * from all files which are to be merged - \**************************************************************/ - if (parser.get("intersect-file-attributes") || - parser.get("intersect-datasets") || - parser.get("intersect-step-attributes") ) - { - StringIntMap localStepAttribName; - StringInt64Map localStepAttribType; - StringInt64Map localStepAttribNumType; - StringIntMap localDataSetName; - StringInt64Map localDataSetType; - StringIntMap::iterator itlocalName; - StringInt64Map::iterator itlocalType; - StringInt64Map::iterator itlocalNumType; - - - if (parser.get("intersect-file-attributes")) - { - NumFileAttr = H5PartGetNumFileAttribs(H5InFile); - // cout << NumFileAttr << " file attributes" << endl; - for (int l = 0; l < NumFileAttr; ++l) - { - - H5PartGetFileAttribInfo(H5InFile, l, AttrName, MAX_LEN, &Type, &NumType); - // cout << "Found file attribute '" << AttrName << "'" << endl; - itName = FileAttribName.find(string(AttrName)); - if (itName == FileAttribName.end()) - { - FileAttribName.insert(make_pair(string(AttrName), 1)); - FileAttribType.insert(make_pair(string(AttrName), Type)); - FileAttribNumType.insert(make_pair(string(AttrName), NumType)); - // cout << "Added file attribute " << AttrName << endl; - } - else - { - if (FileAttribType[string(AttrName)] == Type) - { - if (FileAttribNumType[string(AttrName)] == NumType) - { - FileAttribName[string(AttrName)] += 1; - } - else - { - cerr << "WARNING: found same file attribute (" << AttrName << ") " << endl; - cerr << " with same type but different length! Will be skipped!" << endl; - } - } - else - { - cerr << "WARNING: found same file attribute (" << AttrName << ") " << endl; - cerr << " with different type! Will be skipped!" << endl; - } - } - } - } - - - for (int k = from[i]; k <= to[i]; ++k) - { - H5PartSetStep(H5InFile,k); - - if (parser.get("intersect-datasets")) - { - NumDataSets = H5PartGetNumDatasets(H5InFile); - for (h5part_int64_t m = 0; m < NumDataSets; ++m) - { - H5PartGetDatasetInfo(H5InFile, m, SetName, MAX_LEN, &SetType, &SetNum); - // cout << "Found dataset '" << SetName << "' " << endl; - itName = localDataSetName.find(string(SetName)); - if (itName == localDataSetName.end()) - { - localDataSetName.insert(make_pair(string(SetName), 1)); - localDataSetType.insert(make_pair(string(SetName), SetType)); - // cout << "Added dataset " << SetName << endl; - } - else - { - if (localDataSetType[string(SetName)] == SetType) - { - localDataSetName[string(SetName)] += 1; - } - else - { - cerr << "WARNING: found same dataset (" << SetName << ")" << endl; - cerr << " with different type! Will be skipped!" << endl; - } - } - } - } - - if (parser.get("intersect-step-attributes")) - { - NumStepAttr = H5PartGetNumStepAttribs(H5InFile); - for (int m = 0; m < NumStepAttr; ++m) - { - H5PartGetStepAttribInfo(H5InFile, m, StepAttrName, MAX_LEN, &Type, &NumType); - // cout << "Found Step Attribute '" << StepAttrName << "' " << endl; - itlocalName = localStepAttribName.find(string(StepAttrName)); - if (itlocalName == localStepAttribName.end()) - { - localStepAttribName.insert(make_pair(string(StepAttrName), 1)); - localStepAttribType.insert(make_pair(string(StepAttrName), Type)); - localStepAttribNumType.insert(make_pair(string(StepAttrName), NumType)); - } - else - { - if (localStepAttribType[string(StepAttrName)] == Type) - { - if (localStepAttribNumType[string(StepAttrName)] == NumType) - { - localStepAttribName[string(StepAttrName)] += 1; - } - else - { - cerr << "WARNING: found same step attribute (" << StepAttrName << ") " << endl; - cerr << " with same type but different length! Will be skipped!" << endl; - } - } - else - { - cerr << "WARNING: found same step attribute (" << StepAttrName << ")" << endl; - cerr << " with different type! Will be skipped!" << endl; - } - } - } - } - } - - if (parser.get("intersect-datasets")) - { - - // exclude those datasets which do not occur in all steps in file i - for (itlocalName = localDataSetName.begin(), itlocalType = localDataSetType.begin(); itlocalName != localDataSetName.end(); itlocalName++, itlocalType++) - { - if (itlocalName->second != NumSteps) - { - cerr << "WARNING: dataset '" << itlocalName->first << "' in file " << InputFilenames[i] << " only found in " << itlocalName->second << " of " << NumSteps << " steps;" << endl; - cerr << " Skipping this dataset;" << endl; - localDataSetName.erase(itlocalName); - } - else - { - itName = DataSetName.find(itlocalName->first); - if (itName == DataSetName.end()) - { - DataSetName.insert(make_pair(itlocalName->first, 1)); - DataSetType.insert(make_pair(itlocalName->first, itlocalType->second)); - } - else - { - if (DataSetType[itlocalName->first] == itlocalType->second) - { - DataSetName[itlocalName->first] += 1; - } - else - { - cerr << "WARNING: found same dataset (" << itlocalName->first << ")" << endl; - cerr << " with different type! Will be skipped!" << endl; - } - } - } - } - } - - if (parser.get("intersect-step-attributes")) - { - // exclude those step attributes which do not occur in all steps in file i - itlocalType = localStepAttribType.begin(); - itlocalNumType = localStepAttribNumType.begin(); - for (itlocalName = localStepAttribName.begin(); itlocalName != localStepAttribName.end(); itlocalName++, itlocalType++, itlocalNumType++) - { - if (itlocalName->second != NumSteps){ - cerr << "WARNING: step attribute '" << itlocalName->first << "' in file " << InputFilenames[i] << " only found in " << itlocalName->second << " of " << NumSteps << " steps;" << endl; - cerr << " Skipping this step attribute;" << endl; - // localStepAttribName.erase(itlocalName); - // localStepAttribType.erase(itlocalType); - // localStepAttribNumType.erase(itlocalNumType); - } - else - { - itName = StepAttribName.find(itlocalName->first); - if (itName == StepAttribName.end()) - { - StepAttribName.insert( make_pair(itlocalName->first, 1)); - StepAttribType.insert( make_pair(itlocalName->first, itlocalType->second)); - StepAttribNumType.insert( make_pair(itlocalName->first, itlocalNumType->second)); - } - else - { - if (StepAttribType[itlocalName->first] == itlocalType->second) - { - if (StepAttribNumType[itlocalName->first] == itlocalNumType->second) - { - StepAttribName[itlocalName->first] += 1; - } - else - { - cerr << "WARNING: found same step attribute (" << itlocalName->first << ") " << endl; - cerr << " with same type but different length! Will be skipped!" << endl; - } - } - else - { - cerr << "WARNING: found same step attribute (" << itlocalName->first << ")" << endl; - cerr << " with different type! Will be skipped!" << endl; - } - } - } - } - } - - H5PartCloseFile(H5InFile); - } - } - - - if (parser.get("intersect-file-attributes")) - { - //erase all those file attributes which do not occur in all files - itType = FileAttribType.begin(); - itNumType = FileAttribNumType.begin(); - for (itName = FileAttribName.begin(); itName != FileAttribName.end(); itName++, itType++, itNumType++) - { - if (itName->second != effNumInput) - { - cerr << "WARNING: file attribute '" << itName->first << "' only found in " << itName->second << " of " << effNumInput << " input files;" << endl; - cerr << " skipping this attribute!" << endl; - FileAttribName.erase(itName); - FileAttribType.erase(itType); - FileAttribNumType.erase(itNumType); - } - } - - if (verbosity > 0) - { - cout << "found the following file attributes (intersection of all file attributes):" << endl; - for (itName = FileAttribName.begin(); itName != FileAttribName.end(); ++itName) - { - cout << "file attribute '" << itName->first << "'" << endl; - } - cout << endl; - } - } - - if (parser.get("intersect-datasets")) - { - //erase all those datasets which do not occur in all steps of all files - for (itName = DataSetName.begin(), itType = DataSetType.begin(); itName != DataSetName.end(); itName++, itType++) - { - if (itName->second != effNumInput) - { - cerr << "WARNING: dataset '" << itName->first << "' only found in " << itName->second << " of " << effNumInput << " input files;" << endl; - cerr << " skipping this data set!" << endl; - DataSetName.erase(itName); - DataSetType.erase(itType); - } - } - - if (verbosity > 0) - { - cout << "found the following data sets (intersection of all datasets):" << endl; - for (itName = DataSetName.begin(); itName != DataSetName.end(); itName++) - cout << "dataset '" << itName->first << "'" << endl; - cout << endl; - } - } - - if (parser.get("intersect-step-attributes")) - { - //erase all those step attributes which do not occur in all steps of all fiels - itType = StepAttribType.begin(); - itNumType = StepAttribNumType.begin(); - for (itName = StepAttribName.begin(); itName != StepAttribName.end(); itName++, itType++, itNumType++) - { - if (itName->second != effNumInput) - { - cerr << "WARNING: step attribute '" << itName->first << "' only found in " << itName->second << " of " << effNumInput << " input files;" << endl; - cerr << " skipping this attribute!" << endl; - StepAttribName.erase(itName); - StepAttribType.erase(itType); - StepAttribNumType.erase(itNumType); - } - } - - if (verbosity > 0) - { - cout << "found the following step attributes (intersection of all step attributes):" << endl; - for (itName = StepAttribName.begin(); itName != StepAttribName.end(); ++itName) - { - cout << "step attribute '" << itName->first << "'" << endl; - } - cout << endl; - } - } - - - H5OutFile = H5PartOpenFile(OutputFilename.c_str(), H5PART_WRITE); - if (H5OutFile == NULL) - { - cerr << "ABORT: could not open '" << OutputFilename << "' for writing!" << endl; - exit(1); - } - - FloatValues = new h5part_float64_t[maxNumParticles]; - IntegerValues = new h5part_int64_t[maxNumParticles]; - - // cout << "ready to write data " << maxNumParticles << endl; - for (int i = 0; i < effNumInput; ++i) - { - H5InFile = H5PartOpenFile(InputFilenames[i].c_str(), H5PART_READ); - - H5PartSetStep(H5InFile,from[i]); - H5PartSetStep(H5OutFile,effStep); - - if (parser.get("intersect-file-attributes")) - { - itType = FileAttribType.begin(); - itNumType = FileAttribNumType.begin(); - for (itName = FileAttribName.begin(); itName != FileAttribName.end(); itName++, itType++, itNumType++) - { - // cout << "writing file attribute " << itName->first << endl; - if (i == 0) - { -#ifdef USE_BOOST - rc = copyFileAttribute(H5InFile, H5OutFile, FileAttributes, itName->first, itType->second, itNumType->second); -#else - rc = copyFileAttribute(H5InFile, H5OutFile, itName->first, itType->second, itNumType->second); -#endif - } - else - { -#ifdef USE_BOOST - rc = copyFileToStepAttribute(H5InFile, H5OutFile, FileAttributes, itName->first, itType->second, itNumType->second); -#else - rc = copyFileToStepAttribute(H5InFile, H5OutFile, itName->first, itType->second, itNumType->second); -#endif - } - if (rc != H5PART_SUCCESS) - cerr << "WARNING: could not write file attribute '" << AttrName << "'" << endl; - } - // cout << "wrote file attributes" << endl; - } - else - { - h5part_int64_t NumFileAttr = H5PartGetNumFileAttribs(H5InFile); - // cout << NumFileAttr << " file attributes" << endl; - for (h5part_int64_t l = 0; l < NumFileAttr; ++l) - { - - H5PartGetFileAttribInfo(H5InFile, l, AttrName, MAX_LEN, &Type, &NumType); - // cout << "Found file attribute '" << AttrName << "'" << endl; - if (i == 0) - { -#ifdef USE_BOOST - rc = copyFileAttribute(H5InFile, H5OutFile, FileAttributes, string(AttrName), Type, NumType); -#else - rc = copyFileAttribute(H5InFile, H5OutFile, string(AttrName), Type, NumType); -#endif - } - else - { -#ifdef USE_BOOST - rc = copyFileToStepAttribute(H5InFile, H5OutFile, FileAttributes, string(AttrName), Type, NumType); -#else - rc = copyFileToStepAttribute(H5InFile, H5OutFile, string(AttrName), Type, NumType); -#endif - } - if (rc != H5PART_SUCCESS) - cerr << "WARNING: could not write file attribute '" << AttrName << "'" << endl; - } - } - - firstStepInput = true; - for (int l = from[i]; l <= to[i]; ++l, ++effStep) - { - if(!firstStepInput) - { - rc = H5PartSetStep(H5InFile, l); - if (rc != H5PART_SUCCESS) - { - cerr << "ABORT: could not change to step #" << l << " in input file '" << InputFilenames[i] << "'" << endl; - rc = H5PartCloseFile(H5InFile); - rc = H5PartCloseFile(H5OutFile); - exit(1); - } - rc = H5PartSetStep(H5OutFile, effStep); - if (rc != H5PART_SUCCESS) - { - cerr << "ABORT: could not change to step #" << effStep << " in output file '" << OutputFilename << "'" << endl; - rc = H5PartCloseFile(H5InFile); - rc = H5PartCloseFile(H5OutFile); - exit(1); - } - } - else - { - firstStepInput = false; - } - NumParticles = H5PartGetNumParticles(H5InFile); - rc = H5PartSetNumParticles(H5OutFile, NumParticles); - if (rc != H5PART_SUCCESS) - { - cerr << "ABORT: could not set the number of particles in output file '" << OutputFilename << "'" << endl; - rc = H5PartCloseFile(H5InFile); - rc = H5PartCloseFile(H5OutFile); - exit(1); - } - if (parser.get("intersect-step-attributes")) - { - itType = StepAttribType.begin(); - itNumType = StepAttribNumType.begin(); - for (itName = StepAttribName.begin(); itName != StepAttribName.end(); ++itName, ++itType, ++itNumType) - { - rc = copyStepAttribute(H5InFile, H5OutFile, itName->first, itType->second, itNumType->second); - if (rc != H5PART_SUCCESS) - cerr << "WARNING: could not write step attribute '" << itName->first << "'" << endl; - } - } - else - { - h5part_int64_t NumStepAttr = H5PartGetNumStepAttribs(H5InFile); - for (h5part_int64_t m = 0; m < NumStepAttr; ++m) - { - H5PartGetStepAttribInfo(H5InFile, m, StepAttrName, MAX_LEN, &Type, &NumType); - rc = copyStepAttribute(H5InFile, H5OutFile, string(StepAttrName), Type, NumType); - if (rc != H5PART_SUCCESS) - cerr << "WARNING: could not write step attribute '" << StepAttrName << "'" << endl; - } - } - - if (parser.get("intersect-datasets")) - { - - for (itType = DataSetType.begin(); itType != DataSetType.end(); ++itType) - { - rc = copyDataset(H5InFile, H5OutFile, itType->first, itType->second, FloatValues, IntegerValues); - if (rc != H5PART_SUCCESS) - cerr << "WARNING: could not write dataset '" << itType->first << "'" << endl; - } - } - else - { - h5part_int64_t NumDataSets = H5PartGetNumDatasets(H5InFile); - for (h5part_int64_t m = 0; m < NumDataSets; ++m) - { - H5PartGetDatasetInfo(H5InFile, m, SetName, MAX_LEN, &SetType, &SetNum); - rc = copyDataset(H5InFile, H5OutFile, string(SetName), SetType, FloatValues, IntegerValues); - if (rc != H5PART_SUCCESS) - cerr << "WARNING: could not write dataset '" << SetName << "'" << endl; - } - } - - } - rc = H5PartCloseFile(H5InFile); - } - rc = H5PartCloseFile(H5OutFile); - - if (isOutputInput) - { - rename(OutputFilename.c_str(), InputFilenames[OutputIsInput].c_str()); - } - - delete[] FloatValues; - delete[] IntegerValues; - delete[] InputFilenames; - delete[] from; - delete[] to; -} - -h5part_int64_t copyFileAttribute(H5PartFile* In, H5PartFile* Out, string AttrName, h5part_int64_t Type, h5part_int64_t Num) -{ - h5part_int64_t rc; - if (Type == H5T_NATIVE_DOUBLE) - { - void *Attrib = (double*)malloc(sizeof(double)*Num); - rc = H5PartReadFileAttrib(In, AttrName.c_str(), (double*)Attrib); - if (rc == H5PART_SUCCESS) - rc = H5PartWriteFileAttrib(Out, AttrName.c_str(), Type, (double*)Attrib, Num); - free(Attrib); - return rc; - } - else if (Type == H5T_NATIVE_CHAR) - { - void *Attrib = (char*)malloc(sizeof(char)*Num); - rc = H5PartReadFileAttrib(In, AttrName.c_str(), (char*)Attrib); - if (rc == H5PART_SUCCESS) - rc = H5PartWriteFileAttrib(Out, AttrName.c_str(), Type, (char*)Attrib, Num); - free(Attrib); - return rc; - } - else if (Type == H5T_NATIVE_INT64) - { - void *Attrib = (h5part_int64_t*)malloc(sizeof(h5part_int64_t)*Num); - rc = H5PartReadFileAttrib(In, AttrName.c_str(), (h5part_int64_t*)Attrib); - if (rc == H5PART_SUCCESS) - rc = H5PartWriteFileAttrib(Out, AttrName.c_str(), Type, (h5part_int64_t*)Attrib, Num); - free(Attrib); - return rc; - } - else - { - cerr << "WARNING: unknown type for file attribue " << AttrName << "! Skipping it. " << endl; - return H5PART_ERR_INVAL; - } -} - - -h5part_int64_t copyFileToStepAttribute(H5PartFile* In, H5PartFile* Out, string AttrName, h5part_int64_t Type, h5part_int64_t Num) -{ - h5part_int64_t rc; - if (Type == H5T_NATIVE_DOUBLE) - { - void *Attrib = (double*)malloc(sizeof(double)*Num); - rc = H5PartReadFileAttrib(In, AttrName.c_str(), (double*)Attrib); - if (rc == H5PART_SUCCESS) - rc = H5PartWriteStepAttrib(Out, AttrName.c_str(), Type, (double*)Attrib, Num); - free(Attrib); - return rc; - } - else if (Type == H5T_NATIVE_CHAR) - { - void *Attrib = (char*)malloc(sizeof(char)*Num); - rc = H5PartReadFileAttrib(In, AttrName.c_str(), (char*)Attrib); - if (rc == H5PART_SUCCESS) - rc = H5PartWriteStepAttrib(Out, AttrName.c_str(), Type, (char*)Attrib, Num); - free(Attrib); - return rc; - } - else if (Type == H5T_NATIVE_INT64) - { - void *Attrib = (h5part_int64_t*)malloc(sizeof(h5part_int64_t)*Num); - rc = H5PartReadFileAttrib(In, AttrName.c_str(), (h5part_int64_t*)Attrib); - if (rc == H5PART_SUCCESS) - rc = H5PartWriteStepAttrib(Out, AttrName.c_str(), Type, (h5part_int64_t*)Attrib, Num); - free(Attrib); - return rc; - } - else - { - cerr << "WARNING: unknown type for file attribue " << AttrName << "! Skipping it. " << endl; - return H5PART_ERR_INVAL; - } -} - -h5part_int64_t copyStepAttribute(H5PartFile* In, H5PartFile* Out, string AttrName, h5part_int64_t Type, h5part_int64_t Num) -{ - h5part_int64_t rc; - if (Type == H5T_NATIVE_DOUBLE) - { - void* Attrib = (double*)malloc(sizeof(double)*Num);; - rc = H5PartReadStepAttrib(In, AttrName.c_str(), (double*)Attrib); - if (rc == H5PART_SUCCESS) - rc = H5PartWriteStepAttrib(Out, AttrName.c_str(), Type, (double*)Attrib, Num); - free(Attrib); - return rc; - } - else if (Type == H5T_NATIVE_CHAR) - { - void* Attrib = (char*)malloc(sizeof(char)*Num);; - rc = H5PartReadStepAttrib(In, AttrName.c_str(), (char*)Attrib); - if (rc == H5PART_SUCCESS) - rc = H5PartWriteStepAttrib(Out, AttrName.c_str(), Type, (char*)Attrib, Num); - free(Attrib); - return rc; - } - else if (Type == H5T_NATIVE_INT64) - { - void* Attrib = (h5part_int64_t*)malloc(sizeof(h5part_int64_t)*Num); - rc = H5PartReadStepAttrib(In, AttrName.c_str(), (h5part_int64_t*)Attrib); - if (rc == H5PART_SUCCESS) - rc = H5PartWriteStepAttrib(Out, AttrName.c_str(), Type, (h5part_int64_t*)Attrib, Num); - free(Attrib); - return rc; - } - else - { - cerr << "WARNING: unknown type for step attribute " << AttrName << "! Skipping it." << endl; - return H5PART_ERR_INVAL; - } -} - - -h5part_int64_t copyDataset(H5PartFile* In, H5PartFile* Out, string SetName, h5part_int64_t Type, h5part_float64_t* FloatArray, h5part_int64_t* IntegerArray) -{ - h5part_int64_t rc; - if (Type == H5T_NATIVE_DOUBLE) - { - rc = H5PartReadDataFloat64(In, SetName.c_str(), FloatArray); - if (rc == H5PART_SUCCESS) - rc = H5PartWriteDataFloat64(Out, SetName.c_str(), FloatArray); - return rc; - } - else if (Type == H5T_NATIVE_INT64) - { - rc = H5PartReadDataInt64(In, SetName.c_str(), IntegerArray); - if (rc == H5PART_SUCCESS) - rc = H5PartWriteDataInt64(Out, SetName.c_str(), IntegerArray); - return rc; - } - else - { - cerr << "WARNING: unknown type for dataset " << SetName << "! Skipping it." << endl; - return H5PART_ERR_INVAL; - } -} - -#ifdef USE_BOOST -h5part_int64_t copyFileAttribute(H5PartFile* In, H5PartFile* Out, StringAnyValueMap &FileAttributes, string AttrName, h5part_int64_t Type, h5part_int64_t Num) -{ - h5part_int64_t rc; - if (Type == H5T_NATIVE_DOUBLE) - { - void *Attrib = (double*)malloc(sizeof(double)*Num); - rc = H5PartReadFileAttrib(In, AttrName.c_str(), (double*)Attrib); - if (rc == H5PART_SUCCESS) - rc = H5PartWriteFileAttrib(Out, AttrName.c_str(), Type, (double*)Attrib, Num); - if (rc == H5PART_SUCCESS) - FileAttributes.insert(make_pair(AttrName,boost::any(*(double*)Attrib))); - free(Attrib); - return rc; - } - else if (Type == H5T_NATIVE_CHAR) - { - void *Attrib = (char*)malloc(sizeof(char)*Num); - rc = H5PartReadFileAttrib(In, AttrName.c_str(), (char*)Attrib); - if (rc == H5PART_SUCCESS) - rc = H5PartWriteFileAttrib(Out, AttrName.c_str(), Type, (char*)Attrib, Num); - if (rc == H5PART_SUCCESS) - FileAttributes.insert(make_pair(AttrName,boost::any(string((char*)Attrib)))); - free(Attrib); - return rc; - } - else if (Type == H5T_NATIVE_INT64) - { - void *Attrib = (h5part_int64_t*)malloc(sizeof(h5part_int64_t)*Num); - rc = H5PartReadFileAttrib(In, AttrName.c_str(), (h5part_int64_t*)Attrib); - if (rc == H5PART_SUCCESS) - rc = H5PartWriteFileAttrib(Out, AttrName.c_str(), Type, (h5part_int64_t*)Attrib, Num); - if (rc == H5PART_SUCCESS) - FileAttributes.insert(make_pair(AttrName,boost::any(*(h5part_int64_t*)Attrib))); - free(Attrib); - return rc; - } - else - { - cerr << "WARNING: unknown type for file attribue " << AttrName << "! Skipping it. " << endl; - return H5PART_ERR_INVAL; - } -} - - -h5part_int64_t copyFileToStepAttribute(H5PartFile* In, H5PartFile* Out, StringAnyValueMap &FileAttributes, string AttrName, h5part_int64_t Type, h5part_int64_t Num) -{ - h5part_int64_t rc; - if (Type == H5T_NATIVE_DOUBLE) - { - void *Attrib = (double*)malloc(sizeof(double)*Num); - rc = H5PartReadFileAttrib(In, AttrName.c_str(), (double*)Attrib); - if (rc == H5PART_SUCCESS) - { - if (FileAttributes.find(AttrName) == FileAttributes.end()) - { - rc = H5PartWriteStepAttrib(Out, AttrName.c_str(), Type, (double*)Attrib, Num); - if (rc == H5PART_SUCCESS) - FileAttributes.insert(make_pair(AttrName,boost::any(*(double*)Attrib))); - } - else if(any_cast(FileAttributes[AttrName]) != *(double*)Attrib) - { - rc = H5PartWriteStepAttrib(Out, (AttrName + " changed to").c_str(), Type, (double*)Attrib, Num); - if (rc == H5PART_SUCCESS) - FileAttributes[AttrName] = boost::any(*(double*)Attrib); - } - } - free(Attrib); - return rc; - } - else if (Type == H5T_NATIVE_CHAR) - { - void *Attrib = (char*)malloc(sizeof(char)*Num); - rc = H5PartReadFileAttrib(In, AttrName.c_str(), (char*)Attrib); - if (rc == H5PART_SUCCESS) - { - if (FileAttributes.find(AttrName) == FileAttributes.end()) - { - rc = H5PartWriteStepAttrib(Out, AttrName.c_str(), Type, (char*)Attrib, Num); - if (rc == H5PART_SUCCESS) - FileAttributes.insert(make_pair(AttrName,boost::any(string((char*)Attrib)))); - } - else if(strcmp((any_cast(FileAttributes[AttrName])).c_str(),(char*)Attrib) != 0) - { - rc = H5PartWriteStepAttrib(Out, (AttrName + " changed to").c_str(), Type, (char*)Attrib, Num); - if (rc == H5PART_SUCCESS) - FileAttributes[AttrName] = boost::any(string((char*)Attrib)); - } - } - free(Attrib); - return rc; - } - else if (Type == H5T_NATIVE_INT64) - { - void *Attrib = (h5part_int64_t*)malloc(sizeof(h5part_int64_t)*Num); - rc = H5PartReadFileAttrib(In, AttrName.c_str(), (h5part_int64_t*)Attrib); - if (rc == H5PART_SUCCESS) - { - if (FileAttributes.find(AttrName) == FileAttributes.end()) - { - rc = H5PartWriteStepAttrib(Out, AttrName.c_str(), Type, (h5part_int64_t*)Attrib, Num); - FileAttributes.insert(make_pair(AttrName,boost::any((h5part_int64_t*)Attrib))); - } - else if(any_cast(FileAttributes[AttrName]) != *(h5part_int64_t*)Attrib) - { - rc = H5PartWriteStepAttrib(Out, (AttrName + " changed to").c_str(), Type, (h5part_int64_t*)Attrib, Num); - if (rc == H5PART_SUCCESS) - FileAttributes[AttrName] = boost::any((h5part_int64_t*)Attrib); - } - } - free(Attrib); - return rc; - } - else - { - cerr << "WARNING: unknown type for file attribue " << AttrName << "! Skipping it. " << endl; - return H5PART_ERR_INVAL; - } -} -#endif diff --git a/tools/H5PartMerge/make.sh b/tools/H5PartMerge/make.sh deleted file mode 100755 index 43fbf4a..0000000 --- a/tools/H5PartMerge/make.sh +++ /dev/null @@ -1,3 +0,0 @@ -g++ -c -g optparse.cpp -g++ -c -g H5merge.cpp -I$HOME/include -DUSE_BOOST -g++ -g -o H5merge0.1 H5merge.o optparse.o -L$HOME/lib -lH5Part -lhdf5 -lz -lm diff --git a/tools/H5PartMerge/optparse.cpp b/tools/H5PartMerge/optparse.cpp deleted file mode 100644 index 5ab156e..0000000 --- a/tools/H5PartMerge/optparse.cpp +++ /dev/null @@ -1,309 +0,0 @@ -/* - * Implementation of optparse.h - * - * Roman Geus, 2005 - * - */ - -#include -#include -#include "optparse.h" - -using namespace std; - -namespace optparse { - -/********************** Option **********************/ - -Option::Option (string shrt, string lng, string dest, - string hlp, action_t act, string dfault, type_t type, string allowed_args) - : action (act), - shrt_flag (shrt), - lng_flag (lng), - help (hlp), - destination (dest), - dfault_(dfault), - type_(type), - allowed_args_(allowed_args) -{} - -Option::~Option () {} - -bool -Option::is_allowed(std::string argument) { - // Test type - // FIXME: implement that - - // Test allowed values - if (allowed_args_ == "") - return true; - - size_t pos_begin = 0; - do { - size_t pos_comma = allowed_args_.find(',', pos_begin); - if (pos_comma == string::npos) - pos_comma = allowed_args_.size(); - if (allowed_args_.substr(pos_begin, pos_comma-pos_begin) == argument) - return true; - pos_begin = pos_comma + 1; - } while(pos_begin < allowed_args_.size()); - return false; -} - -/******************** OptionParser *******************/ - -OptionParser::OptionParser (string usage) - : use_msg (usage) -{ } - -OptionParser::~OptionParser () {} - -void -OptionParser::add_option(string shrt_flag, string lng_flag, string destination, - string help, action_t act, type_t type, string dfault, - string allowed_values) -{ - Option option(shrt_flag, lng_flag, destination, help, act, dfault, type, allowed_values); - - /* Add the option to our list of options. */ - opts.push_back(option); - - /* Set the default value for this option, this not only allows you to - * set default values but insures that every option's destination will - * be in our dictionary, even if the value is only "". - */ - set_option(option, dfault); -} - -string OptionParser::get_option(std::string option_name) { - string arg(options[option_name]); - size_t colon_pos = arg.find(':'); - return arg.substr(0, colon_pos); -} - -void -OptionParser::parse_args (int argc, char **argv) { - /* Walk through the arguments and sort them into options - * or arguments. - */ - for (int i = 1; i < argc; i++) { - /* If we start with a '-' we're probably a pair - * so we need to figure out which option it is. find_opt() is - * where the real work is done. - */ - if (argv[i][0] == '-') - if (argv[i][1] == '-') - find_opt_long(argc, argv, i); - else - find_opt_short(argc, argv, i); - - /* If we're looking at an argument (i.e. a value with no flag who's - * meaning is determined by position) just append it into the - * arguments list. - */ - else - arguments.insert(arguments.end(), argv[i]); - } -} - -void -OptionParser::help (ostream& os) { - const size_t WORD_WRAP = 50; // max width of last column - - // Determine column width for short options - size_t shrt_flag_max_len = 0; - for (size_t i=0; i < opts.size(); ++ i) { - stringstream buf; - buf << opts[i].shrt_flag; - if (opts[i].shrt_flag != "" && opts[i].action == STORE) - buf << " " << type2string(opts[i].type_); - if (buf.str().size() > shrt_flag_max_len) - shrt_flag_max_len = buf.str().size(); - } - - // Determine column width for long options - size_t lng_flag_max_len = 0; - for (size_t i=0; i < opts.size(); ++ i) { - stringstream buf; - buf << opts[i].lng_flag; - if (opts[i].action == STORE) - buf << "=" << type2string(opts[i].type_); - if (buf.str().size() > lng_flag_max_len) - lng_flag_max_len = buf.str().size(); - } - - os << use_msg << endl; - for (size_t i=0; i < opts.size(); ++ i) { - stringstream line; - line << " "; - - // short option column - stringstream shrt_buf; - shrt_buf << opts[i].shrt_flag; - if (opts[i].shrt_flag != "" && opts[i].action == STORE) - shrt_buf << " " << type2string(opts[i].type_); - line << ' ' << shrt_buf.str(); - for (size_t k = 0; k < shrt_flag_max_len-shrt_buf.str().size()+2; ++ k) - line << ' '; - - // long option column - stringstream buf; - buf << opts[i].lng_flag; - if (opts[i].action == STORE) - buf << "=" << type2string(opts[i].type_); - line << buf.str(); - for (size_t k = 0; k < lng_flag_max_len-buf.str().size()+4; ++ k) - line << ' '; - - // help column - os << line.str(); - size_t help_col = line.str().size(); - line.str(""); - - line << opts[i].help; - bool is_allowed = opts[i].allowed_args_ != ""; - bool is_default = opts[i].action == STORE && opts[i].dfault_ != ""; - if (is_allowed || is_default) { - line << " ("; - if (is_allowed) { - line << "possible values="; - size_t pos_begin = 0; - size_t pos_comma = opts[i].allowed_args_.find(',', pos_begin); - while (pos_comma != string::npos) { - line << '\'' << opts[i].allowed_args_.substr(pos_begin, pos_comma-pos_begin) << "\',"; - pos_begin = pos_comma + 1; - pos_comma = opts[i].allowed_args_.find(',', pos_begin); - } - line << '\'' << opts[i].allowed_args_.substr(pos_begin) << '\''; - if (is_default) - line << ", "; - } - if (is_default) - line << "default=\'" << opts[i].dfault_ << "\'"; - line << ')'; - } - - // split over several lines - size_t begin_pos = 0; - size_t last_pos = 0; - size_t next_pos; - - do { - next_pos = line.str().find_first_of(" ,", last_pos+1); - if (next_pos == string::npos) - next_pos = line.str().size()-1; - if (last_pos == line.str().size()-1 || (next_pos+1 - begin_pos > WORD_WRAP && last_pos > begin_pos)) { - if (begin_pos != 0) - for (size_t k = 0; k < help_col+2; ++ k) - os << ' '; - os << line.str().substr(begin_pos, last_pos+1 - begin_pos) << endl; - begin_pos = last_pos+1; - last_pos = begin_pos; - } else - last_pos = next_pos; - } while (begin_pos != line.str().size()); - } - } - -void -OptionParser::find_opt_short(int argc, char **argv, int &index) { - /* Step through our list of known options. */ - for (size_t i = 0; i < opts.size(); i++) { - /* Uses the overridden == operator for the Options class - * to compare argv[index] to the flags of each Option. - */ - if (opts[i].shrt_flag == (string)argv[index]) { - switch (opts[i].action) { - case STORE_FALSE: - set_option(opts[i], "0"); - break; - case STORE_TRUE: - set_option(opts[i], "1"); - break; - case STORE: - /* Set the value and return if we've found a match. */ - if (index >= argc-1) - throw OptionError(argv[index], "Missing option argument"); - set_option(opts[i], argv[index+1]); - index++; - break; - default: - break; - }; - return; - } - } - - /* If we haven't found a match this is not a known argument. */ - throw OptionError(argv[index], "Unknown option"); -} - -void -OptionParser::find_opt_long(int argc, char **argv, int &index) { - // Split option and argument at "=" - string option; - string argument; - string arg_str(argv[index]); - size_t equal_pos = arg_str.find('='); - if (equal_pos != string::npos) { - option = arg_str.substr(0, equal_pos); - argument = arg_str.substr(equal_pos+1, string::npos); - } else - option = arg_str; - - /* Step through our list of known options. */ - for (size_t i = 0; i < opts.size(); i++) { - if (opts[i].lng_flag == option) { - switch (opts[i].action) { - case STORE_FALSE: - if (argument != "") - throw OptionError(option, "No argument expected for this option"); - set_option(opts[i], "0"); - break; - case STORE_TRUE: - if (argument != "") - throw OptionError(option, "No argument expected for this option"); - set_option(opts[i], "1"); - break; - case STORE: - if (argument == "") - throw OptionError(option, "Missing option argument"); - set_option(opts[i], argument); - break; - default: - break; - }; - return; - } - } - - /* If we haven't found a match this is not a known argument. */ - throw OptionError(option, "Unknown option"); -} - -void OptionParser::set_option(Option& option, std::string argument) { - if (option.is_allowed(argument)) - options[option.destination] = argument; - else - throw OptionError("", "Invalid argument for option"); -} - -string OptionParser::type2string(type_t type) { - if (type == STRING) - return string("STRING"); - else if (type == DOUBLE) - return string("DOUBLE"); - else if (type == INT) - return string("INT"); - else if (type == BOOL) - return string("BOOL"); - else - return ""; -} - -template<> bool OptionParser::get(std::string option_name) -{ - return get_option(option_name) == "1"; -} - -} // namespace optparse diff --git a/tools/H5PartMerge/optparse.h b/tools/H5PartMerge/optparse.h deleted file mode 100644 index 7183673..0000000 --- a/tools/H5PartMerge/optparse.h +++ /dev/null @@ -1,180 +0,0 @@ -/* - * optparse.h - * - * An option parser for C++ modeled after the optparse Python - * module. Create an instance of OptionParser in your program - * and you can add options to it then call the method - * parse_args with argc and argv and it will parse them. The - * '-h' and '--help' options are built in, they print the - * usage message. - * - * W. Evan Sheehan - * - */ - -#ifndef OPTPARSE_H -#define OPTPARSE_H - -#include -#include -#include -#include -#include - -namespace optparse { - -/** - * Action type. - * Use this type to determine what we're storing, naming - * convention is the same as the optparse python module. - * Even with STORE_FALSE and STORE_TRUE the values are - * going to be stored as strings, false is "0" true is "1" - * so you can just atoi() the value and use that for tests. - */ -typedef enum {STORE_FALSE=0, STORE_TRUE, STORE} action_t; - -/** - * Option argument type. - * Defines expected option argument type. - */ -typedef enum {STRING=0, BOOL, INT, DOUBLE} type_t; - -/** Option for OptionParser */ -class Option { -public: - Option (std::string shrt, std::string lng, std::string dest, - std::string hlp, action_t act, std::string dfault, type_t type, - std::string allowed_args); - ~Option (); - - /** - * Validate option argument. - * Test if argument is valid for the option. The argument must be valid w.r.t. - * to type_ and allowed_values_. - * @param argument Argument to be tested. - * @return true if argument is valid. - */ - bool is_allowed(std::string argument); - - action_t action; // define what we store - std::string shrt_flag; // short flag, something like -o - std::string lng_flag; // long flag, something like --outfile - std::string help; // help message about the option - std::string destination; // the key used to store this option in the parser. - /** - * Default value. An empty string means no default value exist. - */ - std::string dfault_; - /** - * Expected type the argument of this option should have. - * Only relevant for STORE action. - * Used for generating the usage string. - */ - type_t type_; - std::string allowed_args_; //!< Comma-separated list of allowed option arguments. -}; - -class OptionError : public std::runtime_error { -public: - OptionError(std::string option, std::string error_msg) - : std::runtime_error("") { - std::ostringstream str; - str << "OptionParser error: option: " << option << ", cause: " << error_msg; - msg_ = str.str(); - } - virtual ~OptionError() throw() {} - /** - * Human-readable error message. - * @return Pointer to error message. - */ - virtual const char* what() const throw() { return msg_.c_str(); } -protected: - std::string msg_; -}; - -/** Option parser. */ -class OptionParser { -public: - OptionParser (std::string usage=""); - virtual ~OptionParser (); - - /** - * Add an option to the parser. - * @param shrt_flag Short option name, like e.g. "-q". - * @param lng_flag Long option name, like e.g. "--quiet" - * @param destination Key under which the option argument is stored in the dictionary. - * @param help Help string for generating the usage info. - * @param act Action, one of STORE, STORE_TRUE, STORE_FALSE. - * @param type Type info of the expected option argument. One of INT, DOUBLE, STRING, BOOL. - * @param dfault Default value. Value stored in the dictionary if the option is not given. - * @param allowed_values List of possible option values. - * A string of comma-separated allowed values. An empty string means - * that any value is allowed. - */ - void add_option (std::string shrt_flag, std::string lng_flag, - std::string destination, std::string help="", action_t act=STORE, - type_t type=STRING, std::string dfault="", - std::string allowed_values=""); - - /** - * Get option argument. - * @param option_name Name of option, as given in "destination" parameter of "add_option". - * @return Option argument with type appendix removed. - */ - std::string get_option(std::string option_name); - template T get(std::string option_name); - /* Parse the commandline args. */ - void parse_args (int argc, char **argv); - /** - * Write usage info to stream. - * The usage info includes a formatted list of all options the parser knows about, - * including the help string, expected argument type and default value. - * @param os Output stream the usage info is written to. - */ - void help (std::ostream& os); - /** - * Convert type_t type to human-readable string. - * This is used for generating the usage string and also in - * TypeOptionParser to encode the argument type in the options dictionary. - * @see help - * @param type Type. - * @return Converted string. - */ - std::string type2string(type_t type); - /** - * Type of "options" dictionary. - */ - typedef std::map options_type; - options_type options; //!< Dictionary of options. Use options[key] to access. - std::vector arguments; //!< List of positional arguments. -protected: - /** - * Set option in dictionary. - * Function the parser uses to store an option argument or a default value in - * options dictionary. Can be overridden in a subclass to store additional info. - * @param option Option object. - * @param argument Option argument to store. - */ - virtual void set_option(Option& option, std::string argument); - -private: - std::string use_msg; //!< Usage message. - std::vector