Ejemplo n.º 1
0
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;
}
Ejemplo n.º 5
0
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;
}