diff options
Diffstat (limited to 'Skin++/src')
| -rwxr-xr-x | Skin++/src/Clcm.cxx | 1308 | ||||
| -rwxr-xr-x | Skin++/src/Clcm.hxx | 706 | ||||
| -rwxr-xr-x | Skin++/src/Cle2000.cxx | 104 | ||||
| -rwxr-xr-x | Skin++/src/Cle2000.hxx | 96 | ||||
| -rwxr-xr-x | Skin++/src/Cle2000Exception.cxx | 22 | ||||
| -rwxr-xr-x | Skin++/src/Cle2000Exception.hxx | 22 | ||||
| -rwxr-xr-x | Skin++/src/LCMexception.cxx | 22 | ||||
| -rwxr-xr-x | Skin++/src/LCMexception.hxx | 22 | ||||
| -rwxr-xr-x | Skin++/src/Lifo.cxx | 691 | ||||
| -rwxr-xr-x | Skin++/src/Lifo.hxx | 373 | ||||
| -rwxr-xr-x | Skin++/src/LifoException.cxx | 22 | ||||
| -rwxr-xr-x | Skin++/src/LifoException.hxx | 22 | ||||
| -rwxr-xr-x | Skin++/src/Makefile | 182 | ||||
| -rwxr-xr-x | Skin++/src/Skin++.cxx | 80 |
14 files changed, 3672 insertions, 0 deletions
diff --git a/Skin++/src/Clcm.cxx b/Skin++/src/Clcm.cxx new file mode 100755 index 0000000..4ea27ca --- /dev/null +++ b/Skin++/src/Clcm.cxx @@ -0,0 +1,1308 @@ + +/*****************************************/ +/* C++ LCM OBJECT WRAPPER */ +/* AUTHOR: A. HEBERT ; 2024/08/04 */ +/*****************************************/ + +/* +Copyright (C) 2010 Ecole Polytechnique de Montreal + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. +*/ + +#include "Clcm.hxx" + +using namespace std; +using namespace ganlib; +static ostringstream hsmg; + +/* abort condition setting */ +void xabort_c(char *msg){ + cout << "Clcm xabort called: " << string(msg) << endl; + throw LCMexception(msg); +} + +ganlib::Clcm::Clcm(const string stype, const string myName, const string myPath) { + cout << "New Clcm object called '" << myName << "'" << endl; + this->root = this; + this->global_list = new vector<AnyPtr>; + this->isroot = true; + this->version = 4; + bool l_import = false; + bool l_exists = false; + int_32 imode=0; + if (stype == "LCM") { + this->objtype = 1; + } else if (stype == "XSM") { + DIR *dp; + struct dirent *dirp; + this->objtype = 2; + vector<string> names = vector<string>(); + if((dp = opendir(myPath.c_str())) == NULL) { + hsmg << "no XSM file found (missing directory name: '" << myPath << ")'" << endl; + throw LCMexception(hsmg.str()); + } + while ((dirp = readdir(dp)) != NULL) { + names.push_back(string(dirp->d_name)); + } + closedir(dp); + for (size_t i=0; i<names.size(); i++) { + if (names[i] == myName) l_exists = true; + } + } else if (stype == "BINARY") { + this->objtype = 3; + } else if (stype == "ASCII") { + this->objtype = 4; + } else if (stype == "DA") { + this->objtype = 5; + } else if (stype == "LCM_IMP_BINARY") { + imode = 1; + this->objtype = 1; + l_import = true; + } else if (stype == "XSM_IMP_BINARY") { + imode = 1; + this->objtype = 2; + l_import = true; + } else if (stype == "LCM_IMP_ASCII") { + imode = 2; + this->objtype = 1; + l_import = true; + } else if (stype == "XSM_IMP_ASCII") { + imode = 2; + this->objtype = 2; + l_import = true; + } else if (stype == "LCM_IMP_ASCII_V3") { + imode = 2; + this->objtype = 1; + this->version = 3; + l_import = true; + } else { + throw LCMexception("invalid type: '" + stype + "'"); + } + this->access = 0; + this->name = myName; + this->path = myPath; + this->addr = NULL; + this->lrda = 128; + try { + if (l_exists) { + this->addr = NULL; + cout << "XSM file " << path << myName << " already exists\n"; + this->open("READ-ONLY"); + this->access = 2; + } else { + this->open("NEW"); + this->access = 1; + } + } catch(...) { + throw LCMexception("Exception catched by new(1)"); + } + if (this->objtype <= 2) { + this->nammy = "/"; + this->empty = true; + this->ilong = -1; + } + if (l_import) { + this->empty = false; + this->untoutched = false; + try { + DIR *dp; + struct dirent *dirp; + vector<string> names = vector<string>(); + if((dp = opendir(myPath.c_str())) == NULL) { + hsmg << "no ASCII file found (missing directory name: '" << myPath << ")'" << endl; + throw LCMexception(hsmg.str()); + } + while ((dirp = readdir(dp)) != NULL) { + names.push_back(string(dirp->d_name)); + } + closedir(dp); + for (size_t i=0; i<names.size(); i++) { + string::size_type loc = names[i].find("_"); + if( loc != string::npos ) { + string fileName = names[i].substr(loc, string::npos); + if (fileName == "_"+this->name) { + FILE *file; + file = fopen((myPath+names[i]).c_str(), "r"); + if (this->version == 4) { + lcmexp_c(&(this->addr), 0, file, imode, 2); + } + else { + lcmexpv3_c(&(this->addr), 0, file, imode, 2); + } + fclose(file); + return; + } + } + } + // Modified R. Chambon 09/2011 + for (size_t i=0; i<names.size(); i++) { + if (myName.compare(names[i]) == 0) { + FILE *file; + file = fopen((myPath+names[i]).c_str(), "r"); + if (this->version == 4) { + lcmexp_c(&(this->addr), 0, file, imode, 2); + } + else { + lcmexpv3_c(&(this->addr), 0, file, imode, 2); + } + fclose(file); + return; + } + } + // + hsmg << "File '" << "_" << this->name << "' not found in '" << myPath <<"'"; + throw LCMexception(hsmg.str()); + } catch(...) { + throw LCMexception("Exception catched by new(2)"); + } + } +} + +ganlib::Clcm::Clcm(lcm *daughter, Clcm *root, const int_32 type, const string name, const int_32 ilong, const string key) { + this->global_list = root->global_list; + this->root = root; + this->addr = daughter; + this->access = 1; + this->name = name; + this->path = "./"; + this->nammy = key; + this->empty = true; + this->ilong = ilong; + this->objtype = type; + this->untoutched = false; + this->isroot = false; + this->version = root->version; +} + +ganlib::Clcm::Clcm(lcm *myLcm, const int_32 type, const int_32 access, const string OSname) { + this->root = this; + this->global_list = new vector<AnyPtr>; + this->isroot = false; + this->version = 4; + this->addr = myLcm; + this->access = access; + this->ilong = -1; + this->objtype = type-2; + this->empty = false; + this->name = OSname; + this->nammy = "/"; + this->path = ""; + this->untoutched = true; +} + +ganlib::Clcm::Clcm(const string stype, ClcmPtr myClcm) { + if (myClcm->objtype > 2) throw LCMexception("copy constructor not available for file objects"); + if (stype == "LCM") { + this->objtype = 1; + } else if (stype == "XSM") { + this->objtype = 2; + } + bool lopen = true; + if (myClcm->access == 0) { + lopen = false; + myClcm->open("READ-ONLY"); + } + this->version = root->version; + this->name = myClcm->name + ".bis"; + cout << "New Clcm object (clone) called '" << this->name << "'" << endl; + this->open("NEW"); + this->access = 1; + lcm *myLcm = myClcm->addr; + lcmequ_c(&myLcm, &(this->addr)); + this->root = this; + this->global_list = new vector<AnyPtr>; + this->isroot = true; + this->path = myClcm->path; + this->lrda = myClcm->lrda; + if (!lopen) { + myClcm->close("KEEP"); + this->close("KEEP"); + } +} + +ganlib::Clcm::~Clcm() { + if (this->isroot) { + cout << "Clcm root destructor called. LCM object=" << this->name << endl; + if ((this->addr != NULL) & (this->access == 1)) { + cout << "Destroy object " << this->name << endl; + this->close("DESTROY"); + } else if ((this->addr != NULL) & (this->access == 2)) { + cout << "Keep object " << this->name << endl; + this->close("KEEP"); + } + if (this->global_list != NULL) delete this->global_list; + } +} + +ostream & ganlib::operator<<(ostream &s, ClcmPtr myClcm) { + if (myClcm->objtype > 2) throw LCMexception("operator<< not available for file objects"); + FILE *file = fopen("_dummy.txt", "w"); + if (file == NULL) { + throw LCMexception("fopen failure in operator<<. file=_dummy.txt"); + } + lcmexp_c(&(myClcm->addr), 0, file, 2, 1); + fclose(file); + ifstream ifs ( "_dummy.txt" , ifstream::in ); + while (ifs.good()) s << (char) ifs.get(); + ifs.close(); + if( remove("_dummy.txt") != 0 ) { + throw LCMexception("Error deleting file after <<: _dummy.txt"); + } + return s; +} + +void ganlib::Clcm::expor(const string stype) { + this->expor(stype, "_"+this->name); +} + +void ganlib::Clcm::expor(const string stype, const string new_name) { + if (this->objtype > 2) throw LCMexception("expor not available for file objects"); + int_32 imode; + if (stype == "BINARY") { + imode = 1; + } else if (stype == "ASCII") { + imode = 2; + } else { + throw LCMexception("invalid type: '" + stype + "'"); + } + size_t found=new_name.find("_"); + if (found == string::npos) { + throw LCMexception("Export file name ("+new_name+") must contains _"); + } + FILE *file = fopen(new_name.c_str(), "w"); + if (file == NULL) { + throw LCMexception("fopen failure in expor(). file="+new_name); + } + lcmexp_c(&(this->addr), 0, file, imode, 1); + fclose(file); +} + +void ganlib::Clcm::except() { + throw LCMexception("Programmer-triggered exception"); +} + +string ganlib::Clcm::getName() throw() { + return this->name; +} + +string ganlib::Clcm::getPath() throw() { + return this->path; +} + +int_32 ganlib::Clcm::getType() throw() { + return this->objtype; +} + +int_32 ganlib::Clcm::getLength() { + char namlcm[73], nammy[13]; + int_32 empty, ilong, lcml, access; + if (this->objtype > 2) throw LCMexception("getLength not available for file objects"); + lcminf_c(&(this->addr), namlcm, nammy, &empty, &ilong, &lcml, &access); + return ilong; +} + +string ganlib::Clcm::getDirectory() { + char namlcm[73], nammy[13]; + int_32 empty, ilong, lcml, access; + if (this->objtype > 2) throw LCMexception("getDirectory not available for file objects"); + lcminf_c(&(this->addr), namlcm, nammy, &empty, &ilong, &lcml, &access); + return nammy; +} + +int_32 ganlib::Clcm::getAccess() { + char namlcm[73], nammy[13]; + int_32 empty, ilong, lcml; + if (this->objtype <= 2) { + lcminf_c(&(this->addr), namlcm, nammy, &empty, &ilong, &lcml, &(this->access)); + } + return this->access; +} + +int_32 ganlib::Clcm::getLrda() throw() { + return this->lrda; +} + +int_32 ganlib::Clcm::getVersion() throw() { + return this->version; +} + +bool ganlib::Clcm::isEmpty() { + char namlcm[73], nammy[13]; + int_32 empty, ilong, lcml, access; + if (this->objtype > 2) throw LCMexception("isEmpty not available for file objects"); + lcminf_c(&(this->addr), namlcm, nammy, &empty, &ilong, &lcml, &access); + return empty; +} + +bool ganlib::Clcm::isNew() throw() { + return this->untoutched; +} + +void ganlib::Clcm::open(const string saccess) { + if (this->access != 0) { + throw LCMexception("the object " + this->name + " is already open"); + } + if (saccess == "NEW") { + this->untoutched = true; + } else if (saccess == "READ/WRITE") { + if ((this->addr == NULL)&(this->objtype == 1)) { + throw LCMexception("the object " + this->name + " is destroyed(1)"); + } + this->access = 1; + this->untoutched = false; + } else if (saccess == "READ-ONLY") { + if ((this->addr == NULL)&(this->objtype == 1)) { + throw LCMexception("the object " + this->name + " is destroyed(2)"); + } + this->access = 2; + this->untoutched = false; + } else { + throw LCMexception("invalid access: '" + saccess + "'"); + } + if (this->objtype == 1) { + try { + lcmop_c(&(this->addr), (char *)(this->name).c_str(), this->access, this->objtype, 99); + } catch(...) { + throw LCMexception("Exception catched by open (1)"); + } + } else if (this->objtype == 2) { + try { + lcmop_c(&(this->addr), (char *)(this->path+this->name).c_str(), this->access, this->objtype, 0); + } catch(...) { + throw LCMexception("Exception catched by open (1)"); + } + } else if (this->objtype <= 5) { + this->addr = NULL; + bool exs = false; + DIR *dp; + struct dirent *dirp; + vector<string> names = vector<string>(); + if((dp = opendir(this->path.c_str())) == NULL) { + hsmg << "no file found (missing directory name: '" << this->path << ")'" << endl; + throw LCMexception(hsmg.str()); + } + while ((dirp = readdir(dp)) != NULL) { + names.push_back(string(dirp->d_name)); + } + closedir(dp); + for (size_t i=0; i<names.size(); i++) { + if (names[i] == this->name) exs = true; + } + if (this->access == 0) { + if (exs) { + hsmg << "New file " << this->path << this->name << " exists";; + throw LCMexception(hsmg.str()); + } + } else if (this->access == 1) { + if (!exs) { + hsmg << "Old file " << this->path << this->name << " does not exist(1)";; + throw LCMexception(hsmg.str()); + } + } else if (this->access == 2) { + if (!exs) { + hsmg << "Old file " << this->path << this->name << " does not exist(2)";; + throw LCMexception(hsmg.str()); + } + } + } else { + hsmg << "invalid type in open (" << this->objtype << ")"; + throw LCMexception(hsmg.str()); + } +} + +void ganlib::Clcm::close(const string saccess) { + int iact; + if (saccess == "KEEP") { + iact = 1; + } else if (saccess == "DESTROY") { + iact = 2; + } else if (saccess == "ERASE") { + iact = 3; + } else { + throw LCMexception("invalid condition: '" + saccess + "'"); + } + if (this->access != 0) { + if (this->objtype <= 2) { + try { + lcmcl_c(&(this->addr), iact); + } catch(...) { + throw LCMexception("Exception catched by close(1)"); + } + } else if (this->objtype <= 5) { + if (iact >= 2) { + try { + this->aFile.close(); + if( remove((this->path+this->name).c_str()) != 0 ) { + throw LCMexception("Error deleting file: " + this->path + this->name); + } + cout << "File deleted:" << this->path << this->name << endl; + } catch(...) { + throw LCMexception("Exception catched by close(2)"); + } + } + } + } else { + throw LCMexception("the object " + this->name + " is already closed"); + } + if (iact == 2) { + this->addr = NULL; + } + this->access = 0; +} + +int_32 ganlib::Clcm::length(const std::string key) { + int_32 mylength, itylcm; + if (this->objtype > 2) throw LCMexception("length not available for file objects"); + lcmlen_c(&(this->addr), (char *)key.c_str() ,&mylength, &itylcm); + if (itylcm == 3) mylength=4*mylength; + return mylength; +} + +int_32 ganlib::Clcm::length(const int_32 iset) { + int_32 mylength, itylcm; + if (this->objtype > 2) throw LCMexception("length not available for file objects"); + lcmlel_c(&(this->addr), iset ,&mylength, &itylcm); + if (itylcm == 3) mylength=4*mylength; + return mylength; +} + +int_32 ganlib::Clcm::type(const std::string key) { + int_32 mylength, itylcm; + if (this->objtype > 2) throw LCMexception("type not available for file objects"); + lcmlen_c(&(this->addr), (char *)key.c_str() ,&mylength, &itylcm); + if (itylcm == 99) { + hsmg << "length: no block named '" << key << "'"; + throw LCMexception(hsmg.str()); + } + return itylcm; +} + +int_32 ganlib::Clcm::type(const int_32 iset) { + int_32 mylength, itylcm; + if (this->objtype > 2) throw LCMexception("type not available for file objects"); + lcmlel_c(&(this->addr), iset ,&mylength, &itylcm); + if (itylcm == 99) { + hsmg << "length: no block at position " << iset << "."; + throw LCMexception(hsmg.str()); + } + return itylcm; +} + +void ganlib::Clcm::lib() { + if (this->objtype > 2) throw LCMexception("lib not available for file objects"); + lcmlib_c(&(this->addr)); +} + +void ganlib::Clcm::val() { + if (this->objtype > 2) throw LCMexception("val not available for file objects"); + lcmval_c(&(this->addr), " "); +} + +//---------------------------------------------------------------------- +//-- set -- +//---------------------------------------------------------------------- + +ClcmPtr ganlib::Clcm::setDictionary(const std::string key) { + if (this->objtype > 2) throw LCMexception("setDictionary not available for file objects"); + lcm *daughter = lcmdid_c(&(this->addr), (char *)key.c_str()); + return ClcmPtr(new Clcm(daughter, this->root, this->objtype, this->name, -1, key)); +} + +ClcmPtr ganlib::Clcm::setDictionary(const int_32 iset) { + if (this->objtype > 2) throw LCMexception("setDictionary not available for file objects"); + lcm *daughter = lcmdil_c(&(this->addr), iset); + return ClcmPtr(new Clcm(daughter, this->root, this->objtype, this->name, -1, " ")); +} + +ClcmPtr ganlib::Clcm::setList(const std::string key, const int_32 ilong) { + if (this->objtype > 2) throw LCMexception("setList not available for file objects"); + lcm *daughter = lcmlid_c(&(this->addr), (char *)key.c_str(), ilong); + return ClcmPtr(new Clcm(daughter, this->root, this->objtype, this->name, 0, key)); +} + +ClcmPtr ganlib::Clcm::setList(const int_32 iset, const int_32 ilong) { + if (this->objtype > 2) throw LCMexception("setList not available for file objects"); + lcm *daughter = lcmlil_c(&(this->addr), iset, ilong); + return ClcmPtr(new Clcm(daughter, this->root, this->objtype, this->name, 0, " ")); +} + +//---------------------------------------------------------------------- +//-- get -- +//---------------------------------------------------------------------- + +ClcmPtr ganlib::Clcm::getClcm(const std::string key) { + int_32 mylength, itylcm; + if (this->objtype > 2) throw LCMexception("getClcm not available for file objects"); + lcmlen_c(&(this->addr), (char *)key.c_str() ,&mylength, &itylcm); + if (mylength == 0) { + hsmg << "getClcm(" << key << ") entry is missing(1)"; + throw LCMexception(hsmg.str()); + } + if (itylcm == 0) { + lcm *daughter = lcmgid_c(&(this->addr), (char *)key.c_str()); + return ClcmPtr(new Clcm(daughter, this->root, this->objtype, this->name, -1, key)); + } else if (itylcm == 10) { + lcm *daughter = lcmgid_c(&(this->addr), (char *)key.c_str()); + return ClcmPtr(new Clcm(daughter, this->root, this->objtype, this->name, 0, key)); + } else { + hsmg << "getClcm(" << key << ") expecting a Clcm object(1)"; + throw LCMexception(hsmg.str()); + } +} + +ClcmPtr ganlib::Clcm::getClcm(const int_32 iset) { + int_32 mylength, itylcm; + if (this->objtype > 2) throw LCMexception("getClcm not available for file objects"); + lcmlel_c(&(this->addr), iset ,&mylength, &itylcm); + if (mylength == 0) { + hsmg << "getClcm(" << iset << ") entry is missing(2)"; + throw LCMexception(hsmg.str()); + } + if (itylcm == 0) { + lcm *daughter = lcmgil_c(&(this->addr), iset); + return ClcmPtr(new Clcm(daughter, this->root, this->objtype, this->name, -1, " ")); + } else if (itylcm == 10) { + lcm *daughter = lcmgil_c(&(this->addr), iset); + return ClcmPtr(new Clcm(daughter, this->root, this->objtype, this->name, 0, " ")); + } else { + hsmg << "getClcm(" << iset << ") expecting a Clcm object(2)"; + throw LCMexception(hsmg.str()); + } +} + +/// @cond DEV +// Use this destructor to avoid deleting LCM array pointed by the shared_array object +template<typename T> +struct my_deleter +{ + void operator()(T* p) { } +}; +/// @endcond + +IntPtrConst ganlib::Clcm::getInt(const std::string key) { + int_32 mylength, itylcm; + lcmlen_c(&(this->addr), (char *)key.c_str() ,&mylength, &itylcm); + if (mylength == 0) { + hsmg << "getInt(" << key << ") entry is missing(1)"; + throw LCMexception(hsmg.str()); + } else if (itylcm != 1) { + hsmg << "getInt(" << key << ") expecting an integer array(1)"; + throw LCMexception(hsmg.str()); + } + if (this->objtype == 1) { + // Use a reference without copy (pinning). + int_32 *array; + lcmgpd_c(&(this->addr), (char *)key.c_str(), &array); + IntPtrConst iarray(array, my_deleter<const int_32>()); + return iarray; + } else if (this->objtype == 2) { + // Use a reference with copy. + IntPtrConst iarray(new int_32[mylength]); + lcmget_c(&(this->addr), (char *)key.c_str(), (int_32 *)iarray.get()); + return iarray; + } else { + throw LCMexception("getInt not available for file objects"); + } +} + +IntPtrConst ganlib::Clcm::getInt(const int_32 iset) { + int_32 mylength, itylcm; + lcmlel_c(&(this->addr), iset ,&mylength, &itylcm); + if (mylength == 0) { + hsmg << "getInt(" << iset << ") entry is missing(2)"; + throw LCMexception(hsmg.str()); + } else if (itylcm != 1) { + hsmg << "getInt(" << iset << ") expecting an integer array(2)"; + throw LCMexception(hsmg.str()); + } + if (this->objtype == 1) { + // Use a reference without copy (pinning). + int_32 *array; + lcmgpl_c(&(this->addr), iset, &array); + IntPtrConst iarray(array, my_deleter<const int_32>()); + return iarray; + } else if (this->objtype == 2) { + // Use a reference with copy. + IntPtrConst iarray(new int_32[mylength]); + lcmgdl_c(&(this->addr), iset, (int_32 *)iarray.get()); + return iarray; + } else { + throw LCMexception("getInt not available for file objects"); + } +} + +FloatPtrConst ganlib::Clcm::getFloat(const std::string key) { + int_32 mylength, itylcm; + lcmlen_c(&(this->addr), (char *)key.c_str() ,&mylength, &itylcm); + if (mylength == 0) { + hsmg << "getFloat(" << key << ") entry is missing(1)"; + throw LCMexception(hsmg.str()); + } else if (itylcm != 2) { + hsmg << "getFloat(" << key << ") expecting a single precision real array(1)"; + throw LCMexception(hsmg.str()); + } + if (this->objtype == 1) { + // Use a reference without copy (pinning). + float_32 *array; + lcmgpd_c(&(this->addr), (char *)key.c_str(), (int_32 **)&array); + FloatPtrConst iarray(array, my_deleter<const float_32>()); + return iarray; + } else if (this->objtype == 2) { + // Use a reference with copy. + FloatPtrConst iarray(new float_32[mylength]); + lcmget_c(&(this->addr), (char *)key.c_str(), (int_32 *)iarray.get()); + return iarray; + } else { + throw LCMexception("getFloat not available for file objects"); + } +} + +FloatPtrConst ganlib::Clcm::getFloat(const int_32 iset) { + int_32 mylength, itylcm; + lcmlel_c(&(this->addr), iset ,&mylength, &itylcm); + if (mylength == 0) { + hsmg << "getFloat(" << iset << ") entry is missing(2)"; + throw LCMexception(hsmg.str()); + } else if (itylcm != 2) { + hsmg << "getFloat(" << iset << ") expecting a single precision real array(2)"; + throw LCMexception(hsmg.str()); + } + if (this->objtype == 1) { + // Use a reference without copy (pinning). + float_32 *array; + lcmgpl_c(&(this->addr), iset, (int_32 **)&array); + FloatPtrConst iarray(array, my_deleter<const float_32>()); + return iarray; + } else if (this->objtype == 2) { + // Use a reference with copy. + FloatPtrConst iarray(new float_32[mylength]); + lcmgdl_c(&(this->addr), iset, (int_32 *)iarray.get()); + return iarray; + } else { + throw LCMexception("getFloat not available for file objects"); + } +} + +StringPtrConst ganlib::Clcm::getString(const std::string key) { + int_32 mylength, itylcm; + if (this->objtype > 2) throw LCMexception("getString not available for file objects"); + lcmlen_c(&(this->addr), (char *)key.c_str() ,&mylength, &itylcm); + if (mylength == 0) { + hsmg << "getString(" << key << ") entry is missing(1)"; + throw LCMexception(hsmg.str()); + } else if (itylcm != 3) { + hsmg << "getString(" << key << ") expecting a character array(1)"; + throw LCMexception(hsmg.str()); + } + // Use a reference with copy. + int_32 *iarray; + lcmgpd_c(&(this->addr), (char *)key.c_str(), &iarray); + return StringPtrConst(new string((char*)iarray, 4*mylength)); +} + +StringPtrConst ganlib::Clcm::getString(const int_32 iset) { + int_32 mylength, itylcm; + if (this->objtype > 2) throw LCMexception("getString not available for file objects"); + lcmlel_c(&(this->addr), iset ,&mylength, &itylcm); + if (mylength == 0) { + hsmg << "getString(" << iset << ") entry is missing(2)"; + throw LCMexception(hsmg.str()); + } else if (itylcm != 3) { + hsmg << "getString(" << iset << ") expecting a character array(2)"; + throw LCMexception(hsmg.str()); + } + // Use a reference with copy. + int_32 *iarray; + lcmgpl_c(&(this->addr), iset, &iarray); + return StringPtrConst(new string((char*)iarray, 4*mylength)); +} + +StringVecPtr ganlib::Clcm::getVecString(const std::string key, const int_32 size) { + int_32 mylength, itylcm; + if (this->objtype > 2) throw LCMexception("getVecString not available for file objects"); + lcmlen_c(&(this->addr), (char *)key.c_str() ,&mylength, &itylcm); + if (mylength == 0) { + hsmg << "getVecString(" << key << ") entry is missing(1)"; + throw LCMexception(hsmg.str()); + } else if (itylcm != 3) { + hsmg << "getVecString(" << key << ") expecting a character array(1)"; + throw LCMexception(hsmg.str()); + } + // Use a reference with copy. + int_32 *iarray; + lcmgpd_c(&(this->addr), (char *)key.c_str(), &iarray); + StringVecPtr ivecPtr = StringVecPtr(new vector<string>); + for (int i=0; i<size; i++) { + int_32 nbchar = ( mylength*4 + size - 1) / size; + int_32 istart = nbchar*i; + if (i == size-1) nbchar = mylength*4 - nbchar*i; + if (nbchar != 0) { + string myString = string((char *)iarray, istart, nbchar); + ivecPtr->push_back(myString.substr(0, myString.find_last_not_of(" ")+1)); + } + } + return ivecPtr; +} + +StringVecPtr ganlib::Clcm::getVecString(const int_32 iset, const int_32 size) { + int_32 mylength, itylcm; + if (this->objtype > 2) throw LCMexception("getVecString not available for file objects"); + lcmlel_c(&(this->addr), iset ,&mylength, &itylcm); + if (mylength == 0) { + hsmg << "getVecString(" << iset << ") entry is missing(2)"; + throw LCMexception(hsmg.str()); + } else if (itylcm != 3) { + hsmg << "getVecString(" << iset << ") expecting a character array(2)"; + throw LCMexception(hsmg.str()); + } + // Use a reference with copy. + int_32 *iarray; + lcmgpl_c(&(this->addr), iset, &iarray); + StringVecPtr ivecPtr = StringVecPtr(new vector<string>); + for (int i=0; i<size; i++) { + int_32 nbchar = ( mylength*4 + size - 1) / size; + int_32 istart = nbchar*i; + if (i == size-1) nbchar = mylength*4 - nbchar*i; + if (nbchar != 0) { + string myString = string((char *)iarray, istart, nbchar); + ivecPtr->push_back(myString.substr(0, myString.find_last_not_of(" ") + 1)); + } + } + return ivecPtr; +} + +DoublePtrConst ganlib::Clcm::getDouble(const std::string key) { + int_32 mylength, itylcm; + lcmlen_c(&(this->addr), (char *)key.c_str() ,&mylength, &itylcm); + if (mylength == 0) { + hsmg << "getDouble(" << key << ") entry is missing(1)"; + throw LCMexception(hsmg.str()); + } else if (itylcm != 4) { + hsmg << "getDouble(" << key << ") expecting a double precision real array(1)"; + throw LCMexception(hsmg.str()); + } + if (this->objtype == 1) { + // Use a reference without copy (pinning). + double_64 *array; + lcmgpd_c(&(this->addr), (char *)key.c_str(), (int_32 **)&array); + DoublePtrConst iarray(array, my_deleter<const double_64>()); + return iarray; + } else if (this->objtype == 2) { + // Use a reference with copy. + DoublePtrConst iarray(new double_64[mylength]); + lcmget_c(&(this->addr), (char *)key.c_str(), (int_32 *)iarray.get()); + return iarray; + } else { + throw LCMexception("getDouble not available for file objects"); + } +} + +DoublePtrConst ganlib::Clcm::getDouble(const int_32 iset) { + int_32 mylength, itylcm; + lcmlel_c(&(this->addr), iset ,&mylength, &itylcm); + if (mylength == 0) { + hsmg << "getDouble(" << iset << ") entry is missing(2)"; + throw LCMexception(hsmg.str()); + } else if (itylcm != 4) { + hsmg << "getDouble(" << iset << ") expecting a double precision real array(2)"; + throw LCMexception(hsmg.str()); + } + if (this->objtype == 1) { + // Use a reference without copy (pinning). + double_64 *array; + lcmgpl_c(&(this->addr), iset, (int_32 **)&array); + DoublePtrConst iarray(array, my_deleter<const double_64>()); + return iarray; + } else if (this->objtype == 2) { + // Use a reference with copy. + DoublePtrConst iarray(new double_64[mylength]); + lcmgdl_c(&(this->addr), iset, (int_32 *)iarray.get()); + return iarray; + } else { + throw LCMexception("getDouble not available for file objects"); + } +} + +BoolPtrConst ganlib::Clcm::getBool(const std::string key) { + int_32 mylength, itylcm; + if (this->objtype > 2) throw LCMexception("getBool not available for file objects"); + lcmlen_c(&(this->addr), (char *)key.c_str() ,&mylength, &itylcm); + if (mylength == 0) { + hsmg << "getBool(" << key << ") entry is missing(1)"; + throw LCMexception(hsmg.str()); + } else if (itylcm != 5) { + hsmg << "getBool(" << key << ") expecting a boolean array(1)"; + throw LCMexception(hsmg.str()); + } + // Use a reference with copy. + int_32 *iarray; + lcmgpd_c(&(this->addr), (char *)key.c_str(), &iarray); + BoolPtrConst ibool(new bool[mylength]); + bool *myBool = (bool *)ibool.get(); + for (int i=0; i<mylength; i++) myBool[i] = (iarray[i] == 1); + return ibool; +} + +BoolPtrConst ganlib::Clcm::getBool(const int_32 iset) { + int_32 mylength, itylcm; + if (this->objtype > 2) throw LCMexception("getBool not available for file objects"); + lcmlel_c(&(this->addr), iset ,&mylength, &itylcm); + if (mylength == 0) { + hsmg << "getBool(" << iset << ") entry is missing(2)"; + throw LCMexception(hsmg.str()); + } else if (itylcm != 5) { + hsmg << "getBool(" << iset << ") expecting a boolean array(2)"; + throw LCMexception(hsmg.str()); + } + // Use a reference with copy. + int_32 *iarray; + lcmgpl_c(&(this->addr), iset, &iarray); + BoolPtrConst ibool(new bool[mylength]); + bool *myBool = (bool *)ibool.get(); + for (int i=0; i<mylength; i++) myBool[i] = (iarray[i] == 1); + return ibool; +} + +ComplexPtrConst ganlib::Clcm::getComplex(const std::string key) { + int_32 mylength, itylcm; + if (this->objtype > 2) throw LCMexception("getComplex not available for file objects"); + lcmlen_c(&(this->addr), (char *)key.c_str() ,&mylength, &itylcm); + if (mylength == 0) { + hsmg << "getComplex(" << key << ") entry is missing(1)"; + throw LCMexception(hsmg.str()); + } else if (itylcm != 6) { + hsmg << "getComplex(" << key << ") expecting a Complex array(1)"; + throw LCMexception(hsmg.str()); + } + // Use a reference with copy. + int_32 *iarray; + lcmgpd_c(&(this->addr), (char *)key.c_str(), &iarray); + complex<float_32> *icomplex = new complex<float_32>[mylength]; + for (int i=0; i<mylength; i++) { + icomplex[i] = complex<float_32>((float_32)iarray[2*i],(float_32)iarray[1+2*i]); + } + return ComplexPtrConst(icomplex); +} + +ComplexPtrConst ganlib::Clcm::getComplex(const int_32 iset) { + int_32 mylength, itylcm; + if (this->objtype > 2) throw LCMexception("getComplex not available for file objects"); + lcmlel_c(&(this->addr), iset ,&mylength, &itylcm); + if (mylength == 0) { + hsmg << "getComplex(" << iset << ") entry is missing(1)"; + throw LCMexception(hsmg.str()); + } else if (itylcm != 6) { + hsmg << "getComplex(" << iset << ") expecting a Complex array(2)"; + throw LCMexception(hsmg.str()); + } + // Use a reference with copy. + int_32 *iarray; + lcmgpl_c(&(this->addr), iset, &iarray); + complex<float_32> *icomplex = new complex<float_32>[mylength]; + for (int i=0; i<mylength; i++) { + icomplex[i] = complex<float_32>((float_32)iarray[2*i],(float_32)iarray[1+2*i]); + } + return ComplexPtrConst(icomplex); +} + +//---------------------------------------------------------------------- +//-- keys -- +//---------------------------------------------------------------------- + +StringVecPtr ganlib::Clcm::keys() { + if (this->objtype > 2) throw LCMexception("keys not available for file objects"); + if (this->getLength() != -1) throw LCMexception("keys only available for dictionaries"); + StringVecPtr ivecPtr = StringVecPtr(new vector<string>); + char first[13], key[13]; + strcpy(first, " "); + lcmnxt_c(&(this->addr), first); + strcpy(key, first); + while (true) { + lcmnxt_c(&(this->addr), key); + ivecPtr->push_back(string(key)); + if (strcmp(key, first) == 0) break; + } + return ivecPtr; +} + +//---------------------------------------------------------------------- +//-- put -- +//---------------------------------------------------------------------- + +void ganlib::Clcm::put(const std::string key, IntPtr myArray, const int_32 myLength) { + if (this->getAccess() != 1) { + hsmg << "put(" << key << ") forbidden if the object is not open in modification mode(1)"; + throw LCMexception(hsmg.str()); + } else if (myLength <= 0) { + hsmg << "put(" << key << ") has zero length(1)"; + throw LCMexception(hsmg.str()); + } + int_32 *myArrayPointer = (int_32 *)myArray.get(); + if ((this->objtype == 1) && (this->global_list != NULL)) { + // Use a reference without copy (pinning) for memory-resident lcm objects. + lcmppd_c(&(this->addr), (char *)key.c_str(), myLength, 1, myArrayPointer); + refpush(&(this->addr), myArrayPointer); + (this->global_list)->push_back(myArray); + } else if (this->objtype == 1) { + // Use a reference with copy for memory-resident lcm objects (the lcm object is + // coming from outside C++). + int_32 *iarray = setara_c(myLength); + for (int i=0; i<myLength; i++) iarray[i] = myArrayPointer[i]; + lcmppd_c(&(this->addr), (char *)key.c_str(), myLength, 1, iarray); + } else if (this->objtype == 2) { + // Use a reference with copy for xsm file objects. + xsm *ipxsm = (xsm *)(this->addr); + xsmput_c(&ipxsm, (char *)key.c_str(), myLength, 1, myArrayPointer); + } + myArray.reset(); + return; +} + +void ganlib::Clcm::put(const int_32 iset, IntPtr myArray, const int_32 myLength) { + if (this->getAccess() != 1) { + hsmg << "put(" << iset << ") forbidden if the object is not open in modification mode(2)"; + throw LCMexception(hsmg.str()); + } else if (myLength <= 0) { + hsmg << "put(" << iset << ") has zero length(2)"; + throw LCMexception(hsmg.str()); + } + int_32 *myArrayPointer = (int_32 *)myArray.get(); + if ((this->objtype == 1) && (this->global_list != NULL)) { + // Use a reference without copy (pinning) for memory-resident lcm objects. + lcmppl_c(&(this->addr), iset, myLength, 1, myArrayPointer); + refpush(&(this->addr), myArrayPointer); + (this->global_list)->push_back(myArray); + } else if (this->objtype == 1) { + // Use a reference with copy for memory-resident lcm objects (the lcm object is + // coming from outside C++). + int_32 *iarray = setara_c(myLength); + for (int i=0; i<myLength; i++) iarray[i] = myArrayPointer[i]; + lcmppl_c(&(this->addr), iset, myLength, 1, iarray); + } else if (this->objtype == 2) { + // Use a reference with copy for xsm file objects. + xsm *ipxsm = (xsm *)(this->addr) + iset; + xsmput_c(&ipxsm, " ", myLength, 1, myArrayPointer); + } + myArray.reset(); + return; +} + +void ganlib::Clcm::put(const std::string key, FloatPtr myArray, const int_32 myLength) { + if (this->getAccess() != 1) { + hsmg << "put(" << key << ") forbidden if the object is not open in modification mode(1)"; + throw LCMexception(hsmg.str()); + } else if (myLength <= 0) { + hsmg << "put(" << key << ") has zero length(1)"; + throw LCMexception(hsmg.str()); + } + float_32 *myArrayPointer = (float_32 *)myArray.get(); + if ((this->objtype == 1) && (this->global_list != NULL)) { + // Use a reference without copy (pinning) for memory-resident lcm objects. + lcmppd_c(&(this->addr), (char *)key.c_str(), myLength, 2, (int_32 *)myArrayPointer); + refpush(&(this->addr), (int_32 *)myArrayPointer); + (this->global_list)->push_back(myArray); + } else if (this->objtype == 1) { + // Use a reference with copy for memory-resident lcm objects (the lcm object is + // coming from outside C++). + int_32 *iarray = setara_c(myLength); + for (int i=0; i<myLength; i++) iarray[i] = (int_32)myArrayPointer[i]; + lcmppd_c(&(this->addr), (char *)key.c_str(), myLength, 2, iarray); + } else if (this->objtype == 2) { + // Use a reference with copy for xsm file objects. + xsm *ipxsm = (xsm *)(this->addr); + xsmput_c(&ipxsm, (char *)key.c_str(), myLength, 2, (int_32 *)myArrayPointer); + } + myArray.reset(); + return; +} + +void ganlib::Clcm::put(const int_32 iset, FloatPtr myArray, const int_32 myLength) { + if (this->getAccess() != 1) { + hsmg << "put(" << iset << ") forbidden if the object is not open in modification mode(2)"; + throw LCMexception(hsmg.str()); + } else if (myLength <= 0) { + hsmg << "put(" << iset << ") has zero length(2)"; + throw LCMexception(hsmg.str()); + } + float_32 *myArrayPointer = (float_32 *)myArray.get(); + if ((this->objtype == 1) && (this->global_list != NULL)) { + // Use a reference without copy (pinning) for memory-resident lcm objects. + lcmppl_c(&(this->addr), iset, myLength, 2, (int_32 *)myArrayPointer); + refpush(&(this->addr), (int_32 *)myArrayPointer); + (this->global_list)->push_back(myArray); + } else if (this->objtype == 1) { + // Use a reference with copy for memory-resident lcm objects (the lcm object is + // coming from outside C++). + int_32 *iarray = setara_c(myLength); + for (int i=0; i<myLength; i++) iarray[i] = (int_32)myArrayPointer[i]; + lcmppl_c(&(this->addr), iset, myLength, 2, iarray); + } else if (this->objtype == 2) { + // Use a reference with copy for xsm file objects. + xsm *ipxsm = (xsm *)(this->addr) + iset; + xsmput_c(&ipxsm, " ", myLength, 2, (int_32 *)myArrayPointer); + } + myArray.reset(); + return; +} + +void ganlib::Clcm::put(const std::string key, StringPtr myArray) { + if (this->getAccess() != 1) { + hsmg << "put(" << key << ") forbidden if the object is not open in modification mode(1)"; + throw LCMexception(hsmg.str()); + } else if ((myArray.get())->length() <= 0) { + hsmg << "put(" << key << ") has zero length(1)"; + throw LCMexception(hsmg.str()); + } + int_32 ilen = ((myArray.get())->length()+3)/4; + int_32 *iarray = (int_32 *)setara_c(ilen); + for (int i=0; i<ilen; i++) memcpy((char *)&iarray[i], " ", 4); + string myString = *myArray.get(); + strncpy((char *)iarray, myString.c_str(), myString.length()); + lcmppd_c(&(this->addr), (char *)key.c_str(), ilen, 3, iarray); + myArray.reset(); + return; +} + +void ganlib::Clcm::put(const int_32 iset, StringPtr myArray) { + if (this->getAccess() != 1) { + hsmg << "put(" << iset << ") forbidden if the object is not open in modification mode(2)"; + throw LCMexception(hsmg.str()); + } else if ((myArray.get())->length() <= 0) { + hsmg << "put(" << iset << ") has zero length(2)"; + throw LCMexception(hsmg.str()); + } + int_32 ilen = ((myArray.get())->length()+3)/4; + int_32 *iarray = (int_32 *)setara_c(ilen); + for (int i=0; i<ilen; i++) memcpy((char *)&iarray[i], " ", 4); + string myString = *myArray.get(); + strncpy((char *)iarray, myString.c_str(), myString.length()); + lcmppl_c(&(this->addr), iset, ilen, 3, iarray); + myArray.reset(); + return; +} + +void ganlib::Clcm::put(const std::string key, StringVecPtr myArray) { + const vector<string> *ivec = (vector<string>*)myArray.get(); + const int_32 mySize = ivec->size(); + if (this->getAccess() != 1) { + hsmg << "put(" << key << ") forbidden if the object is not open in modification mode(1)"; + throw LCMexception(hsmg.str()); + } else if (mySize <= 0) { + hsmg << "put(" << key << ") has zero size(1)"; + throw LCMexception(hsmg.str()); + } + int_32 maxLength = 0; + for (int i=0; i<mySize; i++) { + maxLength = max(maxLength, (int_32)(*ivec)[i].length()); + } + if (maxLength == 0) { + hsmg << "put(" << key << ") has zero length(1)"; + throw LCMexception(hsmg.str()); + } + maxLength = (maxLength+3)/4; + int_32 *iarray = (int_32 *)setara_c(maxLength*mySize); + for (int i=0; i<maxLength*mySize; i++) memcpy((char *)&iarray[i], " ", 4); + for (int i=0; i<mySize; i++) { + string myString = (*ivec)[i]; + strncpy((char *)&iarray[maxLength*i], myString.c_str(), myString.length()); + } + lcmppd_c(&(this->addr), (char *)key.c_str(), maxLength*mySize, 3, iarray); + myArray.reset(); + return; +} + +void ganlib::Clcm::put(const int_32 iset, StringVecPtr myArray) { + const vector<string> *ivec = (vector<string>*)myArray.get(); + const int_32 mySize = ivec->size(); + if (this->getAccess() != 1) { + hsmg << "put(" << iset << ") forbidden if the object is not open in modification mode(2)"; + throw LCMexception(hsmg.str()); + } else if (mySize <= 0) { + hsmg << "put(" << iset << ") has zero size(2)"; + throw LCMexception(hsmg.str()); + } + int_32 maxLength = 0; + for (int i=0; i<mySize; i++) { + maxLength = max(maxLength, (int_32)(*ivec)[i].length()); + } + if (maxLength == 0) { + hsmg << "put(" << iset << ") has zero length(2)"; + throw LCMexception(hsmg.str()); + } + maxLength = (maxLength+3)/4; + int_32 *iarray = (int_32 *)setara_c(maxLength*mySize); + for (int i=0; i<maxLength*mySize; i++) memcpy((char *)(&iarray[i]), " ", 4); + for (int i=0; i<mySize; i++) { + string myString = (*ivec)[i]; + strncpy((char *)(&iarray[maxLength*i]), myString.c_str(), myString.length()); + } + lcmppl_c(&(this->addr), iset, maxLength*mySize, 3, iarray); + myArray.reset(); + return; +} + +void ganlib::Clcm::put(const std::string key, DoublePtr myArray, const int_32 myLength) { + if (this->getAccess() != 1) { + hsmg << "put(" << key << ") forbidden if the object is not open in modification mode(1)"; + throw LCMexception(hsmg.str()); + } else if (myLength <= 0) { + hsmg << "put(" << key << ") has zero length(1)"; + throw LCMexception(hsmg.str()); + } + double_64 *myArrayPointer = (double_64 *)myArray.get(); + if ((this->objtype == 1) && (this->global_list != NULL)) { + // Use a reference without copy (pinning) for memory-resident lcm objects. + lcmppd_c(&(this->addr), (char *)key.c_str(), myLength, 4, (int_32 *)myArrayPointer); + refpush(&(this->addr), (int_32 *)myArrayPointer); + (this->global_list)->push_back(myArray); + } else if (this->objtype == 1) { + // Use a reference with copy for memory-resident lcm objects (the lcm object is + // coming from outside C++). + int_32 *iarray = setara_c(2*myLength); + for (int i=0; i<2*myLength; i++) iarray[i] = ((int_32 *)myArrayPointer)[i]; + lcmppd_c(&(this->addr), (char *)key.c_str(), myLength, 4, iarray); + } else if (this->objtype == 2) { + // Use a reference with copy for xsm file objects. + xsm *ipxsm = (xsm *)(this->addr); + xsmput_c(&ipxsm, (char *)key.c_str(), myLength, 4, (int_32 *)myArrayPointer); + } + myArray.reset(); + return; +} + +void ganlib::Clcm::put(const int_32 iset, DoublePtr myArray, const int_32 myLength) { + if (this->getAccess() != 1) { + hsmg << "put(" << iset << ") forbidden if the object is not open in modification mode(2)"; + throw LCMexception(hsmg.str()); + } else if (myLength <= 0) { + hsmg << "put(" << iset << ") has zero length(2)"; + throw LCMexception(hsmg.str()); + } + double_64 *myArrayPointer = (double_64 *)myArray.get(); + if ((this->objtype == 1) && (this->global_list != NULL)) { + // Use a reference without copy (pinning) for memory-resident lcm objects. + lcmppl_c(&(this->addr), iset, myLength, 4, (int_32 *)myArrayPointer); + refpush(&(this->addr), (int_32 *)myArrayPointer); + (this->global_list)->push_back(myArray); + } else if (this->objtype == 1) { + // Use a reference with copy for memory-resident lcm objects (the lcm object is + // coming from outside C++). + int_32 *iarray = setara_c(2*myLength); + for (int i=0; i<2*myLength; i++) iarray[i] = ((int_32 *)myArrayPointer)[i]; + lcmppl_c(&(this->addr), iset, myLength, 4, iarray); + } else if (this->objtype == 2) { + // Use a reference with copy for xsm file objects. + xsm *ipxsm = (xsm *)(this->addr) + iset; + xsmput_c(&ipxsm, " ", myLength, 4, (int_32 *)myArrayPointer); + } + myArray.reset(); + return; +} + +void ganlib::Clcm::put(const std::string key, BoolPtr myArray, const int_32 myLength) { + if (this->getAccess() != 1) { + hsmg << "put(" << key << ") forbidden if the object is not open in modification mode(1)"; + throw LCMexception(hsmg.str()); + } else if (myLength <= 0) { + hsmg << "put(" << key << ") has zero length(1)"; + throw LCMexception(hsmg.str()); + } + bool *myArrayPointer = (bool *)myArray.get(); + // Use a reference with copy. + int_32 *iarray = setara_c(myLength); + for (int i=0; i<myLength; i++) { + myArrayPointer[i] ? iarray[2*i] = 1 : iarray[2*i] = 0; + } + lcmppd_c(&(this->addr), (char *)key.c_str(), myLength, 5, iarray); + myArray.reset(); + return; +} + +void ganlib::Clcm::put(const int_32 iset, BoolPtr myArray, const int_32 myLength) { + if (this->getAccess() != 1) { + hsmg << "put(" << iset << ") forbidden if the object is not open in modification mode(2)"; + throw LCMexception(hsmg.str()); + } else if (myLength <= 0) { + hsmg << "put(" << iset << ") has zero length(2)"; + throw LCMexception(hsmg.str()); + } + bool *myArrayPointer = (bool *)myArray.get(); + // Use a reference with copy. + int_32 *iarray = setara_c(myLength); + for (int i=0; i<myLength; i++) { + myArrayPointer[i] ? iarray[2*i] = 1 : iarray[2*i] = 0; + } + lcmppl_c(&(this->addr), iset, myLength, 5, iarray); + myArray.reset(); + return; +} + +void ganlib::Clcm::put(const std::string key, ComplexPtr myArray, const int_32 myLength) { + if (this->getAccess() != 1) { + hsmg << "put(" << key << ") forbidden if the object is not open in modification mode(1)"; + throw LCMexception(hsmg.str()); + } else if (myLength <= 0) { + hsmg << "put(" << key << ") has zero length(1)"; + throw LCMexception(hsmg.str()); + } + complex<float_32> *myArrayPointer = (complex<float_32> *)myArray.get(); + // Use a reference with copy. + int_32 *iarray = setara_c(2*myLength); + for (int i=0; i<myLength; i++) { + iarray[2*i] = (int_32)myArrayPointer[i].real(); + iarray[1+2*i] = (int_32)myArrayPointer[i].imag(); + } + lcmppd_c(&(this->addr), (char *)key.c_str(), myLength, 6, iarray); + myArray.reset(); + return; +} + +void ganlib::Clcm::put(const int_32 iset, ComplexPtr myArray, const int_32 myLength) { + if (this->getAccess() != 1) { + hsmg << "put(" << iset << ") forbidden if the object is not open in modification mode(2)"; + throw LCMexception(hsmg.str()); + } else if (myLength <= 0) { + hsmg << "put(" << iset << ") has zero length(2)"; + throw LCMexception(hsmg.str()); + } + complex<float_32> *myArrayPointer = (complex<float_32> *)myArray.get(); + // Use a reference with copy. + int_32 *iarray = setara_c(2*myLength); + for (int i=0; i<myLength; i++) { + iarray[2*i] = (int_32)myArrayPointer[i].real(); + iarray[1+2*i] = (int_32)myArrayPointer[i].imag(); + } + lcmppl_c(&(this->addr), iset, myLength, 6, iarray); + myArray.reset(); + return; +} + +void ganlib::Clcm::put(const std::string key, ClcmPtr myClcm) { + if (this->getAccess() != 1) { + hsmg << "put(" << key << ") forbidden if the object is not open in modification mode(1)"; + throw LCMexception(hsmg.str()); + } + lcm *daughter = lcmgid_c(&(this->addr), (char *)key.c_str()); + lcm *myLcm = myClcm->addr; + lcmequ_c(&myLcm, &daughter); + return; +} + +void ganlib::Clcm::put(const int_32 iset, ClcmPtr myClcm) { + if (this->getAccess() != 1) { + hsmg << "put(" << iset << ") forbidden if the object is not open in modification mode(2)"; + throw LCMexception(hsmg.str()); + } + lcm *daughter = lcmgil_c(&(this->addr), iset); + lcm *myLcm = myClcm->addr; + lcmequ_c(&myLcm, &daughter); + return; +} + +lcm *ganlib::Clcm::extract() { + return this->addr; +} diff --git a/Skin++/src/Clcm.hxx b/Skin++/src/Clcm.hxx new file mode 100755 index 0000000..86a12b7 --- /dev/null +++ b/Skin++/src/Clcm.hxx @@ -0,0 +1,706 @@ +/** + * This class is an implementation of the C++ bindings for LCM. + * LCM capabilities are available for a program written in C++ + * by using methods belonging to the Clcm class. + * <P> A Clcm object in C++ can encapsulate a native LCM object + * which can be memory-resident or persistent (using the XSM C API) + * or a file. A LCM or XSM native object can contains dictionaries + * (aka associative tables or hash tables) and lists. + * <P> + * + * @author Alain Hebert, Ecole Polytechnique de Montreal (2024) + */ +#ifndef Clcm_HXX +#define Clcm_HXX + +#include <cstddef> // for __GLIBCXX__ + +#ifdef __GLIBCXX__ // for memory management with shared_ptr +# include <tr1/memory> +#else +# ifdef __IBMCPP__ +# define __IBMCPP_TR1__ +# endif +# include <memory> +#endif + +#include <cerrno> +#include <cstdio> +#include <cstring> +#include <iostream> +#include <sstream> +#include <vector> +#include <fstream> +#include <complex> +#include <memory> +#include <variant> +#include "LCMexception.hxx" +extern "C" { +#include <dirent.h> +#include "lcm.h" +} + +#define IntPtr std::shared_ptr<int_32[]> +#define FloatPtr std::shared_ptr<float_32[]> +#define StringPtr std::shared_ptr<std::string> +#define DoublePtr std::shared_ptr<double_64[]> +#define BoolPtr std::shared_ptr<bool[]> +#define ComplexPtr std::shared_ptr< std::complex<float_32>[] > +#define StringVecPtr std::shared_ptr< std::vector<std::string> > +#define ClcmPtr std::shared_ptr<Clcm> + +// support for pinning. +#define AnyPtr std::variant<IntPtr, FloatPtr, StringPtr, DoublePtr, BoolPtr, ComplexPtr> +#define IntPtrConst std::shared_ptr<const int_32> +#define FloatPtrConst std::shared_ptr<const float_32> +#define StringPtrConst std::shared_ptr<const std::string> +#define DoublePtrConst std::shared_ptr<const double_64> +#define BoolPtrConst std::shared_ptr<const bool> +#define ComplexPtrConst std::shared_ptr<const std::complex<float_32> > + +namespace ganlib { + +/** + * This class is an implementation of the C++/shared_ptr bindings for LCM. + * LCM capabilities are available for a program written in C++ + * by using methods belonging to the Clcm class. These methods + * encapsulate the LCM C API calls used as "extern"C" functions. + * <P> A Clcm object in C++ can encapsulate a native LCM object + * which can be memory-resident or persistent (using the XSM C API) + * or a file. A LCM or XSM native object can contains dictionaries + * (aka associative tables or hash tables) and lists. + * <P> + * The Clcm class uses predefined declarations for some datatypes: + * <table border="0"> + * <tr> <td><tt>#define IntPtr</tt>:</td> <td><tt>std::shared_ptr<int_32[]></tt></td> </tr> + * <tr> <td><tt>#define FloatPtr</tt>:</td> <td><tt>std::shared_ptr<float_32[]></tt></td> </tr> + * <tr> <td><tt>#define StringPtr</tt>:</td> <td><tt>std::shared_ptr<std::string></tt></td> </tr> + * <tr> <td><tt>#define DoublePtr</tt>:</td> <td><tt>std::shared_ptr<double_64[]></tt></td> </tr> + * <tr> <td><tt>#define BoolPtr</tt>:</td> <td><tt>std::shared_ptr<bool[]></tt></td> </tr> + * <tr> <td><tt>#define ComplexPtr</tt>:</td> <td><tt>std::shared_ptr< complex<float_32>[] ></tt></td> </tr> + * <tr> <td><tt>#define StringVecPtr</tt>:</td> <td><tt>std::shared_ptr< std::vector<std::string> ></tt></td> </tr> + * <tr> <td><tt>#define ClcmPtr</tt>:</td> <td><tt>std::shared_ptr<Clcm></tt></td> </tr> + * </table> + * <P> + * Moreover, get methods are constructing shared arrays that <i>cannot</i> be modified in the calling C++ + * code. To prevent this, they are declared <tt>const</tt> using the following predefined declarations: + * <table border="0"> + * <tr> <td><tt>#define IntPtrConst</tt>:</td> <td><tt>std::shared_ptr<const int_32[]></tt></td> </tr> + * <tr> <td><tt>#define FloatPtrConst</tt>:</td> <td><tt>std::shared_ptr<const float_32[]></tt></td> </tr> + * <tr> <td><tt>#define StringPtrConst</tt>:</td> <td><tt>std::shared_ptr<const std::string></tt></td> </tr> + * <tr> <td><tt>#define DoublePtrConst</tt>:</td> <td><tt>std::shared_ptr<const double_64[]></tt></td> </tr> + * <tr> <td><tt>#define BoolPtrConst</tt>:</td> <td><tt>std::shared_ptr<const bool[]></tt></td> </tr> + * <tr> <td><tt>#define ComplexPtrConst</tt>:</td> <td><tt>std::shared_ptr<const complex<float_32>[] ></tt></td> </tr> + * </table> + * <P> + * + * @author Alain Hebert, Ecole Polytechnique de Montreal (2010) + */ + +class Clcm { +public: + /** + * Use this constructor to create a Clcm object of a specified type. + * The new LCM object is open in modification mode and is in a state + * such that the <tt>isNew()</tt> method will return <tt>true</tt>. + * If a XSM file <tt>name</tt> exists, the Clcm object is pointing to + * this file open in <tt>"READ-ONLY"</tt> mode and is in a state + * such that the <tt>isNew()</tt> method will return <tt>false</tt>. + * If the type is <tt>"LCM_IMP"</tt> or <tt>"XSM_IMP"</tt>, the new + * LCM object is open in modification mode and the <tt>isNew()</tt> + * method will return <tt>false</tt>. + * <p> + * A Clcm object is created using a construct similar to the following one: + * <pre> + * ClcmPtr myNewClcm = ClcmPtr(new Clcm("XSM_IMP_ASCII", "Multicompo", "./")); + * </pre> + * where a XSM file is imported from ASCII file <tt>./Multicompo</tt>. + * + * @param stype type of the new Clcm object. This variable is chosen among + * the following values: + * <ul><dl> + * <dt> <tt>"LCM"</tt> <dd> memory-resident LCM object + * <dt> <tt>"XSM"</tt> <dd> XSM object (or persistent LCM object) + * <dt> <tt>"BINARY"</tt> <dd> binary sequential file + * <dt> <tt>"ASCII"</tt> <dd> ACSII sequential file + * <dt> <tt>"DA"</tt> <dd> binary direct-access file (with 128-word records) + * <dt> <tt>"LCM_IMP_BINARY"</tt> <dd> memory-resident LCM object constructed by + * importing from a binary sequential file named <tt>"_"</tt>+name + * <dt> <tt>"XSM_IMP_BINARY"</tt> <dd> XSM object constructed by importing + * from a binary sequential file named <tt>"_"</tt>+name + * <dt> <tt>"LCM_IMP_ASCII"</tt> <dd> memory-resident LCM object constructed by + * importing from an ASCII sequential file named <tt>"_"</tt>+name + * <dt> <tt>"XSM_IMP_ASCII"</tt> <dd> XSM object constructed by importing + * from an ASCII sequential file named <tt>"_"</tt>+name + * </dl></ul> + * @param myName creation name of the new Clcm object + * @param myPath path to access the associated file. This can be a sequential import + * file (with <tt>"_"</tt> prefix), an <tt>"XSM"</tt>, <tt>"BINARY"</tt>, + * <tt>"ASCII"</tt> or <tt>"DA"</tt> file. Set to <tt>"./"</tt> to work + * in the current directory. + */ + Clcm(const std::string stype, const std::string myName, const std::string myPath); + + /// @cond DEV + Clcm(lcm *, Clcm *, const int_32, const std::string, const int_32, const std::string); + /// @endcond + + /** + * Use this constructor to create a clone of an existing Clcm object. This is a deep-copy + * operation. A clone is created using the following construct: + * <pre> + * ClcmPtr myClcmClone = ClcmPtr(new Clcm("LCM", myClcm)); + * </pre> + * @param stype type of the new Clcm object. This variable is chosen among + * the following values: + * <ul><dl> + * <dt> <tt>"LCM"</tt> <dd> memory-resident LCM object + * <dt> <tt>"XSM"</tt> <dd> XSM object (or persistent LCM object) + * </dl></ul> + * @param myClcm existing ClcmPtr object accessed in read-only mode. This object must me of + * LCM or XSM type. + */ + Clcm(const std::string stype, ClcmPtr myClcm); + + /** + * Use this constructor to encapsulate an open LCM or XSM object into a Clcm object. The + * existing LCM or XSM object is not garbage collected (it may belong to another Clcm object). + * @param mylcm existing LCM or XSM object. + * @param type type of object (=1: LCM; =2:XSM). + * @param access access mode of object (=1: ; =2:). + * @param OSname operating system name of object. + */ + Clcm(lcm *mylcm, const int_32 type, const int_32 access, const std::string OSname); + + /** Close and destroy a Clcm object if in modification mode; close and + * keep a Clcm object if in read-only mode. + */ + ~Clcm(); + + /** Export a Clcm object into an ostream (ascii stream). This method is not available for + * file-type Clcm objects. A Clcm object can be dumped to the standard output using: + * <pre> + * cout << myClcm; + * </pre> + * @param s initial std::ostream objet. + * @param myClcm ClcmPtr object to export. + * @return final std::ostream objet including the ClcmPtr object. + */ + friend std::ostream & operator<<(std::ostream &s, ClcmPtr myClcm); + + /** Serialize and save the object content on a sequential file. This method is not + * available for file-type Clcm objects. The name of the sequential file is + * the catenation of <tt>"_"</tt> with the name of the Clcm object. + * @param stype type of the export file. This variable is chosen among + * the following values: + * <ul><dl> + * <dt> <tt>"BINARY"</tt> <dd> binary sequential file + * <dt> <tt>"ASCII"</tt> <dd> ACSII sequential file + * </dl></ul> + */ + void expor(const std::string stype); + + /** Serialize and save the object content on a sequential file. This method is not + * available for file-type Clcm objects. + * @param stype type of the export file. This variable is chosen among + * the following values: + * <ul><dl> + * <dt> <tt>"BINARY"</tt> <dd> binary sequential file + * <dt> <tt>"ASCII"</tt> <dd> ACSII sequential file + * </dl></ul> + * @param new_name name of the sequential file. This name must begin by + * character <tt>"_"</tt>. + */ + void expor(const std::string stype, const std::string new_name); + + /** Cause an exception (used to debug XABORT in C++). + */ + void except(); + + /** Return the name of the Clcm object. + */ + std::string getName() throw(); + + /** Return the path to access the associated file. + */ + std::string getPath() throw(); + + /** Return the type of the Clcm object. + * @return =1: memory-resident LCM object; =2: persistent LCM object; + * =3: binary sequential file; =4: ASCII sequential file; =5 binary + * direct-access file. + */ + int_32 getType() throw(); + + /** Return the length of a list-type Clcm object. This method is not + * available for file-type Clcm objects. + * @return =-1: dictionary; >=1: length of the list-type Clcm object. + */ + int_32 getLength(); + + /** Return the name of the accessible directory of a dictionary-type + * Clcm object. This method is not available for file-type Clcm objects. + * @return =<tt>"/"</tt> for a dictionary on root or name of the accessible + * directory. + */ + std::string getDirectory(); + + /** Return the access type of a Clcm object. + * @return =0: the object is closed; =1: the object is open in modification + * mode; =2: the object is open in read-only mode. + */ + int_32 getAccess(); + + /** Return the number of words in a record of a direct access-type Clcm object. + */ + int_32 getLrda() throw(); + + /** Return the original version of the imported object. + */ + int_32 getVersion() throw(); + + /** Return true if the a dictionary-type Clcm object is empty. This method + * is not available for file-type Clcm objects. + */ + bool isEmpty(); + + /** Return true if the dictionary-type Clcm object is new. This method + * is not available for file-type Clcm objects. + */ + bool isNew() throw(); + + /** Open a new Clcm object or reopen an existing Clcm object already closed by + * the close(<tt>"KEEP"</tt>) method. In this case, the Clcm object is reopen + * in a state such as the <tt>isNew()</tt> method will return false. + * @param saccess type of open. This variable is chosen among the following + * values: + * <ul><dl> + * <dt> <tt>"NEW"</tt> <dd> open a new Clcm object. + * <dt> <tt>"READ/WRITE"</tt> <dd> open in modification mode. + * <dt> <tt>"READ-ONLY"</tt> <dd> open in read-only mode. + * </dl></ul> + */ + void open(const std::string saccess); + + /** Close a Clcm object. + * @param saccess =<tt>"KEEP"</tt>: close without destruction of the object + * content; =<tt>"DESTROY"</tt>: close with destruction of the object content. + */ + void close(const std::string saccess); + + /** + * Return the length of a block of information in a dictionary-type + * Clcm object. This method is not available for file-type Clcm objects. + * @param key key identification of the block in the dictionary + * @return the number of components for an elementary block; -1 for + * a daughter dictionary; 0: the block does't exist; length of the list + * for a daughter list; length in characters for a string array. + */ + int_32 length(const std::string key); + + /** + * Return the length of a block of information in a list-type Clcm object. + * This method is not available for file-type Clcm objects. + * @param iset index of the block in the list. The first list element is + * stored at index 0. + * @return the number of components for an elementary block; -1 for + * a daughter dictionary; 0: the block does't exist; length of the list + * for a daughter list; length in characters for a string array. + */ + int_32 length(const int_32 iset); + + /** + * Return the type of a block of information in a dictionary-type + * Clcm object. This method is not available for file-type Clcm objects. + * @param key key identification of the block in the dictionary + * @return =0: dictionary; =1: integer (int_32); =2: real number (float); + * =3: string; =4: real number (double); =5: boolean; =6: Complex object; + * =10: list. + */ + int_32 type(const std::string key); + + /** + * Return the type of a block of information in a list-type Clcm object. + * This method is not available for file-type Clcm objects. + * @param iset index of the block in the list. The first list element is + * stored at index 0. + * @return =0: dictionary; =1: integer (int_32); =2: real number (float); + * =3: string; =4: real number (double); =5: boolean; =6: Complex object; + * =10: list. + */ + int_32 type(const int_32 iset); + + /** Print the table of contents of a dictionary- or list-type Clcm object. + * This method is not available for file-type Clcm objects. + */ + void lib(); + + /** Validate a dictionary- or list-type Clcm object. Detect possible memory + * corruption. + * This method is not available for file-type Clcm objects. + */ + void val(); + + /** Set a daughter dictionary-type Clcm object from a dictionary-type Clcm + * object. This method is not available for file-type Clcm objects. + * @param key key identification of the daughter Clcm object in the dictionary + * @return daughter ClcmPtr object of dictionary or list type. + */ + ClcmPtr setDictionary(const std::string key); + + /** Set a daughter dictionary-type Clcm object from a list-type Clcm + * object. This method is not available for file-type Clcm objects. + * @param iset index of the daughter Clcm object in the list. The first list + * element is stored at index 0. + * @return daughter ClcmPtr object of dictionary or list type. + */ + ClcmPtr setDictionary(const int_32 iset); + + /** Set a daughter list-type Clcm object from a dictionary-type Clcm object. + * This method is not available for file-type Clcm objects. + * @param key key identification of the daughter Clcm object in the dictionary + * @param ilong initial length of the heterogeneous list + * @return daughter ClcmPtr object of dictionary or list type. + */ + ClcmPtr setList(const std::string key, const int_32 ilong); + + /** Set a daughter list-type Clcm object from a list-type Clcm object + * This method is not available for file-type Clcm objects. + * @param iset index of the daughter Clcm object in the list. The first list + * element is stored at index 0. + * @param ilong initial length of the heterogeneous list + * @return daughter ClcmPtr object of dictionary or list type. + */ + ClcmPtr setList(const int_32 iset, const int_32 ilong); + + /** Recover a daughter Clcm object from an existing dictionary-type Clcm object. + * This method is not available for file-type Clcm objects. + * @param key key identification of the daughter Clcm object in the dictionary + * @return daughter ClcmPtr object of dictionary or list type. + */ + ClcmPtr getClcm(const std::string key); + + /** Recover a daughter Clcm object from an existing list-type Clcm object. + * This method is not available for file-type Clcm objects. + * @param iset index of the daughter Clcm object in the list. The first list + * element is stored at index 0. + * @return daughter ClcmPtr object of dictionary or list type. + */ + ClcmPtr getClcm(const int_32 iset); + + /** Recover an integer array from a dictionary-type Clcm object. + * <b>General rule:</b> Never try to modify, deallocate or free the object returned + * by <tt>getInt</tt>. This method is not available for file-type Clcm objects. + * <p> + * <b>Example</b>: An integer array named <tt>"myArray"</tt> is read from + * Clcm object named <tt>multicompo</tt> using + * <pre> + * IntPtrConst ia = multicompo->getInt("myArray"); + * for(int i = 0; i < multicompo->length("myArray"); ++i) + * cout << "ia(" << i << ")=" << ia[i] << endl; + * </pre> + * @param key key identification of the integer array in the dictionary + * @return array of integer values stored as <tt>IntPtr</tt> object. + */ + IntPtrConst getInt(const std::string key); + + /** Recover an integer array from a list-type Clcm object. + * <b>General rule:</b> Never try to modify, deallocate or free the object returned + * by <tt>getInt</tt>. This method is not available for file-type Clcm objects. + * @param iset index of the integer array in the list. The first list element + * is stored at index 0. + * @return array of integer values stored as <tt>IntPtr</tt> object. + */ + IntPtrConst getInt(const int_32 iset); + + /** Recover a single precision real array from a dictionary-type Clcm object. + * <b>General rule:</b> Never try to modify, deallocate or free the object returned + * by <tt>getFloat</tt>. This method is not available for file-type Clcm objects. + * @param key key identification of the real array in the dictionary + * @return array of single precision real values stored as <tt>FloatPtr</tt> object. + */ + FloatPtrConst getFloat(const std::string key); + + /** Recover a single precision real array from a list-type Clcm object. + * <b>General rule:</b> Never try to modify, deallocate or free the object returned + * by <tt>getFloat</tt>. This method is not available for file-type Clcm objects. + * @param iset index of the real array in the list. The first list element + * is stored at index 0. + * @return array of single precision real values stored as <tt>FloatPtr</tt> object. + */ + FloatPtrConst getFloat(const int_32 iset); + + /** Recover a string pointer from a dictionary-type Clcm object. + * <b>General rule:</b> Never try to modify, deallocate or free the string returned + * by <tt>getString</tt>. This method is not available for file-type Clcm objects. + * @param key key identification of the character array in the dictionary + * @return character information stored as <tt>StringPtr</tt> object. + */ + StringPtrConst getString(const std::string key); + + /** Recover a string pointer from a list-type Clcm object. + * <b>General rule:</b> Never try to modify, deallocate or free the string returned + * by <tt>getString</tt>. This method is not available for file-type Clcm objects. + * @param iset index of the integer array in the list. The first list element + * is stored at index 0. + * @return character information stored as <tt>StringPtr</tt> object. + */ + StringPtrConst getString(const int_32 iset); + + /** Recover a vector-of-string pointer from a dictionary-type Clcm object. + * <b>General rule:</b> Never try to modify, deallocate or free the vector-of-string returned + * by <tt>getVecString</tt>. This method is not available for file-type Clcm objects. + * @param key key identification of the character array in the dictionary + * @param size number of components in the vector-of-string + * @return vector-of-string containing the character information stored as + * <tt>StringVecPtr</tt> object. + */ + StringVecPtr getVecString(const std::string key, const int_32 size); + + /** Recover a vector-of-string pointer from a list-type Clcm object. + * <b>General rule:</b> Never try to modify, deallocate or free the vector-of-string returned + * by <tt>getVecString</tt>. This method is not available for file-type Clcm objects. + * @param iset index of the integer array in the list. The first list element + * is stored at index 0. + * @param size number of components in the vector-of-string + * @return vector-of-string containing the character information stored as + * <tt>StringVecPtr</tt> object. + */ + StringVecPtr getVecString(const int_32 iset, const int_32 size); + + /** Recover a double precision real array from a dictionary-type Clcm object. + * <b>General rule:</b> Never try to modify, deallocate or free the object returned + * by <tt>getDouble</tt>. This method is not available for file-type Clcm objects. + * @param key key identification of the double precision array in the dictionary + * @return array of double precision real values stored as <tt>DoublePtr</tt> object. + */ + DoublePtrConst getDouble(const std::string key); + + /** Recover a double precision real array from a list-type Clcm object. + * <b>General rule:</b> Never try to modify, deallocate or free the object returned + * by <tt>getDouble</tt>. This method is not available for file-type Clcm objects. + * @param iset index of the double precision array in the list. The first list element + * is stored at index 0. + * @return array of double precision real values stored as <tt>DoublePtr</tt> object. + */ + DoublePtrConst getDouble(const int_32 iset); + + /** Recover a boolean array from a dictionary-type Clcm object. + * <b>General rule:</b> Never try to modify, deallocate or free the object returned + * by <tt>getBool</tt>. This method is not available for file-type Clcm objects. + * @param key key identification of the boolean array in the dictionary + * @return array of boolean values stored as <tt>BoolPtr</tt> object. + */ + BoolPtrConst getBool(const std::string key); + + /** Recover a boolean array from a list-type Clcm object. + * <b>General rule:</b> Never try to modify, deallocate or free the object returned + * by <tt>getBool</tt>. This method is not available for file-type Clcm objects. + * @param iset index of the boolean array in the list. The first list element + * is stored at index 0. + * @return array of boolean values stored as <tt>BoolPtr</tt> object. + */ + BoolPtrConst getBool(const int_32 iset); + + /** Recover a complex array from a dictionary-type Clcm object. + * <b>General rule:</b> Never try to modify, deallocate or free the object returned + * by <tt>getComplex</tt>. This method is not available for file-type Clcm objects. + * @param key key identification of the complex array in the dictionary + * @return array of complex values stored as <tt>ComplexPtr</tt> object. + */ + ComplexPtrConst getComplex(const std::string key); + + /** Recover a complex array from a list-type Clcm object. + * <b>General rule:</b> Never try to modify, deallocate or free the object returned + * by <tt>getComplex</tt>. This method is not available for file-type Clcm objects. + * @param iset index of the complex array in the list. The first list element + * is stored at index 0. + * @return array of complex values stored as <tt>ComplexPtr</tt> object. + */ + ComplexPtrConst getComplex(const int_32 iset); + + /** Recover a vector-of-string pointer containing the keys of a dictionary-type Clcm + * object. <b>General rule:</b> Never try to modify, deallocate or free the vector-of-string + * returned by <tt>keys</tt>. This method is not available for file-type or list-type + * Clcm objects. + * @return <tt>StringVecPtr</tt> of a vector-of-string containing the dictionary keys + */ + StringVecPtr keys(); + + /** Store an integer array in a dictionary-type Clcm object. This method is not + * available for file-type Clcm objects. + * <p> + * <b>Example</b>: An integer array named <tt>"myIntArray"</tt> is inserted in + * Clcm object named <tt>multicompo</tt> using + * <pre> + * static int_32 myStaticArray[] = {33, 22, 11, 89}; + * IntPtr myIntPtr = IntPtr(new int_32[4]); + * for(int i = 0; i < 4; ++i) myIntPtr[i] = myStaticArray[i]; + * multicompo->put("myIntArray", myIntPtr, 4); + * </pre> + * @param key key identification of the block in the dictionary + * @param myArray integer array stored as <tt>IntPtr</tt> object. + * @param myLength number of components in integer array. + */ + void put(const std::string key, IntPtr myArray, const int_32 myLength); + + /** Store an integer array in a list-type Clcm object. This method is not available + * for file-type Clcm objects. + * @param iset index of the integer array in the list. The first list element + * is stored at index 0. + * @param myArray integer array stored as <tt>IntPtr</tt> object. + * @param myLength number of components in integer array. + */ + void put(const int_32 iset, IntPtr myArray, const int_32 myLength); + + /** Store a single precision real array in a dictionary-type Clcm object. This method + * is not available for file-type Clcm objects. + * @param key key identification of the block in the dictionary + * @param myArray single precision real array stored as <tt>FloatPtr</tt> object. + * @param myLength number of components in real array. + */ + void put(const std::string key, FloatPtr myArray, const int_32 myLength); + + /** Store a single precision real array in a list-type Clcm object. This method is + * not available for file-type Clcm objects. + * @param iset index of the real array in the list. The first list element + * is stored at index 0. + * @param myArray single precision real array stored as <tt>FloatPtr</tt> object. + * @param myLength number of components in real array. + */ + void put(const int_32 iset, FloatPtr myArray, const int_32 myLength); + + /** Store a string pointer in a dictionary-type Clcm object. This method is not available + * for file-type Clcm objects. + * @param key key identification of the character array in the dictionary + * @param myArray character information stored as <tt>StringPtr</tt> object. + */ + void put(const std::string key, StringPtr myArray); + + /** Store a string pointer in a list-type Clcm object. This method is not available for + * file-type Clcm objects. + * @param iset index of the string in the list. The first list element is stored at index 0. + * @param myArray character information stored as <tt>StringPtr</tt> object. + */ + void put(const int_32 iset, StringPtr myArray); + + /** Store a vector-of-string pointer in a dictionary-type Clcm object. + * This method is not available for file-type Clcm objects. + * @param key key identification of the character array in the dictionary + * @param myArray vector-of-string containing the character information stored as + * <tt>StringVecPtr</tt> object. + */ + void put(const std::string key, StringVecPtr myArray); + + /** Store a vector-of-string pointer in a list-type Clcm object. + * This method is not available for file-type Clcm objects. + * @param iset index of the character array in the list. The first list element + * is stored at index 0. + * @param myArray vector-of-string containing the character information stored as + * <tt>StringVecPtr</tt> object. + */ + void put(const int_32 iset, StringVecPtr myArray); + + /** Store a double precision real array in a dictionary-type Clcm object. This method is + * not available for file-type Clcm objects. + * @param key key identification of the double precision array in the dictionary + * @param myArray double precision array stored as <tt>DoublePtr</tt> object. + * @param myLength number of components in double precision array. + */ + void put(const std::string key, DoublePtr myArray, const int_32 myLength); + + /** Store a double precision real array in a list-type Clcm object. This method is + * not available for file-type Clcm objects. + * @param iset index of the double precision array in the list. The first list element + * is stored at index 0. + * @param myArray double precision array stored as <tt>DoublePtr</tt> object. + * @param myLength number of components in double precision array. + */ + void put(const int_32 iset, DoublePtr myArray, const int_32 myLength); + + /** Store a boolean array in a dictionary-type Clcm object. This method is not + * available for file-type Clcm objects. + * @param key key identification of the block in the dictionary + * @param myArray boolean array stored as <tt>BoolPtr</tt> object. + * @param myLength number of components in boolean array. + */ + void put(const std::string key, BoolPtr myArray, const int_32 myLength); + + /** Store a boolean array in a list-type Clcm object. This method is not + * available for file-type Clcm objects. + * @param iset index of the boolean array in the list. The first list element + * is stored at index 0. + * @param myArray boolean array stored as <tt>BoolPtr</tt> object. + * @param myLength number of components in boolean array. + */ + void put(const int_32 iset, BoolPtr myArray, const int_32 myLength); + + /** Store a complex array in a dictionary-type Clcm object. This method is not + * available for file-type Clcm objects. + * <p> + * <b>Example</b>: A complex array named <tt>"myComplArray"</tt> is inserted in + * Clcm object named <tt>multicompo</tt> using + * <pre> + * ComplexPtr myComplexPtr = ComplexPtr(new complex<float_32>[2]); + * myComplexPtr[0] = complex<float_32>(3.3, 8.9); + * myComplexPtr[1] = complex<float_32>(-3.3, 7.9); + * multicompo->put("myComplArray", myComplexPtr, 2); + * </pre> + * @param key key identification of the block in the dictionary + * @param myArray complex array stored as <tt>ComplexPtr</tt> object. + * @param myLength number of components in complex array. + */ + void put(const std::string key, ComplexPtr myArray, const int_32 myLength); + + /** Store a complex array in a list-type Clcm object. This method is not + * available for file-type Clcm objects. + * @param iset index of the complex array in the list. The first list element + * is stored at index 0. + * @param myArray complex array stored as <tt>ComplexPtr</tt> object. + * @param myLength number of components in complex array. + */ + void put(const int_32 iset, ComplexPtr myArray, const int_32 myLength); + + /** Store a daughter Clcm object in a dictionary-type Clcm object. This method is not + * available for file-type Clcm objects. + * @param key key identification of the block in the dictionary + * @param myClcm daughter Clcm object. + */ + void put(const std::string key, ClcmPtr myClcm); + + /** Store a daughter Clcm object in a list-type Clcm object. This method is not + * available for file-type Clcm objects. + * @param iset index of the complex array in the list. The first list element + * is stored at index 0. + * @param myClcm daughter Clcm object. + */ + void put(const int_32 iset, ClcmPtr myClcm); + + /** Extract the LCM structure. + * @return ANSI C pointer of the embedded LCM structure. + */ + lcm *extract(); + +private: + std::vector<AnyPtr> *global_list; // container for the global references + lcm *addr; // address of the LCM object + Clcm *root; // address of Clcm root object + std::ofstream aFile; // embedded file if type >= 3 + int_32 lrda; // used with direct access files only + std::string name; // object name + std::string path; // path to access the Clcm file to import + std::string nammy; // directory name inside LCM object + bool empty; // empty flag + int_32 ilong; // -1 (dictionary) or list length + int_32 objtype; // type of the object =1: LCM; =2: XSM; =3: binary Fortran file + // =4: ASCII Fortran file; =5: direct access Fortran file + int_32 access; // =0: closed object; =1: object in read/write mode + // =2: object in read-only mode + int_32 version; // original ganlib version of object + bool untoutched; // brand new object flag + bool isroot; // true if addr is pointing on the root object +}; // class Clcm + std::ostream & operator<<(std::ostream &, ClcmPtr); + +} // namespace ganlib +#endif diff --git a/Skin++/src/Cle2000.cxx b/Skin++/src/Cle2000.cxx new file mode 100755 index 0000000..c49b721 --- /dev/null +++ b/Skin++/src/Cle2000.cxx @@ -0,0 +1,104 @@ + +/*****************************************/ +/* C++ CLE-2000 OBJECT WRAPPER */ +/* AUTHOR: A. HEBERT ; 2012/10/07 */ +/*****************************************/ + +/* +Copyright (C) 2012 Ecole Polytechnique de Montreal + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. +*/ + +#include "Cle2000.hxx" + +using namespace std; +using namespace ganlib; +static ostringstream hsmg; + +ganlib::Cle2000::Cle2000(string sname) { + this->edit = 0; + this->procName = sname; + this->stack.reset(); +} +ganlib::Cle2000::Cle2000(string sname, int_32 edit) { + this->edit = edit; + this->procName = sname; + this->stack.reset(); +} +ganlib::Cle2000::Cle2000(string sname, LifoPtr jstack) { + this->edit = 0; + this->procName = sname; + this->stack = jstack; +} +ganlib::Cle2000::Cle2000(string sname, int_32 edit, LifoPtr jstack) { + this->edit = edit; + this->procName = sname; + this->stack = jstack; +} + +ganlib::Cle2000::~Cle2000() { + cout << "Cle2000 destructor called." << endl; +} + +void ganlib::Cle2000::setLifo(LifoPtr myLifo) { + this->stack = myLifo; +} + +void ganlib::Cle2000::exec() { + int_32 ier, ilevel = 1; + +// close the LCM objects + for (int_32 ipos=0; ipos<this->stack->getMax(); ++ipos) { + int_32 myTypeNode = this->stack->typeNode(ipos); + if ((myTypeNode == 3) || (myTypeNode == 4)) { + if (this->stack->accessNode(ipos) > 0) { + ClcmPtr myClcm; this->stack->node(ipos, myClcm); + try { + lcm *myLcmStructure = myClcm->extract(); + lifo *myLifo = this->stack->extract(); + lifo_node *myNode = clepos(&myLifo, ipos); + strcpy(myNode->OSname, myLcmStructure->hname); + lcmcl_c(&myLcmStructure, 1); + } catch(...) { + throw Cle2000Exception("Exception catched by lcmcl_c"); + } + } + } + } + +// call the parametrized procedure + try { + ier = cle2000_c(ilevel, &donmod, (char *)this->procName.c_str(), this->edit, + (lifo*)this->stack->extract()); + + } catch(...) { + throw Cle2000Exception("Exception catched by cle2000_c"); + } + if (ier != 0) { + hsmg << "Cle2000: cle2000 failure (" << this->procName << ".c2m). ier=" << ier; + throw Cle2000Exception(hsmg.str()); + } + +// reopen the LCM objects + for (int ipos=0; ipos<this->stack->getMax(); ++ipos) { + int_32 myTypeNode = this->stack->typeNode(ipos); + if ((myTypeNode == 3) || (myTypeNode == 4)) { + int_32 access = this->stack->accessNode(ipos); + if (access == 0) access=1; + ClcmPtr myClcm; this->stack->node(ipos, myClcm); + try { + lcm *myLcmStructure = myClcm->extract(); + int_32 myTypeNode = this->stack->typeNode(ipos); + string myOSname_str = this->stack->OSName(ipos); + char *myOSname = (char *)myOSname_str.c_str(); + lcmop_c(&myLcmStructure, myOSname, access, myTypeNode-2, 0); + } catch(...) { + throw Cle2000Exception("Exception catched by lcmop_c"); + } + } + } +} diff --git a/Skin++/src/Cle2000.hxx b/Skin++/src/Cle2000.hxx new file mode 100755 index 0000000..af869dd --- /dev/null +++ b/Skin++/src/Cle2000.hxx @@ -0,0 +1,96 @@ +/** + * Call a parametrized Cle2000 procedure. A Lifo object is used to manage + * input/output parameters for this CLE-2000 procedure. + * <P> + * + * @author Alain Hebert, Ecole Polytechnique de Montreal (2012) + */ +#ifndef Cle2000_HXX +#define Cle2000_HXX + +#include <cstddef> // for __GLIBCXX__ + +#ifdef __GLIBCXX__ // for memory management with shared_ptr +# include <tr1/memory> +#else +# ifdef __IBMCPP__ +# define __IBMCPP_TR1__ +# endif +# include <memory> +#endif + +#include "Cle2000Exception.hxx" +#include "Lifo.hxx" +extern "C" { +#include <dirent.h> +int_32 donmod(char *cmodul, int_32 nentry, char (*hentry)[13], int_32 *ientry, + int_32 *jentry, lcm **kentry, char (*hparam)[73]); +} +#define Cle2000Ptr std::shared_ptr<Cle2000> + +namespace ganlib { + +/** + * Call a parametrized CLE-2000 procedure. A CLE-2000 procedure is implemented + * as a 80-column ascii file. The name of that file must have a <tt>".c2m"</tt> + * suffix. A Lifo object is used to manage input/output parameters for this + * CLE-2000 procedure. + * <P> + * + * @author Alain Hebert, Ecole Polytechnique de Montreal (2012) + */ +class Cle2000 { +public: + /** use this constructor to create a new CLE-2000 object + * @param sname string containing the name of the ascii file containing the CLE-2000 + * procedure (without the <tt>".c2m"</tt> suffix) + */ + Cle2000(std::string sname); + + /** use this constructor to create a new Cle2000 object + * @param sname string containing the name of the ascii file containing the CLE-2000 + * procedure (without the <tt>".c2m"</tt> suffix) + * @param edit user-defined edition index. Increasing value of <tt>edit</tt> will + * cause increasing amount of listing information. Set <tt>edit</tt> to zero to avoid + * listing information. + */ + Cle2000(std::string sname, int_32 edit); + + /** use this constructor to create a new Cle2000 object with an embedded Lifo stack + * @param sname string containing the name of the ascii file containing the CLE-2000 + * procedure (without the <tt>".c2m"</tt> suffix) + * @param jstack Lifo stack to include in Cle2000 object + */ + Cle2000(std::string sname, LifoPtr jstack); + + /** use this constructor to create a new Cle2000 object with an embedded Lifo stack + * @param sname string containing the name of the ascii file containing the CLE-2000 + * procedure (without the <tt>".c2m"</tt> suffix) + * @param edit user-defined edition index. Increasing value of <tt>edit</tt> will + * cause increasing amount of listing information. Set <tt>edit</tt> to zero to avoid + * listing information. + * @param jstack Lifo stack to include in Cle2000 object + */ + Cle2000(std::string sname, int_32 edit, LifoPtr jstack); + + /** Close and destroy a Cle2000 object. + */ + ~Cle2000(); + + /** attach a lifo stack to the Cle2000 object + * @param myLifo Lifo stack containing input/output parameters + */ + void setLifo(LifoPtr myLifo); + + /** call the native CLE-2000 procedure + */ + void exec(); + +private: + std::string procName; + int_32 edit; + LifoPtr stack; +}; // class Cle2000 + +} // namespace ganlib +#endif diff --git a/Skin++/src/Cle2000Exception.cxx b/Skin++/src/Cle2000Exception.cxx new file mode 100755 index 0000000..216825f --- /dev/null +++ b/Skin++/src/Cle2000Exception.cxx @@ -0,0 +1,22 @@ + +/*****************************************/ +/* EXCEPTION CLASS FOR Lifo */ +/* AUTHOR: A. HEBERT ; 2012/10/07 */ +/*****************************************/ + +/* +Copyright (C) 2012 Ecole Polytechnique de Montreal + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. +*/ + +#include "Cle2000Exception.hxx" +using namespace std; +using namespace ganlib; + +ganlib::Cle2000Exception::Cle2000Exception(const string& msg) : runtime_error(msg) { + cout << "A Cle2000Exception was thrown with message: " << msg << endl; +} diff --git a/Skin++/src/Cle2000Exception.hxx b/Skin++/src/Cle2000Exception.hxx new file mode 100755 index 0000000..5c9020a --- /dev/null +++ b/Skin++/src/Cle2000Exception.hxx @@ -0,0 +1,22 @@ +/** + * Exception class for Cle2000 wrapper uses in C++ + * <P> + * + * @author Alain Hebert, Ecole Polytechnique de Montreal (2012) + */ +#ifndef Cle2000Exception_HXX +#define Cle2000Exception_HXX + +#include <string> +#include <iostream> +#include <stdexcept> + +namespace ganlib { + +class Cle2000Exception : public std::runtime_error { +public: + Cle2000Exception(const std::string& msg = ""); +}; // class Cle2000Exception */ + +} // namespace ganlib +#endif diff --git a/Skin++/src/LCMexception.cxx b/Skin++/src/LCMexception.cxx new file mode 100755 index 0000000..08960f3 --- /dev/null +++ b/Skin++/src/LCMexception.cxx @@ -0,0 +1,22 @@ + +/*****************************************/ +/* EXCEPTION CLASS FOR LCM */ +/* AUTHOR: A. HEBERT ; 2010/12/31 */ +/*****************************************/ + +/* +Copyright (C) 2010 Ecole Polytechnique de Montreal + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. +*/ + +#include "LCMexception.hxx" +using namespace std; +using namespace ganlib; + +ganlib::LCMexception::LCMexception(const string& msg) : runtime_error(msg) { + cout << "A LCMexception was thrown with message: " << msg << endl; +} diff --git a/Skin++/src/LCMexception.hxx b/Skin++/src/LCMexception.hxx new file mode 100755 index 0000000..041d334 --- /dev/null +++ b/Skin++/src/LCMexception.hxx @@ -0,0 +1,22 @@ +/** + * Exception class for LCM uses in C++ + * <P> + * + * @author Alain Hebert, Ecole Polytechnique de Montreal (2010) + */ +#ifndef LCMexception_HXX +#define LCMexception_HXX + +#include <string> +#include <iostream> +#include <stdexcept> + +namespace ganlib { + +class LCMexception : public std::runtime_error { +public: + LCMexception(const std::string& msg = ""); +}; // class LCMexception */ + +} // namespace ganlib +#endif diff --git a/Skin++/src/Lifo.cxx b/Skin++/src/Lifo.cxx new file mode 100755 index 0000000..4451d90 --- /dev/null +++ b/Skin++/src/Lifo.cxx @@ -0,0 +1,691 @@ + +/*****************************************/ +/* C++ LIFO STACK OBJECT WRAPPER */ +/* AUTHOR: A. HEBERT ; 2012/10/07 */ +/*****************************************/ + +/* +Copyright (C) 2012 Ecole Polytechnique de Montreal + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. +*/ + +#include "Lifo.hxx" + +using namespace std; +using namespace ganlib; +static ostringstream hsmg; + +ganlib::Lifo::Lifo() { + cout << "New Lifo object constructed.'" << endl; + try { + cleopn(&(this->addr)); + } catch(...) { + throw LifoException("Exception catched by cleopn"); + } + this->global_list = new vector<ClcmPtr>; +} + +ganlib::Lifo::~Lifo() { + cout << "Lifo destructor called (" << this->getMax() << " nodes remaining)." << endl; + int_32 nitma = clecls(&(this->addr)); + if(nitma != 0) { + char hsmg[132]; + snprintf(hsmg,42,"%s\n","Lifo destruction failure: Lifo not empty"); + xabort_c(hsmg); + } + delete this->global_list; +} + +//---------------------------------------------------------------------- +//-- pop -- +//---------------------------------------------------------------------- + +void ganlib::Lifo::pop() { + lifo_node *myNode; + if (this->addr->nup == 0) throw LifoException("no nodes to pop from stack(0)"); + try { + myNode = clepos(&(this->addr), this->addr->nup-1); + } catch(...) { + throw LifoException("Exception catched by clepos(1)"); + } + clepop(&(this->addr)); + free(myNode); +} + +void ganlib::Lifo::pop(int_32 &myInteger) { + lifo_node *myNode; + if (this->addr->nup == 0) throw LifoException("no nodes to pop from stack(1)"); + try { + myNode = clepos(&(this->addr), this->addr->nup-1); + } catch(...) { + throw LifoException("Exception catched by clepos(1)"); + } + if (myNode->type != 11) { + hsmg << "pop() expecting an integer value (" << myNode->type << " found)"; + throw LifoException(hsmg.str()); + } + myInteger = myNode->value.ival; + clepop(&(this->addr)); + free(myNode); +} + +void ganlib::Lifo::pop(float_32 &myFloat) { + lifo_node *myNode; + if (this->addr->nup == 0) throw LifoException("no nodes to pop from stack(2)"); + try { + myNode = clepos(&(this->addr), this->addr->nup-1); + } catch(...) { + throw LifoException("Exception catched by clepos(2)"); + } + if (myNode->type != 12) { + hsmg << "pop() expecting a real value (" << myNode->type << " found)"; + throw LifoException(hsmg.str()); + } + myFloat = myNode->value.fval; + clepop(&(this->addr)); + free(myNode); +} + +void ganlib::Lifo::pop(string &myString) { + lifo_node *myNode; + if (this->addr->nup == 0) throw LifoException("no nodes to pop from stack(3)"); + try { + myNode = clepos(&(this->addr), this->addr->nup-1); + } catch(...) { + throw LifoException("Exception catched by clepos(3)"); + } + if (myNode->type != 13) { + hsmg << "pop() expecting a string value (" << myNode->type << " found)"; + throw LifoException(hsmg.str()); + } + myString = string(myNode->value.hval); + clepop(&(this->addr)); + free(myNode); +} + +void ganlib::Lifo::pop(double &myDouble) { + lifo_node *myNode; + if (this->addr->nup == 0) throw LifoException("no nodes to pop from stack(4)"); + try { + myNode = clepos(&(this->addr), this->addr->nup-1); + } catch(...) { + throw LifoException("Exception catched by clepos(4)"); + } + if (myNode->type != 14) { + hsmg << "pop() expecting a double precision value (" << myNode->type << " found)"; + throw LifoException(hsmg.str()); + } + myDouble = myNode->value.dval; + clepop(&(this->addr)); + free(myNode); +} + +void ganlib::Lifo::pop(bool &myBool) { + lifo_node *myNode; + if (this->addr->nup == 0) throw LifoException("no nodes to pop from stack(5)"); + try { + myNode = clepos(&(this->addr), this->addr->nup-1); + } catch(...) { + throw LifoException("Exception catched by clepos(5)"); + } + if (myNode->type != 15) { + hsmg << "pop() expecting a boolean value (" << myNode->type << " found)"; + throw LifoException(hsmg.str()); + } + myBool = (myNode->value.ival == 1); + clepop(&(this->addr)); + free(myNode); +} + +void ganlib::Lifo::pop(ClcmPtr &myClcm) { + lifo_node *myNode; + if (this->addr->nup == 0) throw LifoException("no nodes to pop from stack(6)"); + try { + myNode = clepos(&(this->addr), this->addr->nup-1); + } catch(...) { + throw LifoException("Exception catched by clepos(6)"); + } + if ((myNode->type != 3) && (myNode->type != 4)) { + hsmg << "pop() expecting a LCM or XSM object (" << myNode->type << " found)"; + throw LifoException(hsmg.str()); + } + lcm *myLcm = myNode->value.mylcm; + myClcm = ClcmPtr(new Clcm(myLcm, myNode->type, myNode->access, myNode->OSname)); + clepop(&(this->addr)); + free(myNode); +} + +void ganlib::Lifo::pop(string myFile, string stype) { + lifo_node *myNode; + if (this->addr->nup == 0) throw LifoException("no nodes to pop from stack(7)"); + try { + myNode = clepos(&(this->addr), this->addr->nup-1); + } catch(...) { + throw LifoException("Exception catched by clepos(7)"); + } + if (myNode->type == 5) { + stype = "BINARY"; + } else if (myNode->type == 6) { + stype = "ASCII"; + } else if (myNode->type == 7) { + stype = "DA"; + } else { + hsmg << "pop(): unknown file type"; + throw LifoException(hsmg.str()); + } + myFile = string(myNode->value.hval); + clepop(&(this->addr)); + free(myNode); +} + +//---------------------------------------------------------------------- +//-- push -- +//---------------------------------------------------------------------- + +void ganlib::Lifo::push(string sname, const int_32 myInteger) { + lifo_node * myNode = (lifo_node *) malloc(sizeof(lifo_node)); + strcpy(myNode->name, (char *)sname.c_str()); myNode->type = 11; myNode->value.ival = myInteger; + try { + clepush(&(this->addr), myNode); + } catch(...) { + throw LifoException("Exception catched by clepush(1)"); + } +} + +void ganlib::Lifo::push(string sname, const float_32 myFloat) { + lifo_node * myNode = (lifo_node *) malloc(sizeof(lifo_node)); + strcpy(myNode->name, (char *)sname.c_str()); myNode->type = 12; myNode->value.fval = myFloat; + try { + clepush(&(this->addr), myNode); + } catch(...) { + throw LifoException("Exception catched by clepush(2)"); + } +} + +void ganlib::Lifo::push(string sname, const string myString) { + lifo_node * myNode = (lifo_node *) malloc(sizeof(lifo_node)); + strcpy(myNode->name, (char *)sname.c_str()); myNode->type = 13; + strcpy(myNode->value.hval, (char *)myString.c_str()); + try { + clepush(&(this->addr), myNode); + } catch(...) { + throw LifoException("Exception catched by clepush(3)"); + } +} + +void ganlib::Lifo::push(string sname, const double myDouble) { + lifo_node * myNode = (lifo_node *) malloc(sizeof(lifo_node)); + strcpy(myNode->name, (char *)sname.c_str()); myNode->type = 14; myNode->value.dval = myDouble; + try { + clepush(&(this->addr), myNode); + } catch(...) { + throw LifoException("Exception catched by clepush(4)"); + } +} + +void ganlib::Lifo::push(string sname, bool myBool) { + lifo_node * myNode = (lifo_node *) malloc(sizeof(lifo_node)); + int_32 ibool = 0; if (myBool) ibool = 1; + strcpy(myNode->name, (char *)sname.c_str()); myNode->type = 15; myNode->value.ival = ibool; + try { + clepush(&(this->addr), myNode); + } catch(...) { + throw LifoException("Exception catched by clepush(5)"); + } +} + +void ganlib::Lifo::push(string sname, ClcmPtr myClcm) { + lifo_node * myNode = (lifo_node *) malloc(sizeof(lifo_node)); + strcpy(myNode->name, (char *)sname.c_str()); + myNode->type = myClcm->getType()+2; + myNode->access = myClcm->getAccess(); + lcm *myLcm = myClcm->extract(); + myNode->value.mylcm = myLcm; + strcpy(myNode->OSname, (char *)myClcm->getName().c_str()); + try { + clepush(&(this->addr), myNode); + } catch(...) { + throw LifoException("Exception catched by clepush(6)"); + } + (this->global_list)->push_back(myClcm); +} + +void ganlib::Lifo::push(string sname, string myFile, string stype) { + lifo_node * myNode = (lifo_node *) malloc(sizeof(lifo_node)); + strcpy(myNode->name, (char *)sname.c_str()); + if (stype == "BINARY") { + myNode->type = 5; + } else if (stype == "ASCII") { + myNode->type = 6; + } else if (stype == "DA") { + myNode->type = 7; + } else { + hsmg << "push() unknown file type (" << stype << ")"; + throw LifoException(hsmg.str()); + } + strcpy(myNode->value.hval, (char *)myFile.c_str()); + strcpy(myNode->OSname, (char *)myFile.c_str()); + try { + clepush(&(this->addr), myNode); + } catch(...) { + throw LifoException("Exception catched by clepush(7)"); + } +} + +void ganlib::Lifo::push(string sname, string myFile, string stype, string OSname) { + lifo_node * myNode = (lifo_node *) malloc(sizeof(lifo_node)); + strcpy(myNode->name, (char *)sname.c_str()); + if (stype == "BINARY") { + myNode->type = 5; + } else if (stype == "ASCII") { + myNode->type = 6; + } else if (stype == "DA") { + myNode->type = 7; + } else { + hsmg << "push(): unknown file type (" << stype << ")"; + throw LifoException(hsmg.str()); + } + strcpy(myNode->value.hval, (char *)myFile.c_str()); + strcpy(myNode->OSname, (char *)OSname.c_str()); + try { + clepush(&(this->addr), myNode); + } catch(...) { + throw LifoException("Exception catched by clepush(8)"); + } +} + +//---------------------------------------------------------------------- +//-- pushEmpty -- +//---------------------------------------------------------------------- + +void ganlib::Lifo::pushEmpty(string sname, string nodeType) { + lifo_node * myNode = (lifo_node *) malloc(sizeof(lifo_node)); + strcpy(myNode->name, (char *)sname.c_str()); + if (nodeType == "I") { + myNode->type = -11 ; + } else if (nodeType == "F") { + myNode->type = -12 ; + } else if (nodeType == "D") { + myNode->type = -13 ; + } else if (nodeType == "S") { + myNode->type = -14 ; + } else if (nodeType == "B") { + myNode->type = -15 ; + } else if (nodeType == "LCM") { + myNode->type = -3 ; + myNode->access = 0 ; + strcpy(myNode->OSname, (char *)sname.c_str()); + } else if (nodeType == "XSM") { + myNode->type = -4 ; + myNode->access = 0 ; + strcpy(myNode->OSname, (char *)sname.c_str()); + } else if (nodeType == "BINARY") { + myNode->type = -5 ; + myNode->access = 0 ; + } else if (nodeType == "ASCII") { + myNode->type = -6 ; + myNode->access = 0 ; + } else if (nodeType == "DA") { + myNode->type = -7 ; + myNode->access = 0 ; + } else { + hsmg << nodeType << "is an invalid type in pushEmpty"; + throw LifoException(hsmg.str()); + } + try { + clepush(&(this->addr), myNode); + } catch(...) { + throw LifoException("Exception catched by clepush(9)"); + } +} + +void ganlib::Lifo::pushEmpty(string sname, string nodeType, string OSname) { + lifo_node * myNode = (lifo_node *) malloc(sizeof(lifo_node)); + strcpy(myNode->name, (char *)sname.c_str()); + if (nodeType == "XSM") { + myNode->type = -4 ; + myNode->access = 0 ; + } else if (nodeType == "BINARY") { + myNode->type = -5 ; + myNode->access = 0 ; + } else if (nodeType == "ASCII") { + myNode->type = -6 ; + myNode->access = 0 ; + } else if (nodeType == "DA") { + myNode->type = -7 ; + myNode->access = 0 ; + } else { + hsmg << nodeType << "is an invalid type in pushEmpty"; + throw LifoException(hsmg.str()); + } + strcpy(myNode->OSname, (char *)OSname.c_str()); + try { + clepush(&(this->addr), myNode); + } catch(...) { + throw LifoException("Exception catched by clepush(9)"); + } +} + +//---------------------------------------------------------------------- +//-- node by position -- +//---------------------------------------------------------------------- + +void ganlib::Lifo::node(int_32 ipos, int_32 &myInteger) { + lifo_node *myNode; + if (this->addr->nup == 0) throw LifoException("no nodes to recover from stack(11)"); + try { + myNode = clepos(&(this->addr), ipos); + } catch(...) { + throw LifoException("Exception catched by clepos(11)"); + } + if (myNode->type != 11) { + hsmg << "node() expecting an integer value (" << myNode->type << " found)"; + throw LifoException(hsmg.str()); + } + myInteger = myNode->value.ival; +} + +void ganlib::Lifo::node(int_32 ipos, float_32 &myFloat) { + lifo_node *myNode; + if (this->addr->nup == 0) throw LifoException("no nodes to recover from stack(12)"); + try { + myNode = clepos(&(this->addr), ipos); + } catch(...) { + throw LifoException("Exception catched by clepos(12)"); + } + if (myNode->type != 12) { + hsmg << "node() expecting a real value (" << myNode->type << " found)"; + throw LifoException(hsmg.str()); + } + myFloat = myNode->value.fval; +} + +void ganlib::Lifo::node(int_32 ipos, string &myString) { + lifo_node *myNode; + if (this->addr->nup == 0) throw LifoException("no nodes to recover from stack(13)"); + try { + myNode = clepos(&(this->addr), ipos); + } catch(...) { + throw LifoException("Exception catched by clepos(13)"); + } + if (myNode->type != 13) { + hsmg << "node() expecting a string value (" << myNode->type << " found)"; + throw LifoException(hsmg.str()); + } + myString = string(myNode->value.hval); +} + +void ganlib::Lifo::node(int_32 ipos, double &myDouble) { + lifo_node *myNode; + if (this->addr->nup == 0) throw LifoException("no nodes to recover from stack(14)"); + try { + myNode = clepos(&(this->addr), ipos); + } catch(...) { + throw LifoException("Exception catched by clepos(14)"); + } + if (myNode->type != 14) { + hsmg << "node() expecting a double precision value (" << myNode->type << " found)"; + throw LifoException(hsmg.str()); + } + myDouble = myNode->value.dval; +} + +void ganlib::Lifo::node(int_32 ipos, bool &myBool) { + lifo_node *myNode; + if (this->addr->nup == 0) throw LifoException("no nodes to recover from stack(15)"); + try { + myNode = clepos(&(this->addr), ipos); + } catch(...) { + throw LifoException("Exception catched by clepos(15)"); + } + if (myNode->type != 11) { + hsmg << "node() expecting a boolean value (" << myNode->type << " found)"; + throw LifoException(hsmg.str()); + } + myBool = (myNode->value.ival == 1); +} + +void ganlib::Lifo::node(int_32 ipos, ClcmPtr &myClcm) { + lifo_node *myNode; + if (this->addr->nup == 0) throw LifoException("no nodes to recover from stack(16)"); + try { + myNode = clepos(&(this->addr), ipos); + } catch(...) { + throw LifoException("Exception catched by clepos(16)"); + } + if ((myNode->type != 3) && (myNode->type != 4)) { + hsmg << "node() expecting a LCM or XSM object (" << myNode->type << " found)"; + throw LifoException(hsmg.str()); + } + lcm *myLcm = myNode->value.mylcm; + myClcm = ClcmPtr(new Clcm(myLcm, myNode->type, myNode->access, myNode->OSname)); +} + +void ganlib::Lifo::node(int_32 ipos, string myFile, string stype) { + lifo_node *myNode; + if (this->addr->nup == 0) throw LifoException("no nodes to pop from stack(17)"); + try { + myNode = clepos(&(this->addr), ipos); + } catch(...) { + throw LifoException("Exception catched by clepos(17)"); + } + if (myNode->type == 5) { + stype = "BINARY"; + } else if (myNode->type == 6) { + stype = "ASCII"; + } else if (myNode->type == 7) { + stype = "DA"; + } else { + hsmg << "node(): unknown file type"; + throw LifoException(hsmg.str()); + } + myFile = string(myNode->value.hval); +} + +//---------------------------------------------------------------------- +//-- node by name -- +//---------------------------------------------------------------------- + +void ganlib::Lifo::node(string sname, int_32 &myInteger) { + lifo_node *myNode; + if (this->addr->nup == 0) throw LifoException("no nodes to recover from stack(21)"); + try { + myNode = clenode(&(this->addr), sname.c_str()); + } catch(...) { + throw LifoException("Exception catched by clenode(21)"); + } + if (myNode->type != 11) { + hsmg << "node() expecting an integer value (" << myNode->type << " found)"; + throw LifoException(hsmg.str()); + } + myInteger = myNode->value.ival; +} + +void ganlib::Lifo::node(string sname, float_32 &myFloat) { + lifo_node *myNode; + if (this->addr->nup == 0) throw LifoException("no nodes to recover from stack(22)"); + try { + myNode = clenode(&(this->addr), sname.c_str()); + } catch(...) { + throw LifoException("Exception catched by clenode(22)"); + } + if (myNode->type != 12) { + hsmg << "node() expecting a real value (" << myNode->type << " found)"; + throw LifoException(hsmg.str()); + } + myFloat = myNode->value.fval; +} + +void ganlib::Lifo::node(string sname, string &myString) { + lifo_node *myNode; + if (this->addr->nup == 0) throw LifoException("no nodes to recover from stack(23)"); + try { + myNode = clenode(&(this->addr), sname.c_str()); + } catch(...) { + throw LifoException("Exception catched by clenode(23)"); + } + if (myNode->type != 13) { + hsmg << "node() expecting a string value (" << myNode->type << " found)"; + throw LifoException(hsmg.str()); + } + myString = string(myNode->value.hval); +} + +void ganlib::Lifo::node(string sname, double &myDouble) { + lifo_node *myNode; + if (this->addr->nup == 0) throw LifoException("no nodes to recover from stack(24)"); + try { + myNode = clenode(&(this->addr), sname.c_str()); + } catch(...) { + throw LifoException("Exception catched by clenode(24)"); + } + if (myNode->type != 14) { + hsmg << "node() expecting a double precision value (" << myNode->type << " found)"; + throw LifoException(hsmg.str()); + } + myDouble = myNode->value.dval; +} + +void ganlib::Lifo::node(string sname, bool &myBool) { + lifo_node *myNode; + if (this->addr->nup == 0) throw LifoException("no nodes to recover from stack(25)"); + try { + myNode = clenode(&(this->addr), sname.c_str()); + } catch(...) { + throw LifoException("Exception catched by clenode(25)"); + } + if (myNode->type != 11) { + hsmg << "node() expecting a boolean value (" << myNode->type << " found)"; + throw LifoException(hsmg.str()); + } + myBool = (myNode->value.ival == 1); +} + +void ganlib::Lifo::node(string sname, ClcmPtr &myClcm) { + lifo_node *myNode; + if (this->addr->nup == 0) throw LifoException("no nodes to recover from stack(26)"); + try { + myNode = clenode(&(this->addr), sname.c_str()); + } catch(...) { + throw LifoException("Exception catched by clenode(26)"); + } + if ((myNode->type != 3) && (myNode->type != 4)) { + hsmg << "node() expecting a LCM or XSM object (" << myNode->type << " found)"; + throw LifoException(hsmg.str()); + } + lcm *myLcm = myNode->value.mylcm; + myClcm = ClcmPtr(new Clcm(myLcm, myNode->type, myNode->access, myNode->OSname)); +} + +void ganlib::Lifo::node(string sname, string myFile, string stype) { + lifo_node *myNode; + if (this->addr->nup == 0) throw LifoException("no nodes to pop from stack(27)"); + try { + myNode = clenode(&(this->addr), sname.c_str()); + } catch(...) { + throw LifoException("Exception catched by clenode(27)"); + } + if (myNode->type == 5) { + stype = "BINARY"; + } else if (myNode->type == 6) { + stype = "ASCII"; + } else if (myNode->type == 7) { + stype = "DA"; + } else { + hsmg << "node(): unknown file type"; + throw LifoException(hsmg.str()); + } + myFile = string(myNode->value.hval); +} + +//---------------------------------------------------------------------- + +int_32 ganlib::Lifo::getMax() { + return this->addr->nup; +} + +int_32 ganlib::Lifo::typeNode(int_32 ipos) { + lifo_node *myNode; + try { + myNode = clepos(&(this->addr), ipos); + } catch(...) { + throw LifoException("Exception catched by clepos(51)"); + } + return myNode->type; +} + +int_32 ganlib::Lifo::accessNode(int_32 ipos) { + lifo_node *myNode; + try { + myNode = clepos(&(this->addr), ipos); + } catch(...) { + throw LifoException("Exception catched by clepos(52)"); + } + return myNode->access; +} + +string ganlib::Lifo::OSName(int_32 ipos) { + lifo_node *myNode; + try { + myNode = clepos(&(this->addr), ipos); + } catch(...) { + throw LifoException("Exception catched by clepos(53)"); + } + return myNode->OSname; +} + +string ganlib::Lifo::Name(int_32 ipos) { + lifo_node *myNode; + try { + myNode = clepos(&(this->addr), ipos); + } catch(...) { + throw LifoException("Exception catched by clepos(54)"); + } + return myNode->name; +} + +int_32 ganlib::Lifo::typeNode(string sname) { + lifo_node *myNode; + try { + myNode = clenode(&(this->addr), sname.c_str()); + } catch(...) { + throw LifoException("Exception catched by clenode(55)"); + } + return myNode->type; +} + +int_32 ganlib::Lifo::accessNode(string sname) { + lifo_node *myNode; + try { + myNode = clenode(&(this->addr), sname.c_str()); + } catch(...) { + throw LifoException("Exception catched by clenode(56)"); + } + return myNode->access; +} + +string ganlib::Lifo::OSName(string sname) { + lifo_node *myNode; + try { + myNode = clenode(&(this->addr), sname.c_str()); + } catch(...) { + throw LifoException("Exception catched by clenode(57)"); + } + return myNode->OSname; +} + +void ganlib::Lifo::lib() { + try { + clelib(&(this->addr)); + } catch(...) { + throw LifoException("Exception catched by clelib"); + } +} + +lifo *ganlib::Lifo::extract() { + return this->addr; +} diff --git a/Skin++/src/Lifo.hxx b/Skin++/src/Lifo.hxx new file mode 100755 index 0000000..78a6836 --- /dev/null +++ b/Skin++/src/Lifo.hxx @@ -0,0 +1,373 @@ +/** + * This class is an implementation of the C++ bindings for a Lifo + * stack, as required by the Cle-2000 class. + * Lifo capabilities are available for a program written in C++ + * by using methods belonging to the Lifo class. + * <P> A Lifo object in C++ can encapsulate a native Lifo stack + * using the GANLIB5 API in ANSI C + * <P> + * + * @author Alain Hebert, Ecole Polytechnique de Montreal (2012) + */ +#ifndef Lifo_HXX +#define Lifo_HXX + +#include <cstddef> // for __GLIBCXX__ + +#ifdef __GLIBCXX__ // for memory management with shared_ptr +# include <tr1/memory> +#else +# ifdef __IBMCPP__ +# define __IBMCPP_TR1__ +# endif +# include <memory> +#endif + +#include "LifoException.hxx" +#include "Clcm.hxx" +extern "C" { +#include <dirent.h> +#include "cle2000.h" +} +#define LifoPtr std::shared_ptr<Lifo> + +namespace ganlib { + +/** + * This class is an implementation of the C++/shared_ptr bindings for a last-in-first-out + * (lifo) stack used with CLE-2000. Lifo management capabilities for a program + * written in C++ are available by using methods belonging to the Lifo class. + * These methods encapsulate the lifo API calls used as "extern"C" functions. + * <P> A Lifo object in C++ can encapsulate a native lifo stack used to + * manage CLE-2000 parameters. + * <P> A lifo stack can contain defined or undefined (empty) nodes; used to represent + * known or unknown parameters, respectively. + * <P> <I>Note:</I> There is a constraint_32 in CLE-2000. LCM (or XSM) objects and files + * must be pushed before single-value nodes in the stack. + * <P> + * + * @author Alain Hebert, Ecole Polytechnique de Montreal (2012) + */ +class Lifo { +public: + /** + * Use this constructor to create an empty Lifo object. + */ + Lifo(); + + /** Close and destroy a Lifo object. + */ + ~Lifo(); + + /** Pop the value on top of the Lifo stack without recovering it. If the node is empty, an + * exception is thrown + */ + void pop(); + + /** Pop the integer value on top of the Lifo stack. If the node is empty or if the argument type + * is wrong, an exception is thrown + * @param myInteger integer value node to pop from the lifo stack. + */ + void pop(int_32 &myInteger); + + /** Pop the real value on top of the Lifo stack. If the node is empty or if the argument type + * is wrong, an exception is thrown + * @param myFloat real value node to pop from the lifo stack. + */ + void pop(float_32 &myFloat); + + /** Pop the character string on top of the Lifo stack. If the node is empty or if the argument type + * is wrong, an exception is thrown + * @param myString character string node (limited to 72 characters) to pop from the lifo stack. + */ + void pop(std::string &myString); + + /** Pop the double precision value on top of the Lifo stack. If the node is empty or if the argument type + * is wrong, an exception is thrown + * @param myDouble double precision value node to pop from the lifo stack. + */ + void pop(double &myDouble); + + /** Pop the boolean value on top of the Lifo stack. If the node is empty or if the argument type + * is wrong, an exception is thrown + * @param myBool boolean value node to pop from the lifo stack. + */ + void pop(bool &myBool); + + /** Pop the ClcmPtr object on top of the Lifo stack. If the node is empty or if the argument type + * is wrong, an exception is thrown + * @param myClcm LCM object node to pop from the lifo stack. + */ + void pop(ClcmPtr &myClcm); + + /** Pop the file object on top of the Lifo stack. If the node is empty or if the argument type + * is wrong, an exception is thrown + * @param myFile operating system (OS) name (limited to 72 characters) associated to the file object + * node to pop from the lifo stack. + * @param stype type of file. This variable is selected by <tt>pop</tt> among the + * following values: + * <ul><dl> + * <dt> <tt>"BINARY"</tt> <dd> binary sequential file + * <dt> <tt>"ASCII"</tt> <dd> ACSII sequential file + * <dt> <tt>"DA"</tt> <dd> binary direct-access file (with 128-word records)</ul> + */ + void pop(std::string myFile, std::string stype); + + /** Return the integer value node with a given position. If the node is empty or if the argument type + * is wrong, an exception is thrown. The lifo stack is not modified + * @param ipos node position in lifo stack + * @param myInteger integer value node. + */ + void node(int_32 ipos, int_32 &myInteger); + + /** Return the real value node with a given position. If the node is empty or if the argument type + * is wrong, an exception is thrown. The lifo stack is not modified + * @param ipos node position in lifo stack + * @param myFloat real value node. + */ + void node(int_32 ipos, float_32 &myFloat); + + /** Return the character string node with a given position. If the node is empty or if the argument type + * is wrong, an exception is thrown. The lifo stack is not modified + * @param ipos node position in lifo stack + * @param myString character string node (limited to 72 characters). + */ + void node(int_32 ipos, std::string &myString); + + /** Return the double precision value node with a given position. If the node is empty or if the argument type + * is wrong, an exception is thrown. The lifo stack is not modified + * @param ipos node position in lifo stack + * @param myDouble double precision value node. + */ + void node(int_32 ipos, double &myDouble); + + /** Return the boolean value node with a given position. If the node is empty or if the argument type + * is wrong, an exception is thrown. The lifo stack is not modified + * @param ipos node position in lifo stack + * @param myBool integer value node. + */ + void node(int_32 ipos, bool &myBool); + + /** Return the ClcmPtr object node with a given position. If the node is empty or if the argument type + * is wrong, an exception is thrown. The lifo stack is not modified + * @param ipos node position in lifo stack + * @param myClcm ClcmPtr object node. + */ + void node(int_32 ipos, ClcmPtr &myClcm); + + /** Return the file object node with a given position. If the node is empty or if the argument type + * is wrong, an exception is thrown. The lifo stack is not modified + * @param ipos node position in lifo stack + * @param node operating system (OS) name (limited to 72 characters) associated to the file object + * node to pop from the lifo stack. + * @param stype type of LCM object or file. This variable is selected by <tt>pop</tt> among the + * following values: + * <ul><dl> + * <dt> <tt>"BINARY"</tt> <dd> binary sequential file + * <dt> <tt>"ASCII"</tt> <dd> ACSII sequential file + * <dt> <tt>"DA"</tt> <dd> binary direct-access file (with 128-word records)</ul> + */ + void node(int_32 ipos, std::string node, std::string stype); + + /** Return the integer value node with a given name. If the node is empty or if the argument type + * is wrong, an exception is thrown. The lifo stack is not modified + * @param sname node name (limited to 12 characters) + * @param myInteger integer value node. + */ + void node(std::string sname, int_32 &myInteger); + + /** Return the real value node with a given name. If the node is empty or if the argument type + * is wrong, an exception is thrown. The lifo stack is not modified + * @param sname node name (limited to 12 characters) + * @param myFloat real value node. + */ + void node(std::string sname, float_32 &myFloat); + + /** Return the character string node with a given name. If the node is empty or if the argument type + * is wrong, an exception is thrown. The lifo stack is not modified + * @param sname node name (limited to 12 characters) + * @param myString character string node (limited to 72 characters). + */ + void node(std::string sname, std::string &myString); + + /** Return the double precision value node with a given name. If the node is empty or if the argument type + * is wrong, an exception is thrown. The lifo stack is not modified + * @param sname node name (limited to 12 characters) + * @param myDouble double precision value node. + */ + void node(std::string sname, double &myDouble); + + /** Return the boolean value node with a given name. If the node is empty or if the argument type + * is wrong, an exception is thrown. The lifo stack is not modified + * @param sname node name (limited to 12 characters) + * @param myBool integer value node. + */ + void node(std::string sname, bool &myBool); + + /** Return the ClcmPtr object node with a given name. If the node is empty or if the argument type + * is wrong, an exception is thrown. The lifo stack is not modified + * @param sname node name (limited to 12 characters) + * @param myClcm ClcmPtr object node. + */ + void node(std::string sname, ClcmPtr &myClcm); + + /** Return the file object node with a given name. If the node is empty or if the argument type + * is wrong, an exception is thrown. The lifo stack is not modified + * @param sname node name (limited to 12 characters) + * @param node operating system (OS) name (limited to 72 characters) associated to the file object + * node to pop from the lifo stack. + * @param stype type of LCM object or file. This variable is selected by <tt>pop</tt> among the + * following values: + * <ul><dl> + * <dt> <tt>"BINARY"</tt> <dd> binary sequential file + * <dt> <tt>"ASCII"</tt> <dd> ACSII sequential file + * <dt> <tt>"DA"</tt> <dd> binary direct-access file (with 128-word records)</ul> + */ + void node(std::string sname, std::string node, std::string stype); + + /** Return the OSname of the node associated with a given name. The lifo stack is not modified + * @param sname node name (limited to 12 characters) + * @return OSName of the file + */ + std::string OSName(std::string sname); + + /** Return the OSname of the node at a given position. The lifo stack is not modified + * @param ipos node position in lifo stack + * @return OSName of the file + */ + std::string OSName(int_32 ipos); + + /** Return the name of the node at a given position. The lifo stack is not modified + * @param ipos node position in lifo stack + * @return name of the node + */ + std::string Name(int_32 ipos); + + /** Return the type of the node associated with a given name. The lifo stack is not modified + * @param sname node name (limited to 12 characters) + * @return node type (3= LCM object; 4= XSM file; 5= seq binary; 6= seq ascii; 7= DA binary; + 11= integer value; 12= real value; 13= character std::string; 14= double precision value; + 15= logical value). A negative value indicates an empty node. + */ + int_32 typeNode(std::string sname); + + /** Return the type of the node at a given position. The lifo stack is not modified + * @param ipos node position in lifo stack + * @return node type (3= LCM object; 4= XSM file; 5= seq binary; 6= seq ascii; 7= DA binary; + 11= integer value; 12= real value; 13= character std::string; 14= double precision value; + 15= logical value). A negative value indicates an empty node. + */ + int_32 typeNode(int_32 ipos); + + /** Return the access of the node associated with a given name. The lifo stack is not modified + * @param sname node name (limited to 12 characters) + * @return node access (0= creation; 1:modification; 2=read-only). + */ + int_32 accessNode(std::string sname); + + /** Return the access of the node at a given position. The lifo stack is not modified + * @param ipos node position in lifo stack + * @return node access (0= creation; 1:modification; 2=read-only). + */ + int_32 accessNode(int_32 ipos); + + /** Push a new integer on top of the Lifo stack + * @param sname node name (limited to 12 characters) + * @param myInteger integer value to push into the lifo stack + */ + void push(std::string sname, const int_32 myInteger); + + /** Push a new real on top of the Lifo stack + * @param sname node name (limited to 12 characters) + * @param myFloat real value to push into the lifo stack + */ + void push(std::string sname, const float myFloat); + + /** Push a new node object on top of the Lifo stack + * @param sname node name (limited to 12 characters) + * @param myString string object to push into the lifo stack. + */ + void push(std::string sname, const std::string myString); + + /** Push a new double precision value on top of the Lifo stack + * @param sname node name (limited to 12 characters) + * @param myDouble double precision value to push into the lifo stack + */ + void push(std::string sname, const double_64 myDouble); + + /** Push a new boolean value on top of the Lifo stack + * @param sname node name (limited to 12 characters) + * @param myBool boolean value to push into the lifo stack + */ + void push(std::string sname, const bool myBool); + + /** Push a new ClcmPtr node object on top of the Lifo stack + * @param sname node name (limited to 12 characters) + * @param myClcm ClcmPtr LCM/XSM object to push into the lifo stack. + * result + */ + void push(std::string sname, const ClcmPtr myClcm); + + /** Push a new node object with a type on top of the Lifo stack + * @param sname node name (limited to 12 characters) + * @param myFile file object to push into the lifo stack. + * @param stype type of LCM object or file. This variable is chosen among + * the following values: + * <ul><dl> + * <dt> <tt>"BINARY"</tt> <dd> binary sequential file + * <dt> <tt>"ASCII"</tt> <dd> ACSII sequential file + * <dt> <tt>"DA"</tt> <dd> binary direct-access file (with 128-word records) + */ + void push(std::string sname, std::string myFile, std::string stype); + + /** Push a new node object with a type and an <tt>"OSname"</tt> on top of the Lifo stack + * @param sname node name (limited to 12 characters) + * @param myFile file object to push into the lifo stack. + * @param stype type of LCM object or file. This variable is chosen among + * the following values: + * <ul><dl> + * <dt> <tt>"BINARY"</tt> <dd> binary sequential file + * <dt> <tt>"ASCII"</tt> <dd> ACSII sequential file + * <dt> <tt>"DA"</tt> <dd> binary direct-access file (with 128-word records)</ul> + * @param OSname operating system (OS) name associated to the file (limited to 72 characters). + */ + void push(std::string sname, std::string myFile, std::string stype, + std::string OSname); + + /** Push an empty node on top of the Lifo stack + * @param sname node name (limited to 12 characters) + * @param nodeType node type (='I': integer value; 'F': real value; 'D': double precision value; + * 'B': boolean value;'S': character string value; ='LCM': memory-resident LCM object; ='XSM': XSM file; + * ='BINARY': binary file; ='ASCII': ascii file; ='DA': direct-access file (with 128-word records)) + */ + void pushEmpty(std::string sname, std::string nodeType); + + /** Push an empty node on top of the Lifo stack + * @param sname node name (limited to 12 characters) + * @param nodeType node type (='XSM': XSM file; ='BINARY': binary file; ='ASCII': ascii file; + * ='DA': direct-access file (with 128-word records)) + * @param OSname operating system (OS) name associated to the file (limited to 72 characters). + */ + void pushEmpty(std::string sname, std::string nodeType, std::string OSname); + + /** Gives the number of nodes in the lifo stack + * @return number of nodes in lifo stack + */ + int_32 getMax(); + + /** Print_32 the table-of-content of a lifo stack + */ + void lib(); + + /** Extract the lifo structure. + * @return ANSI C pointer of the embedded lifo structure. + */ + lifo *extract(); + +private: + std::vector<ClcmPtr> *global_list; // container for the global references + lifo *addr; // address of the Lifo object +}; // class Lifo + +} // namespace ganlib +#endif diff --git a/Skin++/src/LifoException.cxx b/Skin++/src/LifoException.cxx new file mode 100755 index 0000000..ba8c1ad --- /dev/null +++ b/Skin++/src/LifoException.cxx @@ -0,0 +1,22 @@ + +/*****************************************/ +/* EXCEPTION CLASS FOR Lifo */ +/* AUTHOR: A. HEBERT ; 2012/10/07 */ +/*****************************************/ + +/* +Copyright (C) 2012 Ecole Polytechnique de Montreal + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. +*/ + +#include "LifoException.hxx" +using namespace std; +using namespace ganlib; + +ganlib::LifoException::LifoException(const string& msg) : runtime_error(msg) { + cout << "A LifoException was thrown with message: " << msg << endl; +} diff --git a/Skin++/src/LifoException.hxx b/Skin++/src/LifoException.hxx new file mode 100755 index 0000000..79b348a --- /dev/null +++ b/Skin++/src/LifoException.hxx @@ -0,0 +1,22 @@ +/** + * Exception class for Lifo stack uses in C++ + * <P> + * + * @author Alain Hebert, Ecole Polytechnique de Montreal (2012) + */ +#ifndef LifoException_HXX +#define LifoException_HXX + +#include <string> +#include <iostream> +#include <stdexcept> + +namespace ganlib { + +class LifoException : public std::runtime_error { +public: + LifoException(const std::string& msg = ""); +}; // class LifoException */ + +} // namespace ganlib +#endif diff --git a/Skin++/src/Makefile b/Skin++/src/Makefile new file mode 100755 index 0000000..fe13dae --- /dev/null +++ b/Skin++/src/Makefile @@ -0,0 +1,182 @@ +#--------------------------------------------------------------------------- +# +# Makefile for building the Skin++ library and load module +# Author : A. Hebert (2018-5-10) +# +#--------------------------------------------------------------------------- +# +ARCH = $(shell uname -m) +ifneq (,$(filter $(ARCH),aarch64 arm64)) + nbit = +else + ifneq (,$(filter $(ARCH),i386 i686)) + nbit = -m32 + else + nbit = -m64 + endif +endif + +DIRNAME = $(shell uname -sm | sed 's/[ ]/_/') +OS = $(shell uname -s | cut -d"_" -f1) +opt = -O -g +ifeq ($(openmp),1) + COMP = -fopenmp + FOMP = -fopenmp -D_OPENMP +else + COMP = + FOMP = +endif + +ifeq ($(intel),1) + fcompiler = ifort + ccompiler = icpc +else + ifeq ($(nvidia),1) + fcompiler = nvfortran + ccompiler = nvc++ + else + ifeq ($(llvm),1) + fcompiler = flang-new + ccompiler = clang++ + else + fcompiler = gfortran + ccompiler = gcc + endif + endif +endif + +clib = -lstdc++ +ifeq ($(OS),Darwin) + C = $(ccompiler) -std=c++17 + F90 = $(fcompiler) + FLAGS = -DLinux -DUnix + CFLAGS = -Wall $(nbit) -fPIC + LFLAGS = $(nbit) + clib = -lc++ +else +ifeq ($(OS),Linux) + ifeq ($(nvidia),1) + C = $(ccompiler) -std=c++14 + else + C = $(ccompiler) -std=c++17 + endif + F90 = $(fcompiler) + FLAGS = -DLinux -DUnix + CFLAGS = -Wall $(nbit) -fPIC + LFLAGS = $(nbit) +else +ifeq ($(OS),CYGWIN) + C = g++ -std=c++17 + F90 = $(fcompiler) + FLAGS = -DLinux -DUnix + CFLAGS = -Wall $(nbit) -fPIC + LFLAGS = $(nbit) +else +ifeq ($(OS),SunOS) + MAKE = gmake + F90 = f90 + C = cc + FLAGS = -DSunOS -DUnix + CFLAGS = $(nbit) + LFLAGS = $(nbit) +else +ifeq ($(OS),AIX) + opt = -O4 + MAKE = gmake + DIRNAME = AIX + F90 = xlf90 + C = xlc + FLAGS = -DAIX -DUnix + CFLAGS = -qstrict + LFLAGS = -qstrict -bmaxdata:0x80000000 -qipa +else + $(error $(OS) is not a valid OS) +endif +endif +endif +endif +endif +INCLUDE = -I../../Ganlib/src/ + +ifeq ($(intel),1) + FFLAGS = -fPIC + FFLAG77 = -fPIC + lib = ../lib/$(DIRNAME)_intel + bin = ../bin/$(DIRNAME)_intel + libUtl = ../../Utilib/lib/$(DIRNAME)_intel + libGan = ../../Ganlib/lib/$(DIRNAME)_intel + libTri = ../../Trivac/lib/$(DIRNAME)_intel + libDra = ../../Dragon/lib/$(DIRNAME)_intel + libDon = ../../Donjon/lib/$(DIRNAME)_intel +else + ifeq ($(nvidia),1) + lib = ../lib/$(DIRNAME)_nvidia + bin = ../bin/$(DIRNAME)_nvidia + libUtl = ../../Utilib/lib/$(DIRNAME)_nvidia + libGan = ../../Ganlib/lib/$(DIRNAME)_nvidia + libTri = ../../Trivac/lib/$(DIRNAME)_nvidia + libDra = ../../Dragon/lib/$(DIRNAME)_nvidia + libDon = ../../Donjon/lib/$(DIRNAME)_nvidia + else + ifeq ($(llvm),1) + lib = ../lib/$(DIRNAME)_llvm + bin = ../bin/$(DIRNAME)_llvm + libUtl = ../../Utilib/lib/$(DIRNAME)_llvm + libGan = ../../Ganlib/lib/$(DIRNAME)_llvm + libTri = ../../Trivac/lib/$(DIRNAME)_llvm + libDra = ../../Dragon/lib/$(DIRNAME)_llvm + libDon = ../../Donjon/lib/$(DIRNAME)_llvm + LFLAGS += -lclang_rt.osx + else + lib = ../lib/$(DIRNAME) + bin = ../bin/$(DIRNAME) + libUtl = ../../Utilib/lib/$(DIRNAME) + libGan = ../../Ganlib/lib/$(DIRNAME) + libTri = ../../Trivac/lib/$(DIRNAME) + libDra = ../../Dragon/lib/$(DIRNAME) + libDon = ../../Donjon/lib/$(DIRNAME) + endif + endif +endif + +ifeq ($(hdf5),1) + CFLAGS += -DHDF5_LIB -I${HDF5_INC} + LFLAGS += -L${HDF5_API} -lhdf5 +endif + +SRCC = $(shell ls *.cxx) +OBJC = $(SRCC:.cxx=.o) +all : sub-make Skin++ +ifeq ($(openmp),1) + @echo 'Skin++: openmp is defined' +endif +ifeq ($(intel),1) + @echo 'Skin++: intel is defined' +endif +ifeq ($(nvidia),1) + @echo 'Skin++: nvidia is defined' +endif +ifeq ($(llvm),1) + @echo 'Skin++: llvm is defined' +endif +ifeq ($(hdf5),1) + @echo 'Skin++: hdf5 is defined' +endif +sub-make: + $(MAKE) openmp=$(openmp) intel=$(intel) nvidia=$(nvidia) llvm=$(llvm) hdf5=$(hdf5) -C ../../Donjon/src +%.o : %.cxx + $(C) $(CFLAGS) $(FLAGS) $(opt) $(COMP) $(INCLUDE) -c $< -o $@ +$(lib)/: + mkdir -p $(lib)/ +libSkin++.a: $(OBJC) $(lib)/ + ar r $@ $(OBJC) + cp $@ $(lib)/$@ +$(bin)/: + mkdir -p $(bin)/ +Skin++: libSkin++.a Skin++.o $(bin)/ sub-make + $(F90) $(opt) $(FOMP) Skin++.o $(lib)/libSkin++.a $(libDon)/libDonjon.a $(libDra)/libDragon.a $(libTri)/libTrivac.a \ + $(libDra)/libDragon.a $(libUtl)/libUtilib.a $(libGan)/libGanlib.a $(clib) $(LFLAGS) -o Skin++ + cp $@ $(bin)/$@ +clean: + $(MAKE) -C ../../Donjon/src clean + /bin/rm -f *.o *.a sub-make Skin++ diff --git a/Skin++/src/Skin++.cxx b/Skin++/src/Skin++.cxx new file mode 100755 index 0000000..150e6d5 --- /dev/null +++ b/Skin++/src/Skin++.cxx @@ -0,0 +1,80 @@ +#include "Cle2000.hxx" +using namespace std; using namespace ganlib; + +int main(int argc, char **argv) { + // construct the lifo stack + LifoPtr ipLifo = LifoPtr(new Lifo()); + ipLifo->push("input_val",5); + ipLifo->pushEmpty("output_val","I"); + + // call the procedure with in-out CLE-2000 variables + Cle2000Ptr ipCle2000 = Cle2000Ptr(new Cle2000("fact", 0, ipLifo)); + ipCle2000->exec(); + + // recover and erase the lifo stack + int_32 output_val; ipLifo->pop(output_val); + cout << endl << "factorial(5)=" << output_val << endl << endl; + if (output_val != 120) throw Cle2000Exception("Test failure 1"); + + // empty the lifo stack + while (ipLifo->getMax() > 0) ipLifo->pop(); + + // end of case ----------------------------------------------------------- + + // construct a new lcm object + ClcmPtr iplistgen = ClcmPtr(new Clcm("LCM_IMP_ASCII", "Geo3D.txt", "./")); + iplistgen->lib(); + StringPtrConst myString = iplistgen->getString("SIGNATURE"); + cout << "signature=" << *myString << "<---" << endl; + iplistgen->close("KEEP"); + + // construct a new lifo stack + LifoPtr ipLifo2 = LifoPtr(new Lifo()); + ipLifo2->push("Geo3D",iplistgen); + ipLifo2->pushEmpty("nb_mix","I"); + ipLifo2->lib(); + + // call the procedure with in-out CLE-2000 variables + Cle2000Ptr ipCle2000_bis = Cle2000Ptr(new Cle2000("grep", 0, ipLifo2)); + ipCle2000_bis->exec(); + + // recover and erase the lifo stack + int_32 nb_mix; ipLifo2->pop(nb_mix); + cout << endl << "number of mixtures = " << nb_mix << endl << endl; + if (nb_mix != 17) throw Cle2000Exception("Test failure 2"); + + // empty the lifo stack + while (ipLifo2->getMax() > 0) ipLifo2->pop(); + + // end of case ----------------------------------------------------------- + + // construct the lifo stack + LifoPtr ipLifo3 = LifoPtr(new Lifo()); + ipLifo3->pushEmpty("saphyb", "XSM", "./saphyb_UOX_AICN"); + ipLifo3->push("draglib", string("draglibendfb7r1SHEM295")); + ipLifo3->push("type", string("FRA")); + ipLifo3->push("combustible", string("UOX")); + ipLifo3->push("barres", string("AICN")); + ipLifo3->push("homoge", string("HOMOGENE")); + ipLifo3->push("u235", float_32(3.7)); + ipLifo3->push("burnup", float_32(85000.)); + ipLifo3->push("nrgoup", int_32(2)); + ipLifo3->lib(); + + // call the procedure with in-out CLE-2000 variables + Cle2000Ptr ipCle2000_ter = Cle2000Ptr(new Cle2000("pwr2010", 0, ipLifo3)); + ipCle2000_ter->exec(); + + // recover the saphyb + ClcmPtr xsm_object; ipLifo3->node("saphyb", xsm_object); + xsm_object->open("READ-ONLY"); + xsm_object->lib(); + xsm_object->close("KEEP"); + + // empty the lifo stack + while (ipLifo3->getMax() > 0) ipLifo3->pop(); + + // end of case ----------------------------------------------------------- + cout << "Skin++: normal end of execution" << endl; + return 0; +} |
