Ejemplo n.º 1
0
void preprocess_types(rapidjson::Document & d)
{
	/// pre record types
	for (auto & itr : d.GetArray()) {
		RAPIDJSON_ASSERT(itr.HasMember("category"));
		RAPIDJSON_ASSERT(itr.HasMember("name"));
		ensure_has_array_mem(itr, "attr", d);
		ensure_has_array_mem(itr, "msgid", d);
		ensure_has_object_mem(itr, "fields", d);
		ensure_has_array_mem(itr, "alias", d);
		s_type_lists[itr.FindMember("name")->value.GetString()] = &itr;
		for (auto & alias : itr.FindMember("alias")->value.GetArray()) {
			s_alias_lists[alias.GetString()] = & itr;
		}
		s_type_order.push_back(&itr);

	}

	/// messages enum
	for (auto & itr : d.GetArray()) {
		bool has_attr_msg = false;
		rapidjson::Value & attr_val = itr.FindMember("attr")->value;
		for (auto & sattr : attr_val.GetArray()) {
			RAPIDJSON_ASSERT(sattr.IsString());
			if (sattr == "msg") {
				has_attr_msg = true;
				attr_val.GetArray().Erase(&sattr);
			}
			else if (sattr == "export") {
				s_export_order.push_back(&itr);
			}
			else if (sattr == "pqxx") {
				add_pqxx(d, itr, true);
			}
		}

		rapidjson::Value & msgid_val = itr.FindMember("msgid")->value;
		if (has_attr_msg) {
			RAPIDJSON_ASSERT(itr.HasMember("name"));
			rapidjson::Value new_name(itr.FindMember("name")->value, d.GetAllocator());
			msgid_val.PushBack(new_name, d.GetAllocator());
		}

		for (const auto & smsgid : msgid_val.GetArray()) {
			RAPIDJSON_ASSERT(smsgid.IsString());
			s_msg_lists[smsgid.GetString()] = &itr;
		}

		if (msgid_val.GetArray().Size() > 0) {
			s_msg_order.push_back(&itr);
		}

		if (msgid_val.GetArray().Size() == 0) {
			itr.RemoveMember("msgid");
		}
	}

	for (auto i : s_pqxx_order) {
		std::cout << "\t" << i->FindMember("name")->value.GetString() << std::endl;;
	}
}
Ejemplo n.º 2
0
// Load all the Settings from a file.  If 'initializing' is true, then any 
// corrupted or missing settings are given their default values.  In that way,
// when new settings are added in new versions of the firmware, any values for 
// existing settings will not be lost.
bool Settings::Load(const std::string& filename, bool initializing)
{
    bool retVal = false;
    std::vector<std::string> missing;
    try
    {
        FILE* pFile = fopen(filename.c_str(), "r");
        char buf[LOAD_BUF_LEN];
        FileReadStream frs1(pFile, buf, LOAD_BUF_LEN);
        // first parse into a temporary doc, for validation
        Document doc;
        doc.ParseStream(frs1);

        // make sure the file is valid
        RAPIDJSON_ASSERT(doc.IsObject() && doc.HasMember(SETTINGS_ROOT_KEY))
                
        // create a default doc, to check that all the expected setting names 
        // are present and have the correct type
        // (we may not yet have a valid _settingsDoc)
        Document defaultDoc;
        defaultDoc.Parse(_defaultJSON.c_str());                
                
        for (std::set<std::string>::iterator it = _names.begin(); 
                                             it != _names.end(); ++it)
        {
            if (doc[SETTINGS_ROOT_KEY].HasMember(it->c_str())) 
            {
                if (!AreSameType(defaultDoc[SETTINGS_ROOT_KEY][it->c_str()],
                                       doc[SETTINGS_ROOT_KEY][it->c_str()]))
                {
                    HandleError(WrongTypeForSetting, true, it->c_str());
                    return false;                
                }           
            }
            else
            {
                if (initializing) // record the missing member to be added
                    missing.push_back(*it);
                else
                    throw std::exception(); 
            }
        }
        
        // parse again, but now into _settingsDoc
        fseek(pFile, 0, SEEK_SET);
        FileReadStream frs2(pFile, buf, LOAD_BUF_LEN);
        _settingsDoc.ParseStream(frs2);
        fclose(pFile);  
        
        if (initializing && missing.size() > 0)
        {
            // add any missing settings, with their default values
            for (std::vector<std::string>::iterator it = missing.begin(); 
                                                    it != missing.end(); ++it)
            {
                _settingsDoc[SETTINGS_ROOT_KEY].AddMember(StringRef(it->c_str()), 
                        defaultDoc[SETTINGS_ROOT_KEY][StringRef(it->c_str())], 
                        _settingsDoc.GetAllocator());
            }
            Save();
        }              
        retVal = true;
    }
    catch(std::exception)
    {
        // if we're initializing, we'll handle this by simply regenerating
        // the settings file from scratch
        if (!initializing)
            HandleError(CantLoadSettings, true, filename.c_str());
    } 
    return retVal;
}
Ejemplo n.º 3
0
static void convert_enum(rapidjson::Document & /*doc*/, rapidjson::Value & val, const std::size_t lvl)
{
	filebuf & outf = s_outf_converter;

	RAPIDJSON_ASSERT(val.HasMember("name"));
	const char * ename = val.FindMember("name")->value.GetString();

	bool is_flag = is_enum_flag(val);
	//bool is_msg = is_as_msg(val);
	//const char * fn_prefix = is_msg ? "" : "static inline ";

	RAPIDJSON_ASSERT(val.HasMember("fields"));
	auto & fields = val.FindMember("fields")->value;
	RAPIDJSON_ASSERT(fields.IsObject());

	if (is_flag) {
		std::map<std::string, std::string, cmp_str_as_n> int2string;
		std::map<std::string, std::string> string2int;
		for (rapidjson::Value::MemberIterator itr = fields.MemberBegin(); itr != fields.MemberEnd(); ++itr) {
			const char * name = itr->name.GetString();
			RAPIDJSON_ASSERT(itr->value.IsObject());
			RAPIDJSON_ASSERT(itr->value.HasMember("value"));
			const rapidjson::Value & rval = itr->value.FindMember("value")->value;
			RAPIDJSON_ASSERT(rval.IsString());
			int2string[rval.GetString()] = name;
			string2int[name] = rval.GetString();
		}

		int val_num = (int)string2int.size();
#if 0
		/// @note dec order
		std::vector<std::pair<std::string, std::string>> reorder_pairs;
		for (auto & i : string2int)	reorder_pairs.push_back(i);
		std::sort(reorder_pairs.begin(), reorder_pairs.end(), [=](std::pair<std::string, std::string>& lhs, std::pair<std::string, std::string>& rhs) {
			unsigned long long lhs_n = std::stoull(lhs.second,0,0);
			unsigned long long rhs_n = std::stoull(rhs.second,0,0);
			bool ret = false;
			if (lhs_n < rhs_n) {
				ret = true;
			}
			else if (lhs_n == rhs_n) {
				ret = (lhs.first.compare(rhs.first) < 0);
			}
			else {
				ret = false;
			}
			return !ret;
		});
#endif
		const char * const etype = val.FindMember("type")->value.GetString();

		outf.pf(lvl, "/// @%s : string to enum\n", ename);
		outf.pf(lvl, "static const struct {\n");
		outf.pf(lvl+1, "rapidjson::Value::StringRefType name;\n");
		outf.pf(lvl+1, "%s val;\n", etype);
		outf.pf(lvl, "} str2e_%s[%d] = {\n", ename, val_num);
		for (auto & i : string2int) {
			outf.pf(lvl+1, "{ \"%s\", %s },\n", i.first.c_str(), i.second.c_str());
		}
		outf.pf(lvl, "};\n\n");

		outf.pf(lvl, "/// @%s : enum to string\n", ename);
		outf.pf(lvl, "static const struct {\n");
		outf.pf(lvl+1, "%s val;\n", etype);
		outf.pf(lvl+1, "rapidjson::Value::StringRefType name;\n");
		outf.pf(lvl, "} e2str_%s[%d] = {\n", ename, val_num);
		for (auto & i : int2string) {
			outf.pf(lvl+1, "{ %s, \"%s\" },\n", i.first.c_str(), i.second.c_str());
		}
		outf.pf(lvl, "};\n\n");

		outf.pf(lvl, "static inline rapidjson::Value c2json(rapidjson::Document & jd, const enum %s src)\n", ename);
		outf.pf(lvl, "{ return e2flag(jd, e2str_%s, (%s)src); }\n\n", ename, etype);

		outf.pf(lvl, "static inline void json2c(enum %s & dst, const rapidjson::Value & src)\n", ename);
		outf.pf(lvl, "{ dst = (enum %s)flag2e(str2e_%s, src); }\n", ename, ename);
	}
	else {
		std::map<int, std::string> int2string;
		std::map<std::string, int> string2int;
		for (rapidjson::Value::MemberIterator itr = fields.MemberBegin(); itr != fields.MemberEnd(); ++itr) {
			const char * name = itr->name.GetString();
			RAPIDJSON_ASSERT(itr->value.IsObject());
			RAPIDJSON_ASSERT(itr->value.HasMember("value"));
			int rval = itr->value.FindMember("value")->value.GetInt();
			int2string[rval] = name;
			string2int[name] = rval;
		}

		const int min_val = int2string.begin()->first;
		const int max_val = int2string.rbegin()->first;
		const int val_num = (int)int2string.size();
		const char * etype = val.FindMember("type")->value.GetString();

		outf.pf(lvl, "/// @%s : string to enum\n", ename);
		outf.pf(lvl, "static const struct {\n");
		outf.pf(lvl+1, "rapidjson::Value::StringRefType name;\n");
		outf.pf(lvl+1, "%s val;\n", etype);
		outf.pf(lvl, "} str2e_%s[%d] = {\n", ename, (int)string2int.size());
		for (auto & i : string2int) {
			outf.pf(lvl+1, "{ \"%s\", %d },\n", i.first.c_str(), i.second);
		}
		outf.pf(lvl, "};\n\n");

		outf.pf(lvl, "/// @%s : enum to string\n", ename);
		outf.pf(lvl, "static const struct {\n");
		outf.pf(lvl+1, "%s val;\n", etype);
		outf.pf(lvl+1, "rapidjson::Value::StringRefType name;\n");
		outf.pf(lvl, "} e2str_%s[%d] = {\n", ename, val_num);
		for (auto & i : int2string) {
			outf.pf(lvl+1, "{ %d, \"%s\" },\n", i.first, i.second.c_str());
		}
		outf.pf(lvl, "};\n\n");

		outf.pf(lvl, "static inline rapidjson::Value c2json(rapidjson::Document & /*jd*/, const enum %s src)\n", ename);
		if (val_num >= (max_val - min_val + 1)) {
			if (min_val == 0) {
				outf.pf(lvl, "{ return search_name_directly(e2str_%s, (%s)src); }\n\n", ename, etype);
			}
			else {
				outf.pf(lvl, "{ return search_name_directly(e2str_%s, (%s)src - %d); }\n\n", ename, etype, min_val);
			}
		}
		else {
			outf.pf(lvl, "{ return search_name_binary(e2str_%s, (%s)src); }\n\n", ename, etype);
		}

		outf.pf(lvl, "static inline void json2c(enum %s & dst, const rapidjson::Value & src)\n", ename);
		outf.pf(lvl, "{ dst = (enum %s)search_val_binary(str2e_%s, src); }\n", ename, ename);
	}

	outf.pf(0, "\n");
}