void XMLReader::elementEnd(const char* elementName) { if (ignore_) { ignore_ -= 1; return; } assert(!stack_.empty()); // parse character data auto& current = stack_.back(); if (!current.characterData.empty()) { if (!current.value.value<Collection*>()) { FixedMemoryStream dataStream(current.characterData.c_str(), current.characterData.size()); TextStream stream(dataStream); stream >> current.value; stream.skipWhiteSpace(); if (stream.fail() || !stream.eof()) { // failed to deserialize primitive value abortParsing(); return; } } }
ConfigFileParser::ConfigFileParser(const std::string filename) : FILENAME(filename), PARSERS(fillParsers()) { foundCutter = foundStock = foundPoints = false; std::ifstream ifs; FileUtils::openFile(filename, ifs); while(ifs.good() && !foundAll()) { std::string str = FileUtils::readNextValidLine(ifs).validLine; // checks if given line is a section string of type: [SMTHNG] boost::smatch matcher; boost::regex expression("\\[(\\w+)\\]"); if (!boost::regex_match(str, matcher, expression)) { abortParsing("'" + str + "' is not a valid section"); } std::string section(matcher[1]); ParsersMap::const_iterator it; it = PARSERS.find(section); if (it == PARSERS.end()) { // no parsers registered to dissect given section abortParsing("unknown section '" + section + "'"); } // invoke parser in order to dissect section (this->*(it->second))(ifs); // then continue to the next section } if (!foundAll()) { std::string errorStr("missing section[s]: "); if (!foundCutter) errorStr += "tool "; if (!foundPoints) errorStr += "point "; if (!foundStock) errorStr += "product "; abortParsing(errorStr); } }
void ConfigFileParser::sectionParser_points(std::ifstream& ifs) { if (foundPoints) abortParsing("Repeated POINTS section"); this->firstPointPos = ifs.tellg(); this->foundPoints = true; if (!foundAll()) { /* this means that points are not placed at the end of the file so * i would have to scan all points until the end of the file to check * if there are some other sections there....... */ throw std::runtime_error("missing sections or POINTS is not last section"); } }
void ConfigFileParser::sectionParser_product(std::ifstream& ifs) { if(foundStock) abortParsing("Repeated PRODUCT section"); // 1- X=NN std::string line = FileUtils::readNextValidLine(ifs).validLine; std::string XStr = StringUtils::extractProperty(line, "X", "[\\d\\.]+", true); double X = boost::lexical_cast<double>(XStr); // 2- Y=NN line = FileUtils::readNextValidLine(ifs).validLine; std::string YStr = StringUtils::extractProperty(line, "Y", "[\\d\\.]+", true); double Y = boost::lexical_cast<double>(YStr); // 3- Z=NN line = FileUtils::readNextValidLine(ifs).validLine; std::string ZStr = StringUtils::extractProperty(line, "Z", "[\\d\\.]+", true); double Z = boost::lexical_cast<double>(ZStr); RectCuboidPtr geom = boost::make_shared<RectCuboid>(RectCuboid(X, Y, Z)); this->stock = boost::make_shared<StockDescription>(StockDescription(geom)); this->foundStock = true; }
void XMLReader::elementStart(const char* elementName, const char* const* attributes) { if (ignore_) { ignore_ += 1; return; } // parse attributes const char* type = nullptr; const char* objectId = nullptr; const char* objectReference = nullptr; const char* propertyName = nullptr; const char* keyType = nullptr; const char* key = nullptr; for (auto attribute = attributes; *attribute; attribute += 2) { const char* attributeName = attribute[0]; const char* attributeValue = attribute[1]; if (attributeName == format_.typeAttribute) { type = attributeValue; } else if (attributeName == format_.objectIdAttribute) { objectId = attributeValue; } else if (attributeName == format_.objectReferenceAttribute) { objectReference = attributeValue; } else if (attributeName == format_.propertyNameAttribute) { propertyName = attributeValue; } else if (attributeName == format_.keyTypeAttribute) { keyType = attributeValue; } else if (attributeName == format_.keyAttribute) { key = attributeValue; } else { // ignore unknown attributes } } // prepare stack top item assert(!stack_.empty()); if (pushed_) { // asusme that value for the current element is already on the stack pushed_ = false; } else { auto& current = stack_.back(); current.hasChildren = true; current.characterData.clear(); if (current.object.storage()) { // find and push property const IClassDefinition* classDefinition = current.object.getDefinition(definitionManager_); if (!classDefinition) { // type is not reflected abortParsing(); return; } assert(propertyName != nullptr); IBasePropertyPtr property = classDefinition->findProperty(propertyName); if (!property) { // ignore unknown properties ignore_ = 1; return; } if (property->isMethod()) { // ignore method properties ignore_ = 1; return; } stack_.emplace_back(property->get(current.object, definitionManager_)); stack_.back().property = property; } else if (current.collection && current.collection->isValid()) { if (elementName != format_.collectionItemElement) { // ignore non-item properties ignore_ = 1; return; } Variant k; if (key) { k = key; if (keyType) { const MetaType* keyMetaType = MetaType::find(keyType); if (!keyMetaType) { // key type not found abortParsing(); return; } if (!k.setType(keyMetaType)) { // key type conversion failed abortParsing(); return; } } intmax_t keyIndex = 0; if (k.tryCast(keyIndex)) { current.assumedKey = keyIndex; } } else { k = current.assumedKey; } current.assumedKey += 1; auto findIt = current.collection->find(k); if (findIt == current.collection->end()) { findIt = current.collection->insert(k); } stack_.emplace_back(findIt.value()); stack_.back().pos = findIt; } else { // This may occur if we didn't find ClassDefinition for parent // element and assumed parent to be primitive value. So consider // this situation as an error. abortParsing(); return; } } auto& current = stack_.back(); if (objectId != nullptr) { current.objectId = objectId; } if (objectReference != nullptr) { current.needResolve = true; } // check type if (type) { bool isEmpty = current.value.isVoid(); if (!isEmpty) { if (auto object = current.value.value<ObjectHandle*>()) { if (!object->isValid()) { isEmpty = true; } } } if (isEmpty) { // set type if (IClassDefinition* classDefinition = definitionManager_.getDefinition(type)) { if (objectId == nullptr) { current.value = classDefinition->create(); } else { auto objectManager = definitionManager_.getObjectManager(); current.value = objectManager->createObject(RefObjectId(objectId), type); } } else if (const MetaType* metaType = MetaType::find(type)) { current.value = Variant(metaType); } else { // type not found abortParsing(); return; } current.cast(definitionManager_); } else { // deduce actual underlying type current.cast(definitionManager_); const char* actualType = current.value.type()->name(); if (current.object.storage()) { if (const IClassDefinition* definition = current.object.getDefinition(definitionManager_)) { actualType = definition->getName(); } } if (strcmp(actualType, type) != 0) { // types do not match abortParsing(); return; } } } else { current.cast(definitionManager_); } }
void ConfigFileParser::sectionParser_tool(std::ifstream& ifs) { if (foundCutter) abortParsing("Repeated TOOL section"); std::string line = FileUtils::readNextValidLine(ifs).validLine; // 1- discover type boost::smatch match; boost::regex exp("type\\s*=\\s*(.+)", boost::regex::icase); if(!boost::regex_match(line, match, exp)) { abortParsing("first line in tool definition should be 'Type=tool_type'"); } std::string type(match[1]); boost::algorithm::to_lower(type); // 2- extract correct informations based on type GeometryPtr geometry; if (type == "cylinder") { // next line should be 'Height=NN': line = FileUtils::readNextValidLine(ifs).validLine; std::string heightStr = StringUtils::extractProperty(line, "Height", "[\\d\\.]+", true); // next line should be 'Diameter=NN': line = FileUtils::readNextValidLine(ifs).validLine; std::string diameterStr = StringUtils::extractProperty(line, "Diameter", "[\\d\\.]+", true); float height = boost::lexical_cast<float>(heightStr); float diameter = boost::lexical_cast<float>(diameterStr); geometry = boost::make_shared<Cylinder>(Cylinder(diameter * 0.5, height)); } else if (type == "sphere") { // next line should be 'Diameter=NN': line = FileUtils::readNextValidLine(ifs).validLine; std::string diameterStr = StringUtils::extractProperty(line, "Diameter", "[\\d\\.]+", true); float diameter = boost::lexical_cast<float>(diameterStr); geometry = boost::make_shared<Sphere>(Sphere(diameter * 0.5)); } else if (type == "mesh") { // TODO need to be implemented throw std::runtime_error("Not implemented yet"); } // 3- find an _optional_ color specification Color color; FileUtils::ReadData data = FileUtils::readNextValidLine(ifs); try { std::string colorStr = StringUtils::extractProperty(data.validLine, "color", "0x[\\da-f]{6}", true); color = Color(colorStr); } catch (const std::exception &e) { // means no color is present => revert ifs back to the previous line ifs.seekg(data.lastReadPos, std::ios_base::beg); } this->cutter = boost::make_shared<CutterDescription>(CutterDescription(geometry, color)); this->foundCutter = true; }