#include "stdafx.h" #include "SpBase.h" #include "SpMisc.h" #include "SpEntity.h" #include "SpModule.h" #include "sp_def.h" #include "sp_dbg_export.h" #include "sp_svc.h" #include "sp_env.h" #include "dbgutil.h" #include "spinlock.h" #include "memutil.h" #include "fileutil.h" #ifdef _WIN32 #include "sp_checkEntity.h" #endif //_WIN32 #include "json/json.h" #include #include #include #include #include ////////////////////////////////////////////////////////////////////////// // CSmallDateTime ////////////////////////////////////////////////////////////////////////// #define __reference_point 946656000LL // _mktime64 2000-01-01 00:00:00 // 2000-01-01 00:00:00 CSmallDateTime CSmallDateTime::BeginTime(0); // about 136 years after 2000-01-01 CSmallDateTime CSmallDateTime::EndTime(0xffffffff); CSmallDateTime CSmallDateTime::GetNow() { #ifdef _WIN32 __time64_t now; //struct tm t; _time64(&now); //_localtime64_s(&t, &now); #else time_t now; time(&now); #endif return CSmallDateTime((DWORD)(now - __reference_point)); } __time64_t CSmallDateTime::GetTime64() { return (__time64_t)(__reference_point + m_nTimeTicks); } CSimpleStringA CSmallDateTime::ToTimeString() { char buff[80]; struct tm when; #ifdef _WIN32 __time64_t t = __reference_point + m_nTimeTicks; _localtime64_s(&when, &t); #else time_t t = __reference_point + m_nTimeTicks; localtime_r(&t, &when); #endif //asctime_s( buff, sizeof(buff), &when ); sprintf(buff, "%04d-%02d-%02d %02d:%02d:%02d", when.tm_year + 1900, when.tm_mon+1, when.tm_mday, when.tm_hour, when.tm_min, when.tm_sec); return CSimpleStringA(buff); } SYSTEMTIME CSmallDateTime::ToSystemTime() { struct tm when; #ifdef _WIN32 __time64_t t = __reference_point + m_nTimeTicks; _localtime64_s(&when, &t); #else time_t t = __reference_point + m_nTimeTicks; localtime_r(&t, &when); #endif SYSTEMTIME st = {}; st.wYear = when.tm_year + 1900; st.wMonth = when.tm_mon+1; st.wDay = when.tm_mday; st.wHour = when.tm_hour; st.wMinute = when.tm_min; st.wSecond = when.tm_sec; return st; } void CSmallDateTime::FromSystemTime(const SYSTEMTIME &st) { struct tm when; when.tm_year = st.wYear - 1900; when.tm_mon = st.wMonth - 1; when.tm_mday = st.wDay; when.tm_hour = st.wHour; when.tm_min = st.wMinute; when.tm_sec = st.wSecond; #ifdef _WIN32 __time64_t t = _mktime64(&when); #else time_t t = mktime(&when); #endif m_nTimeTicks = t - __reference_point; } ////////////////////////////////////////////////////////////////////////// // CUUID ////////////////////////////////////////////////////////////////////////// #ifndef _WIN32 WORD CUUID::m_gAppID(0); #endif //NOT _WIN32 void SpInitUUID(WORD wId) { TOOLKIT_ASSERT(wId != 0); #ifdef _WIN32 getEntityResource()->m_gAppID = wId; #else CUUID::m_gAppID = wId; #endif //_WIN32 } CUUID CUUID::Create(const CUUID &LastUUID) { #ifdef _WIN32 TOOLKIT_ASSERT(getEntityResource()->m_gAppID != 0); #endif //_WIN32 CUUID t(0); #ifdef _WIN32 t.m_nAppID = getEntityResource()->m_gAppID; #else t.m_nAppID = CUUID::m_gAppID; #endif //_WIN32 DWORD now = (DWORD) CSmallDateTime::GetNow(); if (now == LastUUID.m_nTimeTicks) { t.m_nDsn = LastUUID.m_nDsn+1; if (t.m_nDsn <=0) { t.m_nTimeTicks = now + 1; t.m_nDsn = 0; } else { t.m_nTimeTicks = now; } } else { t.m_nTimeTicks = now; t.m_nDsn = 0; } //LastUUID.m_nUUID64 = t.m_nUUID64; return t; } CUUID CUUID::Create(const CUUID& LastUUID, const CSmallDateTime& DateTime) { #ifdef _WIN32 TOOLKIT_ASSERT(getEntityResource()->m_gAppID != 0); #endif //_WIN32 CUUID t(0); int repeat = 0; #ifdef _WIN32 t.m_nAppID = getEntityResource()->m_gAppID; #else t.m_nAppID = CUUID::m_gAppID; #endif //_WIN32 t.m_nTimeTicks = DateTime; t.m_nDsn = 0; //LastUUID.m_nUUID64 = t.m_nUUID64; return t; } ///////////////////////////////////////////////////////////////////////////////////////////////////// /// CSphereVector ///////////////////////////////////////////////////////////////////////////////////////////////////// // 将float转成度分秒表示法,第4个字节表示经度或纬度方向 void CSphereVector::GetBinaryLongitude(BYTE longitude[4]) { float fTemp = m_fLongitude; if (fTemp < 0) { longitude[3] = 'W'; fTemp = -fTemp; } else longitude[3] = 'E'; longitude[0] = (int)fTemp; longitude[1] = (int)(fTemp * 60) % 60; longitude[2] = (int)(fTemp * 3600) % 60; } void CSphereVector::GetBinaryLatitude(BYTE latitude[4]) { float fTemp = m_fLongitude; if (fTemp < 0) { latitude[3] = 'S'; fTemp = -fTemp; } else latitude[3] = 'N'; latitude[0] = (int)fTemp; latitude[1] = (int)(fTemp * 60) % 60; latitude[2] = (int)(fTemp * 3600) % 60; } ///////////////////////////////////////////////////////////////////////////////////////////////////// ErrorCodeEnum SpIniFileReadString( const char *pszFile, const char *pszSection, const char *pszKey, CSimpleStringA &strValue ) { DWORD dwInitCapacity = 16, dwSize = 0; const int tries = 20; int i; for (i = 0; i < tries; ++i) { CSimpleStringA strTmp('\0', dwInitCapacity); dwSize = ::GetPrivateProfileStringA(pszSection, pszKey, "", &strTmp[0], dwInitCapacity, pszFile); if (dwSize == dwInitCapacity-1) { dwInitCapacity = dwInitCapacity * 2; // buffer is too small, double size } else { strValue = strTmp; break; } } if (i == tries) return Error_Unexpect; return Error_Succeed; } ErrorCodeEnum SpIniFileWriteString( const char *pszFile, const char *pszSection, const char *pszKey, const char *pszValue ) { BOOL bRet = ::WritePrivateProfileStringA(pszSection, pszKey, pszValue, pszFile); WritePrivateProfileStringA(NULL, NULL, NULL, pszFile); if (bRet) return Error_Succeed; return Error_Unexpect; } ErrorCodeEnum SpIniFileReadAllKeys(const char *pszFile, const char *pszSection, CAutoArray &Keys) { DWORD dwInitialCapacity = 16; DWORD dwSize; char *p = NULL; const int tries = 20; ErrorCodeEnum Error = Error_Succeed; int i; for (i = 0; i < tries; ++i) { p = (char*)realloc(p, dwInitialCapacity); dwSize = ::GetPrivateProfileStringA(pszSection, NULL, NULL, p, dwInitialCapacity, pszFile); if (dwSize == dwInitialCapacity-2) { // buffer is too small dwInitialCapacity = dwInitialCapacity * 2; } else { break; } } if (i < tries) { int cnt = 0; char *t = p; size_t n; while ((n = strlen(t)) > 0) { cnt ++; t += n+1; } Keys.Init(cnt); t = p; for (i = 0; i < cnt; ++i) { Keys[i] = t; t = t + strlen(t)+1; } } else { Error = Error_Unexpect; } free(p); return Error; } ErrorCodeEnum SpIniFileReadAllSections(const char *pszFile, CAutoArray &Sections) { DWORD dwInitialCapacity = 16; DWORD dwSize; char *p = NULL; const int tries = 20; ErrorCodeEnum Error = Error_Succeed; int i; for (i = 0; i < tries; ++i) { p = (char*)realloc(p, dwInitialCapacity); dwSize = ::GetPrivateProfileSectionNamesA(p, dwInitialCapacity, pszFile); if (dwSize == dwInitialCapacity-2) { // buffer is too small dwInitialCapacity = dwInitialCapacity * 2; } else { break; } } if (i < tries) { int cnt = 0; char *t = p; size_t n; while ((n = strlen(t)) > 0) { cnt ++; t += n+1; } Sections.Init(cnt); t = p; for (i = 0; i < cnt; ++i) { Sections[i] = t; t = t + strlen(t)+1; } } else { Error = Error_Unexpect; } free(p); return Error; } ErrorCodeEnum SpIniConfig::ReadConfigValue(const char *pszSection, const char *pszKey, CSimpleStringA &strValue) { _ASSERT(pszSection); _ASSERT(pszKey); CSimpleStringA path; ErrorCodeEnum Error = _GetMappFilePath(path); if (Error == Error_Succeed) Error = SpIniFileReadString(path, pszSection, pszKey, strValue); return Error; } ErrorCodeEnum SpIniConfig::ReadConfigValueInt(const char *pszSection, const char *pszKey, int &iValue) { CSimpleStringA strValue; ErrorCodeEnum Error = ReadConfigValue(pszSection, pszKey, strValue); if (Error == Error_Succeed) { if (strValue.IsStartWith("0x")) // support hex string sscanf(strValue, "0x%X", &iValue); else iValue = atoi(strValue); } return Error; } //TODO: forbid from write cfg/entity.ini ErrorCodeEnum SpIniConfig::WriteConfigValue(const char *pszSection, const char *pszKey, const char *pszValue) { if (m_type == Config_Hardware || m_type == Config_Shell || m_type == Config_Root || m_type == Config_CenterSetting) { return Error_Readonly; } CSimpleStringA path; ErrorCodeEnum Error = _GetMappFilePath(path); if (Error == Error_Succeed) { Error = SpIniFileWriteString(path, pszSection, pszKey, pszValue); } return Error; } ErrorCodeEnum SpIniConfig::WriteConfigValueInt(const char *pszSection, const char *pszKey, int iValue) { char tmp[32]; _itoa(iValue, tmp, 10); return WriteConfigValue(pszSection, pszKey, tmp); } ErrorCodeEnum SpIniConfig::WriteConfigValueHexInt(const char *pszSection, const char *pszKey, UINT64 nValue) { char tmp[32]; #if defined(_MSC_VER) sprintf_s(tmp, sizeof(tmp), "0x%I64X", nValue); #else sprintf_s(tmp, sizeof(tmp), "0x%" PRIx64 "", nValue); #endif //_MSC_VER return WriteConfigValue(pszSection, pszKey, tmp); } ErrorCodeEnum SpIniConfig::ReadConfigValueHexInt(const char *pszSection, const char *pszKey, UINT64 &nValue) { nValue = 0; CSimpleStringA strValue; ErrorCodeEnum Error = ReadConfigValue(pszSection, pszKey, strValue); if (Error == Error_Succeed && strValue.GetLength() > 0) { #if defined(_MSC_VER) if (strValue.IsStartWith("0x")) // support hex string sscanf(strValue, "0x%I64X", &nValue); else sscanf(strValue, "%I64X", &nValue); #else if (strValue.IsStartWith("0x")) // support hex string sscanf(strValue, "0x%" PRIx64 "", &nValue); else sscanf(strValue, "%" PRIx64 "", &nValue); #endif //_MSC_VER } return Error; } ErrorCodeEnum SpIniConfig::EstimateBeforeRW() { ErrorCodeEnum result(Error_Succeed); if (m_type == Config_Hardware || m_type == Config_Shell || m_type == Config_Root || m_type == Config_CenterSetting || m_type == Config_Software) { CSimpleStringA strAbsolutePath(true); result = _GetMappFilePath(strAbsolutePath); if (Error_Succeed == result && !strAbsolutePath.IsNullOrEmpty()) { if (!ExistsFileA(strAbsolutePath)) { result = Error_NotExist; } } else if (Error_Succeed == result) { result = Error_Null; } } return result; } ErrorCodeEnum SpIniConfig::_GetMappFilePath(CSimpleStringA& strPath) { char tmp[MAX_PATH]; ErrorCodeEnum Error; sp_env_t* env = sp_get_env(); int flag; if (m_type == Config_Hardware) { flag = SP_DIR_DEVICE_ENTITY_INI; } else if (m_type == Config_Software) { flag = SP_DIR_ENTITY_INI; } else if (m_type == Config_Run) { flag = SP_DIR_RUNINFO_INI; } else if (m_type == Config_Shell) { flag = SP_DIR_SHELL_INI; } else if (m_type == Config_Root) { flag = SP_DIR_ROOT_INI; } else if (m_type == Config_CenterSetting) { flag = SP_DIR_CENTER_SETTING_INI; } else if (m_type == Config_Cache) { flag = SP_DIR_RUNINFO_GLOBAL_INI; } else { return Error_Param; } /** 集中配置文件的获取单独处理*/ if (m_type == Config_CenterSetting) { CSimpleStringA strCtsPath; Error = m_pEntity->GetPath("CenterSetting", strCtsPath); strcpy_s(tmp, MAX_PATH, strCtsPath); } else { Error = (ErrorCodeEnum)sp_dir_get_path_new(env->dir, flag, m_pEntity->get_ent()->cfg->name, tmp, MAX_PATH, detect_env_test_mode(env->cfg->args->test_mode)); } strPath = tmp; return Error; } ErrorCodeEnum SpIniConfig::ReadAllKeys(const char *pszSection, CAutoArray &strKeys) { _ASSERT(pszSection); CSimpleStringA path; ErrorCodeEnum Error = _GetMappFilePath(path); if (Error == Error_Succeed) Error = SpIniFileReadAllKeys(path, pszSection, strKeys); return Error; } ErrorCodeEnum SpIniConfig::ReadAllSections(CAutoArray &strSections) { CSimpleStringA path; ErrorCodeEnum Error = _GetMappFilePath(path); if (Error == Error_Succeed) Error = SpIniFileReadAllSections(path, strSections); return Error; } class SpRootMemConfig::Impl { public: static std::string toLowerCase(std::string str) { #ifdef _WIN32 std::transform(str.begin(), str.end(), str.begin(), [](unsigned char c) { return std::tolower(c, std::locale()); }); #else for (char& c : str) { c = std::tolower(c); } #endif return str; } ConfigTypeEnum type; std::map> m_deviceConfig; std::map> m_centerConfig; std::map> m_shellConfig; std::map> m_nullConfig; std::map>& getCurConfig() { if (type == ConfigTypeEnum::Config_CenterSetting) return m_centerConfig; else if (type == ConfigTypeEnum::Config_Root) return m_deviceConfig; else if (type == ConfigTypeEnum::Config_Shell) return m_shellConfig; else return m_nullConfig; } static std::pair ConvertStrToDeviceConfig(std::string input, std::map> &config) { // 解析为Json::Value Json::Reader reader; Json::Value jsonValue; bool success = reader.parse(input, jsonValue); if (!success) return std::make_pair(false, CSimpleStringA::Format("ConvertStrToDeviceConfig Failed to parse input: %s", reader.getFormattedErrorMessages().c_str()).GetData()); // 转换为std::map config.clear(); Json::Value::Members outer_members = jsonValue.getMemberNames(); for (Json::Value::Members::iterator outer_it = outer_members.begin(); outer_it != outer_members.end(); ++outer_it) { const std::string& outer_key = *outer_it; const Json::Value& inner_value = jsonValue[outer_key]; std::map inner_map; Json::Value::Members inner_members = inner_value.getMemberNames(); for (Json::Value::Members::iterator inner_it = inner_members.begin(); inner_it != inner_members.end(); ++inner_it) { const std::string& inner_key = *inner_it; const std::string& inner_value = jsonValue[outer_key][inner_key].asString(); inner_map.insert(std::make_pair(toLowerCase(inner_key), inner_value)); } config.insert(std::make_pair(toLowerCase(outer_key), inner_map)); } // 输出结果 return std::make_pair(true, ""); } }; SpRootMemConfig::SpRootMemConfig(SpEntity* pEntity, ConfigTypeEnum type) : m_pEntity(pEntity) , m_type(type) , m_impl(new Impl()) { sp_env_t* env = sp_get_env(); sp_cfg_t* cfg = env->cfg; sp_cfg_root_ini_t* root_ini = cfg->root_ini; m_impl->type = type; if (m_impl->m_deviceConfig.size() == 0 && type == ConfigTypeEnum::Config_Root)//首次初始化 m_impl->ConvertStrToDeviceConfig(root_ini->root_config, m_impl->m_deviceConfig); if (m_impl->m_centerConfig.size() == 0 && type == ConfigTypeEnum::Config_CenterSetting) m_impl->ConvertStrToDeviceConfig(root_ini->center_config, m_impl->m_centerConfig); if (m_impl->m_shellConfig.size() == 0 && type == ConfigTypeEnum::Config_Shell) m_impl->ConvertStrToDeviceConfig(root_ini->shell_config, m_impl->m_shellConfig); } SpRootMemConfig::~SpRootMemConfig() { if (m_impl != NULL) { delete m_impl; } } ErrorCodeEnum SpRootMemConfig::ReadConfigValue(const char* pszSection, const char* pszKey, CSimpleStringA& strValue) { _ASSERT(pszSection); _ASSERT(pszKey); auto config = m_impl->getCurConfig(); //can not find section //都转换成小写,避免查不到 auto dstSection = m_impl->toLowerCase(pszSection); auto dstKey = m_impl->toLowerCase(pszKey); //因为存储名字不同,terminal需要进行转换 if (dstSection == "terminal") dstSection = "terminalinfo"; DWORD dwInitCapacity = 16; CSimpleStringA strTmp('\0', dwInitCapacity); if (config.find(dstSection) == config.end()) { strValue = strTmp; DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("ReadConfigValue can not find section:%s", dstSection.c_str()); return Error_Succeed; } //can not find key if (config[dstSection].find(dstKey) == config[dstSection].end()) { strValue = strTmp; DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("ReadConfigValue can not find value:%s", dstKey.c_str()); return Error_Succeed; } strValue = config[dstSection][dstKey].c_str(); return Error_Succeed; } ErrorCodeEnum SpRootMemConfig::ReadConfigValueInt(const char* pszSection, const char* pszKey, int& iValue) { CSimpleStringA strValue; ErrorCodeEnum Error = ReadConfigValue(pszSection, pszKey, strValue); if (Error == Error_Succeed) { if (strValue.IsStartWith("0x")) // support hex string sscanf(strValue, "0x%X", &iValue); else iValue = atoi(strValue); } return Error; } ErrorCodeEnum SpRootMemConfig::WriteConfigValue(const char* pszSection, const char* pszKey, const char* pszValue) { return Error_Readonly; } ErrorCodeEnum SpRootMemConfig::WriteConfigValueInt(const char* pszSection, const char* pszKey, int iValue) { char tmp[32]; _itoa(iValue, tmp, 10); return WriteConfigValue(pszSection, pszKey, tmp); } ErrorCodeEnum SpRootMemConfig::ReadAllKeys(const char* pszSection, CAutoArray& strKeys) { _ASSERT(pszSection); auto config = m_impl->getCurConfig(); auto dstSection = m_impl->toLowerCase(pszSection); //can not find section if (config.find(dstSection) == config.end()) return Error_NotExist; strKeys.Init(config[dstSection].size()); int keys_i = 0; for (auto it = config[dstSection].begin(); it != config[dstSection].end(); it++) strKeys[keys_i++] = it->first.c_str(); return Error_Succeed; } ErrorCodeEnum SpRootMemConfig::ReadAllSections(CAutoArray& strSections) { auto config = m_impl->getCurConfig(); strSections.Init(config.size()); int sections_i = 0; for (auto it = config.begin(); it != config.end(); it++) strSections[sections_i++] = it->first.c_str(); return Error_Succeed; } ErrorCodeEnum SpRootMemConfig::WriteConfigValueHexInt(const char* pszSection, const char* pszKey, UINT64 nValue) { char tmp[32]; sprintf_s(tmp, sizeof(tmp), "0x%I64X", nValue); return WriteConfigValue(pszSection, pszKey, tmp); } ErrorCodeEnum SpRootMemConfig::ReadConfigValueHexInt(const char* pszSection, const char* pszKey, UINT64& nValue) { nValue = 0; CSimpleStringA strValue; ErrorCodeEnum Error = ReadConfigValue(pszSection, pszKey, strValue); if (Error == Error_Succeed && strValue.GetLength() > 0) { if (strValue.IsStartWith("0x")) // support hex string sscanf(strValue, "0x%I64X", &nValue); else sscanf(strValue, "%I64X", &nValue); } return Error; }