ERRCODE Config::load( string filename ) { string tmp; char *line = NULL; FILE *fp = NULL; size_t len = 0, linenum = 0; ssize_t read; vector<string> tokens; C_NODE node; nodes.clear(); enforce(( fp = fopen( filename.c_str(), "r" )) != NULL, "Failed to read from file " << filename << ": " << strerror( errno )); // replace with fgets while(( read = readline( &line, &len, fp )) != -1 ) { linenum++; tmp = line; trim( tmp ); if( tmp.empty() || tmp[0] == '#' ) continue; node.type = NONE; node.list.clear(); node.length = false; tokens.clear(); stringTok( tmp, tokens ); // test min number of tokens enforce( tokens.size() >= 4, "Failed to parse " << filename << " ( " << tokens.size() << " < 4 )\n" << linenum << ": " << line ); // test for type if( tokens[0][0] == '$' ) { node.length = true; tokens[0] = tokens[0].substr( 1 ); } for( size_t j = 0; j < VTYPEL; ++j ) { if( iequals( tokens[0], VTYPES[j] )) { node.type = (VTYPE)j; break; } } enforce( node.type != NONE, "Failed to parse " << filename << " ( \"" << tokens[0] << "\" != TYPE )\n" << linenum << ": " << line ); // test for open bracket enforce( iequals( tokens[1], "{" ), "Failed to parse " << filename << " ( \"" << tokens[1] << "\" != \"{\" )\n" << linenum << ": " << line ); for( size_t j = 2; j < tokens.size(); j++ ) { enforce( tokens[j][0] != '#', "Failed to parse " << filename << " ( \'" << tokens[j][0] << "\' == \'#\' )\n" << linenum << ": " << line ); if( iequals( tokens[j], "}" )) { if( j + 1 < tokens.size()) { enforce( tokens[j+1][0] == '#', "Failed to parse " << filename << " ( \'" << tokens[j][0] << "\' != \'#\' )\n" << linenum << ": " << line ); } break; } node.list.push_back( tokens[j] ); } nodes.push_back(node); } fclose( fp ); free( line ); return PK_OK; }
int Unit::set(const std::string &value) { this->clear(); std::string unitString = value; stringTrim(unitString); if(unitString.empty()) return 0; stringReplace(unitString, "**", ""); // remove exponentiation symbols stringReplace(unitString, "^", ""); stringReplace(unitString, "*", " "); // replace multiplication symbols with space for tokenising stringReplace(unitString, "/", " /"); // pad division symbols with space for tokenising while(stringReplace(unitString, "/ ", "/") == 0); // remove all spaces after division symbols std::vector<std::string> tokens; // Tokenise string using spaces: if(stringTok(unitString, tokens, " ") != 0) { std::cerr << "Error (Unit): Failed to tokenise unit string." << std::endl; this->clear(); return 1; } if(tokens.size() < 1) { std::cerr << "Error (Unit): Failed to tokenise unit string." << std::endl; this->clear(); return 1; } // Loop through all tokens: for(size_t i = 0; i < tokens.size(); i++) { int factorDiv = 1; // Will become -1 if division sign '/' found. int exponent = 1; // Exponent of the unit; defaults to 1 if unspecified. // Check for division symbol: if(tokens[i].substr(0, 1) == "/") { tokens[i] = tokens[i].substr(1, tokens[i].size() - 1); factorDiv = -1; } // Extract exponent: size_t posExp = tokens[i].find_first_of("+-0123456789"); if(posExp != std::string::npos) { exponent = stringToNumber<int>(tokens[i].substr(posExp)); } exponent *= factorDiv; // Only proceed if unit is not unity: if(exponent != 0 and tokens[i] != "1") { // Extract base unit and prefix: bool success = false; std::map<std::string, std::vector<int> >::const_iterator iterUnit = unitMap.begin(); do { std::map<std::string, int>::const_iterator iterPrefix = prefixMap.begin(); do { std::string searchKey = iterPrefix->first + iterUnit->first; if(searchKey == tokens[i].substr(0, posExp)) { success = true; int prefix = iterPrefix->second; std::vector<int> unit(iterUnit->second); // Take care of special case 'kg': if(iterUnit->first == "g") prefix -= 3; for(size_t ii = 0; ii < UNIT_NUMBER_BASE_UNITS; ii++) { units[ii] += unit[ii] * exponent; } prefixes += prefix * exponent; } iterPrefix++; } while(success == false and iterPrefix != prefixMap.end()); iterUnit++; } while(success == false and iterUnit != unitMap.end()); if(success == false) { std::cerr << "Error (Unit): Unknown unit: \'" << value << "\'." << std::endl; std::cerr << " Creating dimensionless unit instead." << std::endl; clear(); return 1; } } } return 0; }