void RequestParser::parseHeaders(const Item& aItem, Headers& aHeaders)
{
  Item lKey;
  String lName;
  String lValue;

  zorba::Iterator_t lIterator = aItem.getObjectKeys();
  lIterator->open();

  while (lIterator->next(lKey))
  {
    lName = lKey.getStringValue();
    getString(aItem, lName, true, lValue);
    aHeaders.push_back(std::pair<String, String>(lName, lValue));
  }
  lIterator->close();
}
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
size_t ChValidation::ReadDataFile(const std::string& filename,
                                  char               delim,
                                  Headers&           headers,
                                  Data&              data)
{
  std::ifstream ifile(filename.c_str());
  std::string   line;

  // Count the number of lines in the file then rewind the input file stream.
  size_t num_lines = std::count(std::istreambuf_iterator<char>(ifile),
                                std::istreambuf_iterator<char>(), '\n');
  ifile.seekg(0, ifile.beg);

  size_t num_data_points = num_lines - 3;

  // Skip the first two lines.
  std::getline(ifile, line);
  std::getline(ifile, line);

  // Read the line with column headers.
  std::getline(ifile, line);
  std::stringstream iss1(line);
  std::string col_header = "";

  while (std::getline(iss1, col_header, delim))
    headers.push_back(col_header);

  size_t num_cols = headers.size();

  // Resize data
  data.resize(num_cols);
  for (size_t col = 0; col < num_cols; col++)
    data[col].resize(num_data_points);

  // Read the actual data, one line at a time.
  size_t row = 0;
  while (std::getline(ifile, line)) {
    std::stringstream iss(line);
    for (size_t col = 0; col < num_cols; col++)
      iss >> data[col][row];
    row++;
  }

  return row;
}
Exemple #3
0
int main(int argc, char *argv[])
{
	// Parse command line arguments.
	boost::filesystem::path output(".");
	if (argc >= 2) output = argv[1];

	// Create the output directory if required.
	if (!boost::filesystem::exists(output)) {
		cout << "Creating output directory " << output << '\n';
		boost::filesystem::create_directories(output);
	}

	// Build the AST.
	Builder builder;
	buildAST(builder);

	// Determine implemented interfaces and child nodes.
	determineImplementedInterfaces(builder);
	determineChildNodes(builder);

	// Generate the code for the nodes.
	Headers headerFileNames;
	Headers sourceFileNames;
	for (Builder::Nodes::iterator it = builder.nodes.begin(); it != builder.nodes.end(); it++) {
		const std::string &name = it->first;
		Node &node = it->second;
		//cout << "- Generating \033[36;1m" << name << "\033[0m" << '\n';
		std::string headerName = name + ".hpp";
		std::string sourceName = name + ".cpp";

		// Generate the header and source file.
		boost::filesystem::path hpath = output, spath = output;
		hpath /= headerName;
		spath /= sourceName;
		std::ofstream h(hpath.c_str());
		std::ofstream s(spath.c_str());

		h << "/* Automatically generated by ast-gen. DO NOT MODIFY. */\n";
		h << "#pragma once\n";
		h << "#include \"maxwell/ast/Node.hpp\"\n";
		h << "#include \"maxwell/ast/nodes/interfaces.hpp\"\n";
		h << "#include \"maxwell/ast/nodes/types.hpp\"\n";
		if (node.parent != "Node") h << "#include \"maxwell/ast/nodes/" << node.parent << ".hpp\"\n";
		h << '\n';

		s << "/* Automatically generated by ast-gen. DO NOT MODIFY. */\n";
		s << "#include \"maxwell/ast/nodes/" << headerName << "\"\n";
		s << "#include \"maxwell/ast/Coder.hpp\"\n";
		s << "#include <cstdio>\n";
		s << "#include <sstream>\n";
		s << "#include <stdexcept>\n";
		s << "using ast::" << name << ";\n";
		s << "using ast::NodePtr;\n";
		s << "using ast::NodeVector;\n\n";

		h << "namespace ast {\n\n";
		h << "class Encoder;\n";
		h << "class Decoder;\n\n";
		h << "class " << name << " : public Node\n{\npublic:\n";

		// Generate the constructor.
		h << "\t// constructor\n";
		h << "\t" << name << "();\n\n";
		s << name << "::" << name << "() : Node()";
		for (Node::Interfaces::iterator it = node.interfaces.begin(); it != node.interfaces.end(); it++) {
			const Node& intf = **it;
			s << ",\n\tinterface" << intf.name << "(this)";
		}
		s << " {}\n\n";

		// Generate auxiliary functions.
		h << "\t// auxiliary functions\n";
		h << "\tvirtual bool isKindOf(Kind k);\n";
		h << "\tvirtual bool implements(Interface i);\n";
		h << "\tvirtual std::string getClassName() const { return \"" << node.name << "\"; }\n";
		h << "\tvirtual NodePtr copy();\n";
		h << "\tvirtual bool equalTo(const NodePtr& o);\n";
		h << "\tvirtual std::string describe(int depth = -1);\n";
		h << '\n';

		// isKindOf
		s << "bool " << name << "::isKindOf(Kind k) {\n";
		s << "\tif (" << node.parent << "::isKindOf(k)) return true;\n";
		s << "\treturn k == k" << node.name << ";\n";
		s << "}\n\n";

		// implements
		s << "bool " << name << "::implements(Interface i) {\n";
		s << "\tif (" << node.parent << "::implements(i)) return true;\n";
		for (Node::Interfaces::iterator it = node.interfaces.begin(); it != node.interfaces.end(); it++) {
			const Node& intf = **it;
			s << "\tif (i == k" << intf.intfName << ") return true;\n";
		}
		s << "\treturn false;\n";
		s << "}\n\n";

		// copy
		s << "NodePtr " << name << "::copy() {\n";
		s << "\tPtr c (new " << name << ");\n";
		for (Node::Fields::iterator f = node.attributes.begin(); f != node.attributes.end(); f++) {
			s << "\tNode::copy(this->" << (*f).name << ", c->" << (*f).name << ");\n";
		}
		s << "\treturn c;\n";
		s << "}\n\n";

		// equalTo
		s << "bool " << name << "::equalTo(const NodePtr& o) {\n";
		s << "\tconst shared_ptr<" << node.name << ">& other = boost::dynamic_pointer_cast<" << node.name << ">(o);\n";
		s << "\tif (!other) return false;\n";
		for (Node::Fields::iterator fit = node.attributes.begin(); fit != node.attributes.end(); fit++) {
			Node::Field& f = *fit;
			s << "\tif (!equal(this->" << f.name << ", other->" << f.name << ")) return false;\n";
		}
		s << "\treturn true;\n";
		s << "}\n\n";

		// describe
		s << "std::string " << name << "::describe(int depth) {\n";
		s << "\tstd::stringstream str, b;\n";
		if (node.descriptionBody.empty()) {
			s << "\tif (depth == 0) return \"" << name << "{…}\";\n";
			s << "\tstr << \"" << name << "{\";\n";
			for (Node::Fields::iterator fit = node.attributes.begin(); fit != node.attributes.end(); fit++) {
				Node::Field& f = *fit;

				// Don't print empty strings and arrays.
				s << "\t";
				if (f.isString || f.isArray) s << "if (!this->" <<f.name<< ".empty()) ";
				if (f.isNode) s << "if (this->" << f.name << ") ";

				// Print the field name.
				s << "b << \"\\n  \\033[1m" << f.name << "\\033[0m = ";

				// Print the actual data.
				if (f.isString) s << "\\033[33m\\\"\" << this->" << f.name << " << \"\\\"\\033[0m\";";
				if (f.isBool) s << "\\033[34m\" << (this->" << f.name << " ? \"true\" : \"false\") << \"\\033[0m\";";
				if (f.isInt) s << "\\033[35m\" << this->" << f.name << " << \"\\033[0m\";";
				if (f.isNode) {
					if (f.ref) {
						s << "\\033[36m\" << this->" << f.name << ".id << \"\\033[0m\";";
					} else {
						s << "\" << indent(this->" << f.name << "->describe(depth-1));";
					}
				}
				if (f.isArray) s << "\" << indent(describeVector(this->" << f.name << ", depth-1));";
				s << "\n";
			}
			s << "\tstring bs = b.str();\n";
			s << "\tif (!bs.empty()) str << bs << '\\n';\n";
			s << "\tstr << \"}\";\n";
		} else {
			string body(node.descriptionBody);
			boost::algorithm::replace_all(body, "\n", "\n\t\t");
			s << "\t" << body << "\n";
		}
		s << "\treturn str.str();\n";
		s << "}\n\n";
		s << '\n';

		// Generate the accessor functions.
		h << "\t// accessor functions\n";
		for (Node::Fields::iterator fit = node.attributes.begin(); fit != node.attributes.end(); fit++) {
			Node::Field& f = *fit;
			string ref = "const " + f.cpp_type + "&";
			string upper = f.name;
			if (!upper.empty()) upper[0] = toupper(upper[0]);
			h << "\tvoid set" << upper << "(" << ref << " v);\n";
			s << "void " << name << "::set" << upper << "(" << ref << " v) {\n";

			vector<string> ifcomponents;
			string allowedNodes;
			string allowedInterfaces;
			for (unsigned i = 0; i < f.allowedNodes.size(); i++) {
				ifcomponents.push_back("!v->isKindOf(k" + f.allowedNodes[i] + ")");
				if (!allowedNodes.empty()) allowedNodes += ", ";
				allowedNodes += f.allowedNodes[i];
			}
			for (unsigned i = 0; i < f.allowedInterfaces.size(); i++) {
				ifcomponents.push_back("!v->implements(k" + builder.interfaces[f.allowedInterfaces[i]].intfName + ")");
				if (!allowedInterfaces.empty()) allowedInterfaces += ", ";
				allowedInterfaces += f.allowedInterfaces[i];
			}
			if (!ifcomponents.empty()) {
				s << "\tif (v";
				for (unsigned i = 0; i < ifcomponents.size(); i++) {
					s << " && " << ifcomponents[i];
				}
				s << ") {\n";
				s << "\t\tthrow std::runtime_error(\"'" << f.name << "' of \" + id.str() + \" needs to be of kind {" << allowedNodes << "} or implement interface {" << allowedInterfaces << "}, got \" + v->getClassName() + \" (\" + v->getId().str() + \") instead.\");\n";
				s << "\t}\n";
			}

			if (f.ref) {
				s << "\tif (!v && " << f.name << ") {\n";
				s << "\t\tmodify(\"" << f.name << "\");\n";
				s << "\t\t" << f.name << ".reset();\n";
				s << "\t}\n";
				s << "\tif (!" << f.name << " || v->getId() != " << f.name << ".id) {\n";
			} else {
				s << "\tif (!equal(v, " << f.name << ")) {\n";
			}
			s << "\t\tmodify(\"" << f.name << "\");\n";
			if (f.ref) {
				s << "\t\t" << f.name << ".set(v);\n";
			} else {
				s << "\t\t" << f.name << " = v;\n";
			}
			s << "\t}\n";
			s << "}\n\n";

			// special setter for references
			if (f.ref) {
				h << "\tvoid set" << upper << "(const NodeId& v);\n";
				s << "void " << name << "::set" << upper << "(const NodeId& v) {\n";
				s << "\tif (v != " << f.name << ".id) {\n";
				s << "\t\tmodify(\"" << f.name << "\");\n";
				s << "\t\t" << f.name << ".set(v);\n";
				s << "\t}\n";
				s << "}\n\n";
			}

			h << "\t" << ref << " get" << upper << "(bool required = true);\n\n";
			s << ref << " " << name << "::get" << upper << "(bool required) {\n";
			s << "\tconst " << f.cpp_type << "& v = ";
			if (f.ref) {
				s << f.name << ".get(repository);\n";
			} else {
				s << f.name << ";\n";
			}
			if (f.isNode) {
				s << "\tif (required && !v) {\n";
				s << "\t\tthrow std::runtime_error(\"Node \" + getId().str() + \" is required to have " << f.name << " set to a non-null value.\");\n";
				s << "\t}\n";
			} else if (f.isString) {
				s << "\tif (required && v.empty()) {\n";
				s << "\t\tthrow std::runtime_error(\"Node \" + getId().str() + \" is required to have a non-empty string " << f.name << " set.\");\n";
				s << "\t}\n";
			}
			s << "\treturn v;\n";
			s << "}\n\n\n";
		}

		// Generate the encode() and decode() function.
		h << "\t// encoding and decoding\n";
		h << "\tvirtual void encode(Encoder& e);\n";
		h << "\tvirtual void decode(Decoder& d);\n";
		h << '\n';

		s << "void " << name << "::encode(Encoder& e) {\n";
		s << "\te.encode(this->range);\n";
		s << "\te.encode(this->referenceRange);\n";
		for (Node::Fields::iterator f = node.attributes.begin(); f != node.attributes.end(); f++) {
			s << "\te.encode(this->" << (*f).name << ");\n";
		}
		s << "}\n\n";

		s << "void " << name << "::decode(Decoder& d) {\n";
		s << "\td.decode(this->range);\n";
		s << "\td.decode(this->referenceRange);\n";
		for (Node::Fields::iterator f = node.attributes.begin(); f != node.attributes.end(); f++) {
			s << "\td.decode(this->" << (*f).name << ");\n";
		}
		s << "}\n\n";
		s << '\n';

		// Generate the hierarchy functions.
		h << "\t// hierarchy functions\n";
		h << "\tvirtual void updateHierarchyOfChildren();\n";
		h << "\tvirtual const NodePtr& resolvePath(const std::string& path);\n";

		// updateHierarchy
		s << "void " << name << "::updateHierarchyOfChildren() {\n";
		for (Node::Fields::iterator fit = node.attributes.begin(); fit != node.attributes.end(); fit++) {
			Node::Field& f = *fit;
			if (f.isNode && !f.ref) {
				s << "\tif (this->"<<f.name<<") this->"<<f.name<<"->updateHierarchy(id + \""<<f.name<<"\", repository, this);\n";
			} else if (f.isNodeArray) {
				s << "\tfor (unsigned i = 0; i < this->"<<f.name<<".size(); i++) {\n";
				s << "\t\tchar buf[32]; snprintf(buf, 31, \"%i\", i);\n";
				s << "\t\tthis->"<<f.name<<"[i]->updateHierarchy((id + \""<<f.name<<"\") + buf, repository, this);\n";
				s << "\t}\n";
			}
		}
		s << "}\n\n";

		// resolvePath
		s << "const NodePtr& " << name << "::resolvePath(const std::string& path) {\n";
		FieldNames fields, arrayFields;
		for (Node::Fields::iterator fit = node.attributes.begin(); fit != node.attributes.end(); fit++) {
			Node::Field& f = *fit;
			if (f.isNode) {
				fields.insert(f.name);
			} else if (f.isNodeArray) {
				fields.insert(f.name);
				arrayFields.insert(f.name);
			}
		}
		if (!fields.empty()) {
			s << "\tsize_t size = path.size();\n";
			generateResolvePathBody(s, fields, arrayFields, 1);
		}
		s << "\tthrow std::runtime_error(\"Node path '\" + path + \"' does not point to a node or array of nodes.\");\n";
		s << "}\n\n";

		// getChildren
		if (!node.children.empty()) {
			h << "\tvirtual NodeVector getChildren();\n";
			s << "NodeVector " << name << "::getChildren() {\n";
			s << "\tNodeVector v;\n";
			for (Node::Children::iterator c = node.children.begin(); c != node.children.end(); c++) {
				Node::Field& f = **c;
				if (f.isNode) {
					string upper = (char)toupper(f.name[0]) + f.name.substr(1);
					s << "\tif (const NodePtr& n = this->get" << upper << "(false)) v.push_back(n);\n";
				} else if (f.isArray) {
					s << "\tv.insert(v.end(), this->" << f.name << ".begin(), this->" << f.name << ".end());\n";
				}
			}
			s << "\treturn v;\n";
			s << "}\n\n";
		}
		h << '\n';

		// Generate the interface accessors.
		if (!node.interfaces.empty()) {
			h << "\t// interfaces\n";
			for (Node::Interfaces::iterator it = node.interfaces.begin(); it != node.interfaces.end(); it++) {
				const Node& intf = **it;
				h << "\tvirtual " << intf.intfName << "* as" << intf.name << "() { return &this->interface" << intf.name << "; }\n";
			}
			h << "\n";
		}

		// Generate boost::shared_ptr convenience typedef.
		h << "\t// shared_ptr convenience\n";
		h << "\ttypedef boost::shared_ptr<" << node.name << "> Ptr;\n";
		h << "\ttemplate<typename T> static Ptr from(const T& n) { return boost::dynamic_pointer_cast<" << node.name << ">(n); }\n";
		h << "\ttemplate<typename T> static Ptr needFrom(const T& n) {\n";
		h << "\t\tPtr r = boost::dynamic_pointer_cast<" << node.name << ">(n);\n";
		h << "\t\tif (!r)\n";
		h << "\t\t\tthrow std::runtime_error(\"Node \" + n->getId().str() + \" (a \" + n->getClassName() + \") cannot be dynamically cast to " << node.name << ".\");\n";
		h << "\t\treturn r;\n";
		h << "\t}\n";
		h << '\n';

		h << "protected:\n";
		for (Node::Fields::iterator f = node.attributes.begin(); f != node.attributes.end(); f++) {
			if ((*f).ref) {
				h << "\tNodeRef " << (*f).name << ";\n";
			} else {
				h << "\t" << (*f).cpp_type << " " << (*f).name << ";\n";
			}
		}
		if (!node.interfaces.empty()) {
			h << "\n\t// interfaces\n";
			for (Node::Interfaces::iterator it = node.interfaces.begin(); it != node.interfaces.end(); it++) {
				const Node& intf = **it;
				h << "\t" << intf.intfName << "Impl<" << node.name << "> interface" << intf.name << ";\n";
			}
		}

		h << "};\n\n";
		h << "} // namespace ast\n";
		headerFileNames.push_back(headerName);
		sourceFileNames.push_back(sourceName);
	}

	// Generate the header file containing general typedefs.
	makeTypesHeader(output, builder);
	makeNodesHeader(output, builder, headerFileNames);
	makeInterfacesHeader(output, builder);

	// Generate the base header file for ast::Node which implements default interface accessors.
	makeBaseNodeHeader(output, builder);

	// Generate the header file aggregating all AST things.
	boost::filesystem::path ahpath = output;
	ahpath /= "ast.hpp";
	ofstream ah(ahpath.c_str());
	ah << "/* Automatically generated by ast-gen. DO NOT MODIFY. */\n";
	ah << "#pragma once\n\n";
	ah << "#include \"maxwell/ast/nodes/types.hpp\"\n";
	ah << "#include \"maxwell/ast/nodes/nodes.hpp\"\n";
	ah << "#include \"maxwell/ast/nodes/interfaces.hpp\"\n";

	return 0;
}