/************************************************************************ MeOS - Orienteering Software Copyright (C) 2009-2024 Melin Software HB This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Melin Software HB - software@melin.nu - www.melin.nu Eksoppsvägen 16, SE-75646 UPPSALA, Sweden ************************************************************************/ #include "stdafx.h" #include #include #include "meos_util.h" #include "localizer.h" #include "oFreeImport.h" #include "meosexception.h" #include using namespace std; StringCache globalStringCache; namespace MeOSUtil { int useHourFormat = true; } string convertSystemTimeN(const SYSTEMTIME &st); string convertSystemDateN(const SYSTEMTIME &st); string convertSystemTimeOnlyN(const SYSTEMTIME &st); extern int defaultCodePage; DWORD mainThreadId = -1; StringCache &StringCache::getInstance() { DWORD id = GetCurrentThreadId(); if (mainThreadId == -1) mainThreadId = id; else if (mainThreadId != id) throw std::exception("Thread access error"); return globalStringCache; } string getLocalTimeN() { SYSTEMTIME st; GetLocalTime(&st); return convertSystemTimeN(st); } string getLocalDateN() { SYSTEMTIME st; GetLocalTime(&st); return convertSystemDateN(st); } wstring getLocalTime() { SYSTEMTIME st; GetLocalTime(&st); return convertSystemTime(st); } wstring getLocalDate() { SYSTEMTIME st; GetLocalTime(&st); return convertSystemDate(st); } int getLocalAbsTime() { return convertAbsoluteTimeHMS(getLocalTimeOnly(), -1); } int getThisYear() { static int thisYear = 0; if (thisYear == 0) { SYSTEMTIME st; GetLocalTime(&st); thisYear = st.wYear; } return thisYear; } /** Extend a year from 03 -> 2003, 97 -> 1997 etc */ int extendYear(int year) { if (year<0) return year; if (year>=100) return year; int thisYear = getThisYear(); int cLast = thisYear%100; if (cLast == 0 && year == 0) return thisYear; if (year > thisYear%100) return (thisYear - cLast) - 100 + year; else return (thisYear - cLast) + year; } wstring getLocalTimeFileName() { SYSTEMTIME st; GetLocalTime(&st); wchar_t bf[32]; swprintf_s(bf, L"%d%02d%02d_%02d%02d%02d", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond); return bf; } string getLocalTimeOnlyN() { SYSTEMTIME st; GetLocalTime(&st); return convertSystemTimeOnlyN(st); } wstring getLocalTimeOnly() { SYSTEMTIME st; GetLocalTime(&st); return convertSystemTimeOnly(st); } int getRelativeDay() { SYSTEMTIME st; GetLocalTime(&st); FILETIME ft; SystemTimeToFileTime(&st, &ft); ULARGE_INTEGER u; u.HighPart = ft.dwHighDateTime; u.LowPart = ft.dwLowDateTime; __int64 qp = u.QuadPart; qp /= __int64(10) * 1000 * 1000 * 3600 * 24; qp -= 400*365; return int(qp); } __int64 SystemTimeToInt64TenthSecond(const SYSTEMTIME &st) { FILETIME ft; SystemTimeToFileTime(&st, &ft); ULARGE_INTEGER u; u.HighPart = ft.dwHighDateTime; u.LowPart = ft.dwLowDateTime; __int64 qp = u.QuadPart; // Time resolution 100 ns qp /= __int64(1000 * 1000 * 10 / timeUnitsPerSecond); return qp; } SYSTEMTIME Int64TenthSecondToSystemTime(__int64 time) { SYSTEMTIME st; FILETIME ft; ULARGE_INTEGER u; // Time resolution 100 ns u.QuadPart = time * __int64(1000 * 1000 * 10 / timeUnitsPerSecond); ft.dwHighDateTime = u.HighPart; ft.dwLowDateTime = u.LowPart; FileTimeToSystemTime(&ft, &st); return st; } //2014-11-03 07:02:00 string convertSystemTimeN(const SYSTEMTIME &st) { char bf[64]; sprintf_s(bf, "%d-%02d-%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond); return bf; } //2014-11-03 07:02:00 wstring convertSystemTime(const SYSTEMTIME &st) { wchar_t bf[64]; swprintf_s(bf, L"%d-%02d-%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond); return bf; } string convertSystemTimeOnlyN(const SYSTEMTIME &st) { char bf[32]; sprintf_s(bf, "%02d:%02d:%02d", st.wHour, st.wMinute, st.wSecond); return bf; } wstring convertSystemTimeOnly(const SYSTEMTIME &st) { wchar_t bf[32]; swprintf_s(bf, L"%02d:%02d:%02d", st.wHour, st.wMinute, st.wSecond); return bf; } string convertSystemDateN(const SYSTEMTIME &st) { char bf[32]; sprintf_s(bf, "%d-%02d-%02d", st.wYear, st.wMonth, st.wDay); return bf; } wstring convertSystemDate(const SYSTEMTIME &st) { wchar_t bf[32]; swprintf_s(bf, L"%d-%02d-%02d", st.wYear, st.wMonth, st.wDay); return bf; } string formatDateN(int m, bool useIsoFormat) { char bf[24]; if (m > 0 && m < 30000101) { sprintf_s(bf, 24, "%d-%02d-%02d", m/(100*100), (m/100)%100, m%100); } else { bf[0] = '-'; bf[1] = 0; } return bf; } wstring formatDate(int m, bool useIsoFormat) { wchar_t bf[24]; if (m > 0 && m < 30000101) { swprintf_s(bf, 24, L"%d-%02d-%02d", m/(100*100), (m/100)%100, m%100); } else { bf[0] = '-'; bf[1] = 0; } return bf; } int convertDateYMD(const wstring &m, SYSTEMTIME &st, bool checkValid) { string ms(m.begin(), m.end()); return convertDateYMD(ms, st, checkValid); } //Absolute time string to SYSTEM TIME int convertDateYMD(const string& m, SYSTEMTIME& st, bool checkValid) { memset(&st, 0, sizeof(st)); if (m.length() == 0) return -1; int len = m.length(); int dashCount = 0; for (int k = 0; k < len; k++) { BYTE b = m[k]; if (b == 'T') break; if (!(b == '-' || b == ' ' || (b >= '0' && b <= '9'))) return -1; if (b == '-') dashCount++; } int year = atoi(m.c_str()); if (dashCount == 0) { int day = year % 100; year /= 100; int month = year % 100; year /= 100; if ((year > 0 && year < 100) || (year == 0 && m.size() > 2 && m[0] == '0' && m[1] == '0')) year = extendYear(year); if (year < 1900 || year>3000) return -1; if (month < 1 || month>12) { if (checkValid) return -1; month = 1; } if (day < 1 || day>31) { if (checkValid) return -1; day = 1; } st.wYear = year; st.wMonth = month; st.wDay = day; int t = year * 100 * 100 + month * 100 + day; if (t < 0) return -1; return t; } if ((year > 0 && year < 100) || (year == 0 && m.size() > 2 && m[0] == '0' && m[1] == '0')) year = extendYear(year); if (year < 1900 || year>3000) return -1; int month = 0; int day = 0; int kp = m.find_first_of('-'); if (kp != string::npos) { string mtext = m.substr(kp + 1); month = atoi(mtext.c_str()); if (month < 1 || month>12) { if (checkValid) return -1; month = 1; } kp = mtext.find_last_of('-'); if (kp != string::npos) { day = atoi(mtext.substr(kp + 1).c_str()); if (day < 1 || day>31) { if (checkValid) return -1; day = 1; } } } st.wYear = year; st.wMonth = month; st.wDay = day; int t = year * 100 * 100 + month * 100 + day; if (t < 0) return -1; return t; } //Absolute time string to absolute time int int convertDateYMD(const string &m, bool checkValid) { SYSTEMTIME st; return convertDateYMD(m, st, checkValid); } int convertDateYMD(const wstring &m, bool checkValid) { SYSTEMTIME st; return convertDateYMD(m, st, checkValid); } bool myIsSpace(wchar_t b) { return iswspace(b) != 0 || b == 0x00A0 || b == 0x2007 || b == 0x202F; } //Absolute time string to absolute time int int convertAbsoluteTimeHMS(const string &m, int daysZeroTime) { int len = m.length(); if (len==0 || m[0]=='-') return -1; // Support for notation 2D 14:30:00 or 2T14:30:00 for several days int tix = -1; for (size_t k = 0; k < m.length(); k++) { int c = m[k]; if (c =='D' || c =='d' || c =='T' || c =='t') { tix = k; break; } } if (tix != -1) { if (daysZeroTime < 0) return -1; // Not supported int tpart = convertAbsoluteTimeHMS(m.substr(tix+1), -1); if (tpart != -1) { int days = atoi(m.c_str()); if (days <= 0) return -1; if (tpart < daysZeroTime) days--; return days * timeConstHour * 24 + tpart; } return -1; } int plusIndex = -1; for (int k=0;k='0' && b<='9') || b == '.' || b == ',') ) { if (b=='+' && plusIndex ==-1 && k>0) plusIndex = k; else return -1; } } if (plusIndex>0) { int t = convertAbsoluteTimeHMS(m.substr(plusIndex+1), -1); int d = atoi(m.c_str()); if (d>0 && t>=0) return d*24* timeConstHour + t; else return -1; } int hour=atoi(m.c_str()); if (hour<0 || hour>23) return -1; int minute=0; int second=0; int tenth = 0; int kp=m.find_first_of(':'); if (kp!=string::npos) { string mtext=m.substr(kp+1); minute=atoi(mtext.c_str()); if (minute<0 || minute>60) minute=0; kp=mtext.find_last_of(':'); if (kp!=string::npos) { second=atoi(mtext.c_str() + kp+1); if (second<0 || second>60) second=0; if (timeConstSecond > 1) { kp = mtext.find_last_of('.'); if (kp == string::npos) kp = mtext.find_last_of(','); if (kp != string::npos) { tenth = atoi(mtext.c_str() + kp + 1); if (tenth < 0 || tenth >= 10) tenth = 0; } } } } int t = hour * timeConstHour + minute * timeConstMinute + second * timeConstSecond + tenth; if (t<0) return 0; return t; } //Absolute time string to absolute time int int convertAbsoluteTimeHMS(const wstring &m, int daysZeroTime) { string sm(m.begin(), m.end()); return convertAbsoluteTimeHMS(sm, daysZeroTime); } //Absolute time string to absolute time int int convertAbsoluteTimeISO(const string &m) { int len = m.length(); if (len==0 || m[0]=='-') return -1; string hStr, mStr, sStr; string tmp = trim(m); if (tmp.length() < 3) return -1; hStr = tmp.substr(0, 2); if (!(tmp[2] >= '0' && tmp[2]<='9')) tmp = tmp.substr(3); else tmp = tmp.substr(2); if (tmp.length() < 3) return -1; mStr = tmp.substr(0, 2); if (!(tmp[2] >= '0' && tmp[2]<='9')) tmp = tmp.substr(3); else tmp = tmp.substr(2); if (tmp.length() < 2) return -1; sStr = tmp.substr(0, 2); for (int i = 0; i < 2; i++) { if (hStr[i] < '0' || hStr[i] > '9') return -1; if (mStr[i] < '0' || mStr[i] > '9') return -1; if (sStr[i] < '0' || sStr[i] > '9') return -1; } int hour = atoi(hStr.c_str()); if (hour<0 || hour>23) return -1; int minute = atoi(mStr.c_str()); if (minute<0 || minute>60) return -1; int second = atoi(sStr.c_str()); if (second<0 || second>60) return -1; int t = hour * timeConstHour + minute * timeConstMinute + second; return t; } int convertAbsoluteTimeISO(const wstring &m) { string mn(m.begin(), m.end()); return convertAbsoluteTimeISO(mn); } // Parse +-MM:SS or +-HH:MM:SS int convertAbsoluteTimeMS(const string &m) { if (m.length()==0) return NOTIME; int minute=0; int second=0; int signpos=m.find_first_of('-'); string mtext; int sign=1; if (signpos!=string::npos) { sign=-1; mtext=m.substr(signpos+1); } else mtext=m; minute=atoi(mtext.c_str()); int hour = 0; if (minute<0 || minute>60*24) minute=0; int kp=mtext.find_first_of(':'); bool gotSecond = false; if (kp!=string::npos) { mtext = mtext.substr(kp+1); second = atoi(mtext.c_str()); gotSecond = true; if (second<0 || second>60) second=0; } int t; kp = mtext.find_first_of(':'); if (kp != string::npos) { //Allow also for format +-HH:MM:SS hour = minute; minute = second; mtext = mtext.substr(kp + 1); second = atoi(mtext.c_str()); if (second < 0 || second>60) second = 0; } int tenth = 0; if (timeConstSecond > 1) { kp = mtext.find_first_of('.'); if (kp == string::npos) kp = mtext.find_last_of(','); if (kp != string::npos) { tenth = atoi(mtext.c_str() + kp + 1); if (!gotSecond) { // Reinterpret minute as second (no minute was specified) second = minute; minute = 0; } if (tenth < 0 || tenth >= 10) tenth = 0; } } t = hour * timeConstHour + minute * timeConstMinute + second * timeConstSecond + tenth; return sign*t; } int convertAbsoluteTimeMS(const wstring &m) { string mn(m.begin(), m.end()); return convertAbsoluteTimeMS(mn); } //Generate +-MM:SS or +-HH:MM:SS const wstring &formatTimeMS(int m, bool force2digit, SubSecond mode) { wchar_t bf[32]; int am = abs(m); if (am < timeConstHour || !MeOSUtil::useHourFormat) { if (force2digit) { if (mode == SubSecond::Off || (mode == SubSecond::Auto && m % 10 == 0)) swprintf_s(bf, L"-%02d:%02d", am / timeConstMinute, (am / timeConstSecond) % 60); else swprintf_s(bf, L"-%02d:%02d.%d", am / timeConstMinute, (am / timeConstSecond) % 60, am % timeConstSecond); } else { if (mode == SubSecond::Off || (mode == SubSecond::Auto && m % 10 == 0)) swprintf_s(bf, L"-%d:%02d", am / timeConstMinute, (am / timeConstSecond) % 60); else swprintf_s(bf, L"-%d:%02d.%d", am / timeConstMinute, (am / timeConstSecond) % 60, am % timeConstSecond); } } else if (am < timeConstHour * 48) { if (force2digit) { if (mode == SubSecond::Off || (mode == SubSecond::Auto && m % 10 == 0)) swprintf_s(bf, L"-%02d:%02d:%02d", am / timeConstHour, (am / timeConstMinute) % 60, (am / timeConstSecond) % 60); else swprintf_s(bf, L"-%02d:%02d:%02d.%d", am / timeConstHour, (am / timeConstMinute) % 60, (am / timeConstSecond) % 60, am % timeConstSecond); } else { if (mode == SubSecond::Off || (mode == SubSecond::Auto && m % 10 == 0)) swprintf_s(bf, L"-%d:%02d:%02d", am / timeConstHour, (am / timeConstMinute) % 60, (am / timeConstSecond) % 60); else swprintf_s(bf, L"-%d:%02d:%02d.%d", am / timeConstHour, (am / timeConstMinute) % 60, (am / timeConstSecond) % 60, am % timeConstSecond); } } else { m = 0; bf[0] = 0x2013; bf[1] = 0; } wstring &res = StringCache::getInstance().wget(); if (m<0) res = bf; // with minus else res = bf + 1; return res; } const wstring &formatTime(int rt, SubSecond mode) { wstring &res = StringCache::getInstance().wget(); if (rt>0 && rt= timeConstHour && MeOSUtil::useHourFormat) swprintf_s(bf, L"%d:%02d:%02d", rt / timeConstHour, (rt / timeConstMinute) % 60, (rt / timeConstSecond) % 60); else swprintf_s(bf, L"%d:%02d", (rt / timeConstMinute), (rt / timeConstSecond) % 60); } else { if (rt >= timeConstHour && MeOSUtil::useHourFormat) swprintf_s(bf, L"%d:%02d:%02d.%d", rt / timeConstHour, (rt / timeConstMinute) % 60, (rt / timeConstSecond) % 60, rt%timeConstSecond); else swprintf_s(bf, L"%d:%02d.%d", (rt / timeConstMinute), (rt / timeConstSecond) % 60, rt%timeConstSecond); } res = bf; return res; } wchar_t ret[2] = {0x2013, 0}; res = ret; return res; } const string &formatTimeN(int rt) { string &res = StringCache::getInstance().get(); if (rt>0 && rt= timeConstHour && MeOSUtil::useHourFormat) sprintf_s(bf, 16, "%d:%02d:%02d", rt/ timeConstHour,(rt/timeConstMinute)%60, (rt/timeConstSecond)%60); else sprintf_s(bf, 16, "%d:%02d", (rt/timeConstMinute), (rt/timeConstSecond)%60); res = bf; return res; } res = "-"; return res; } const wstring &formatTimeHMS(int rt, SubSecond mode) { wstring &res = StringCache::getInstance().wget(); if (rt>=0) { wchar_t bf[40]; if (mode == SubSecond::Off || (mode == SubSecond::Auto && rt%10 == 0)) swprintf_s(bf, 16, L"%02d:%02d:%02d", rt/timeConstHour,(rt/timeConstMinute)%60, (rt/timeConstSecond)%60); else swprintf_s(bf, 16, L"%02d:%02d:%02d.%d", rt / timeConstHour, (rt / timeConstMinute) % 60, (rt / timeConstSecond) % 60, rt % timeConstSecond); res = bf; return res; } wchar_t ret[2] = {0x2013, 0}; res = ret; return res; } wstring formatTimeIOF(int rt, int zeroTime) { if (rt > 0) { rt += zeroTime; wchar_t bf[16]; swprintf_s(bf, 16, L"%02d:%02d:%02d", (rt / timeConstHour) % 24, (rt / timeConstMinute) % 60, (rt / timeConstSecond) % 60); return bf; } return L"--:--:--"; } size_t find(const wstring &str, const wstring &separator, size_t startpos) { size_t seplen = separator.length(); for (size_t m = startpos; m & split(const string &line, const string &separators, vector &split_vector) { split_vector.clear(); if (line.empty()) return split_vector; size_t startpos=0; size_t nextp=find(line, separators, startpos); split_vector.push_back(line.substr(startpos, nextp-startpos)); while(nextp!=line.npos) { startpos=nextp+1; nextp=find(line, separators, startpos); split_vector.push_back(line.substr(startpos, nextp-startpos)); } return split_vector; } const vector & split(const wstring &line, const wstring &separators, vector &split_vector) { split_vector.clear(); if (line.empty()) return split_vector; size_t startpos=0; size_t nextp=find(line, separators, startpos); split_vector.push_back(line.substr(startpos, nextp-startpos)); while(nextp!=line.npos) { startpos=nextp+1; nextp=find(line, separators, startpos); split_vector.push_back(line.substr(startpos, nextp-startpos)); } return split_vector; } const string &unsplit(const vector &split_vector, const string &separators, string &line) { size_t s = split_vector.size() * separators.size(); for (size_t k = 0; k < split_vector.size(); k++) { s += split_vector[k].size(); } line.clear(); line.reserve(s); for (size_t k = 0; k < split_vector.size(); k++) { if (k != 0) line += separators; line += split_vector[k]; } return line; } const wstring &unsplit(const vector &split_vector, const wstring &separators, wstring &line) { size_t s = split_vector.size() * separators.size(); for (size_t k = 0; k < split_vector.size(); k++) { s += split_vector[k].size(); } line.clear(); line.reserve(s); for (size_t k = 0; k < split_vector.size(); k++) { if (k != 0) line += separators; line += split_vector[k]; } return line; } const wstring &limitText(const wstring& tIn, size_t numChar) { wstring& out = StringCache::getInstance().wget(); out.clear(); const auto L = tIn.length(); //if (L < numChar) // out = tIn; int spacePos = -1; int outP = 0; int i = 0; for (; i < L && outP < numChar-1; i++) { wchar_t c = tIn[i]; if (c == '\n' || c == '\r' || c == '\t') c = ' '; if (c==' ' && spacePos == outP) continue; // Skip duplicate space out.push_back(c); outP++; if (iswspace(c)) spacePos = outP; } if (i < L) { if (spacePos <= 2 || spacePos < signed(numChar) - 10) spacePos = numChar - 4; out = out.substr(0, spacePos-1) + L"\u2026"; } return out; } wstring ensureEndingColon(const wstring& text) { if (text.empty() || text[text.length() - 1] == ':') return text; return text + L":"; } const wstring &makeDash(const wstring &t) { return makeDash(t.c_str()); } const wstring &makeDash(const wchar_t *t) { wstring &out = StringCache::getInstance().wget(); out = t; for (size_t i=0;i=0 && (isspace(BYTE(ptr[k])) || BYTE(ptr[i])==BYTE(160))) k--; if (i == 0 && k == len-1) return s; else if (k>=i && i=0 && myIsSpace(ptr[k])) k--; if (i == 0 && k == len-1) return s; else if (k>=i && i') | (bf[k]=='<') | (bf[k]=='"') | (bf[k]==0) | (bf[k]=='\n') | (bf[k]=='\r'); if (!needEncode) return in; out.clear(); for (int k=0;k') out+=">"; else if (bf[k]=='"') out+="""; else if (bf[k]=='\n') out+=" "; else if (bf[k]=='\r') out+=" "; else if (bf[k] == 0) out+=' '; else out+=bf[k]; } return out; } const wstring &encodeXML(const wstring &in) { static wstring out;//WCS const wchar_t *bf = in.c_str(); int len = in.length(); bool needEncode = false; for (int k=0;k') | (bf[k]=='<') | (bf[k]=='"') | (bf[k]==0) | (bf[k]=='\n') | (bf[k]=='\r'); if (!needEncode) return in; out.clear(); for (int k=0;k') out+=L">"; else if (bf[k]=='"') out+=L"""; else if (bf[k]=='\n') out+=L" "; else if (bf[k]=='\r') out+=L" "; else if (bf[k] == 0) out+=' '; else out+=bf[k]; } return out; } const wstring &encodeHTML(const wstring &in) { static wstring out;//WCS const wchar_t *bf = in.c_str(); int len = in.length(); bool needEncode = false; for (int k=0;k') | (bf[k]=='<') | (bf[k]=='"') | (bf[k]==0) | (bf[k]=='\n') | (bf[k]=='\r') | (bf[k]==0x2013); if (!needEncode) return in; out.clear(); for (int k=0;k') out+=L">"; else if (bf[k]=='"') out+=L"""; else if (bf[k]=='\n') out+=L" "; else if (bf[k]=='\r') out+=L" "; else if (bf[k] == 0) out+=' '; else if (bf[k] == 0x2013) { out+=L"–"; } else if (bf[k] == ' ') { out+=L" "; } else out+=bf[k]; } return out; } const string &decodeXML(const string &in) { const char *bf = in.c_str(); int len = in.length(); bool needDecode = false; for (int k=0;k', k+=3; else if ( memcmp(&bf[k], """, 6)==0 ) str << '\"', k+=5; else if ( memcmp(&bf[k], " ", 6)==0 ) str << ' ', k+=5; else if ( memcmp(&bf[k], " ", 5)==0 ) str << '\n', k+=4; else if ( memcmp(&bf[k], " ", 5)==0 ) str << '\r', k+=4; else str << bf[k]; } else str << bf[k]; } out = str.str(); } return out; } void inplaceDecodeXML(char *in) { char *bf = in; int outp = 0; for (int k=0;bf[k] ;k++) { if (bf[k] != '&') bf[outp++] = bf[k]; else { if ( memcmp(&bf[k], "&", 5)==0 ) bf[outp++] = '&', k+=4; else if ( memcmp(&bf[k], "<", 4)==0 ) bf[outp++] = '<', k+=3; else if ( memcmp(&bf[k], ">", 4)==0 ) bf[outp++] = '>', k+=3; else if ( memcmp(&bf[k], """, 6)==0 ) bf[outp++] = '"', k+=5; else if ( memcmp(&bf[k], " ", 5)==0 ) bf[outp++] = '\n', k+=4; else if ( memcmp(&bf[k], " ", 5)==0 ) bf[outp++] = '\r', k+=4; else bf[outp++] = bf[k]; } } bf[outp] = 0; } const char *decodeXML(const char *in) { const char *bf = in; bool needDecode = false; for (int k=0; bf[k] ;k++) needDecode |= (bf[k]=='&'); if (!needDecode) return in; static string out; out.clear(); for (int k=0;bf[k] ;k++) { if (bf[k]=='&') { if ( memcmp(&bf[k], "&", 5)==0 ) out+="&", k+=4; else if ( memcmp(&bf[k], "<", 4)==0 ) out+="<", k+=3; else if ( memcmp(&bf[k], ">", 4)==0 ) out+=">", k+=3; else if ( memcmp(&bf[k], """, 6)==0 ) out+="\"", k+=5; else if ( memcmp(&bf[k], " ", 5)==0 ) out+="\n", k+=4; else if ( memcmp(&bf[k], " ", 5)==0 ) out+="\r", k+=4; else out+=bf[k]; } else out+=bf[k]; } return out.c_str(); } void static setChar(wchar_t *map, wchar_t pos, wchar_t value) { map[pos] = value; } int toLowerStripped(wchar_t c) { if (c>='A' && c<='Z') return c + ('a' - 'A'); else if (c<128) return c; static wchar_t *map = 0; if (map == nullptr) { map = new wchar_t[65536]; for (int i = 0; i < 65536; i++) map[i] = i; setChar(map, L'Å', L'a'); setChar(map, L'Ä', L'a'); setChar(map, L'Ö', L'o'); setChar(map, L'É', L'e'); setChar(map, L'é', L'e'); setChar(map, L'è', L'e'); setChar(map, L'È', L'e'); setChar(map, L'ë', L'e'); setChar(map, L'Ë', L'e'); setChar(map, L'ê', L'e'); setChar(map, L'Ê', L'e'); setChar(map, L'û', L'u'); setChar(map, L'Û', L'u'); setChar(map, L'ü', L'u'); setChar(map, L'Ü', L'u'); setChar(map, L'ú', L'u'); setChar(map, L'Ú', L'u'); setChar(map, L'ù', L'u'); setChar(map, L'Ù', L'u'); setChar(map, L'ñ', L'n'); setChar(map, L'Ñ', L'n'); setChar(map, L'ä', L'a'); setChar(map, L'å', L'a'); setChar(map, L'á', L'a'); setChar(map, L'Á', L'a'); setChar(map, L'à', L'a'); setChar(map, L'À', L'a'); setChar(map, L'â', L'a'); setChar(map, L'Â', L'a'); setChar(map, L'ã', L'a'); setChar(map, L'Ã', L'a'); setChar(map, L'ï', L'i'); setChar(map, L'Ï', L'i'); setChar(map, L'î', L'i'); setChar(map, L'Î', L'i'); setChar(map, L'í', L'i'); setChar(map, L'Í', L'i'); setChar(map, L'ì', L'i'); setChar(map, L'Ì', L'i'); setChar(map, L'ó', L'o'); setChar(map, L'Ó', L'o'); setChar(map, L'ò', L'o'); setChar(map, L'Ò', L'o'); setChar(map, L'õ', L'o'); setChar(map, L'Õ', L'o'); setChar(map, L'ô', L'o'); setChar(map, L'Ô', L'o'); setChar(map, L'ö', L'o'); setChar(map, L'ý', L'y'); setChar(map, L'Ý', L'Y'); setChar(map, L'ÿ', L'y'); setChar(map, L'Æ', L'a'); setChar(map, L'æ', L'a'); setChar(map, L'Ø', L'o'); setChar(map, L'ø', L'o'); setChar(map, L'Ç', L'c'); setChar(map, L'ç', L'c'); wstring srcEx = L"Ă㥹ĆćĈĉĊċČčĎďĐđĒēĔĕĖėĘęĚěĜĝĞğĠġĢģĤĥĦħĨĩĪīĬĭĮįİıIJijĴĵĶķĸĹĺĻĽľĿŀŁł" L"ŃńŅņŇňʼnŊŋŌōŎŏŐőŒœŔŕŖŗŘřŚśŜŝŞşŠšŢţŤťŦŧŨũŪūŬŭŮůŰűŲųŴŵŶŷŸŹźŻżŽž"; wstring dstEx = L"aaaaccccccccddddeeeeeeeeeegggggggghhhhiiiiiiiiiijjjjkkklllllllll" L"nnnnnnnnnooooooaarrrrrrssssssssttttttuuuuuuuuuuuuwwyyyzzzzzz"; assert(srcEx.size() == dstEx.size()); for (int j = 0; j < srcEx.size(); j++) setChar(map, srcEx[j], dstEx[j]); } int a = map[c]; return a; } const wchar_t *canonizeName(const wchar_t *name) { static wchar_t out[70]; static wchar_t tbf[70]; for (int i = 0; i<63 && name[i]; i++) { if (name[i] == ',') { int tout = 0; for (int j = i+1; j < 63 && name[j]; j++) { tbf[tout++] = name[j]; } tbf[tout++] = ' '; for (int j = 0; j < i; j++) { tbf[tout++] = name[j]; } tbf[tout] = 0; name = tbf; break; } } int outp = 0; int k = 0; for (k=0; k<63 && name[k]; k++) { if (name[k] != ' ') break; } bool first = true; while (k<63 && name[k]) { if (!first) out[outp++] = ' '; while(name[k]!= ' ' && k<63 && name[k]) { if (name[k] == '-') out[outp++] = ' '; else out[outp++] = toLowerStripped(name[k]); k++; } first = false; while(name[k] == ' ' && k<64) k++; } out[outp] = 0; return out; } const int notFound = 1000000; int charDist(const wchar_t *b, int len, int origin, wchar_t c) { int i; int bound = max(1, min(len/2, 4)); for (int k = 0;k0 && b[i] == c) return -k; i = origin + k; if (imin(3, max(1, al/3))) return 1; double mfactor = double(missing*0.8); double center = double(avg)/double(ndiff); double dist = 0; for (int k=0; k(fabs(d1[k] - center), abs(d1[k])); dist += ld*ld; } return (sqrt(dist)+mfactor*mfactor)/double(al); } double stringDistanceAssymetric(const wstring &target, const wstring &sample) { double d = stringDistance(target.c_str(), target.length(), sample.c_str(), sample.length()); return min(1.0, d); } double stringDistance(const wchar_t *a, const wchar_t *b) { int al = wcslen(a); int bl = wcslen(b); double d1 = stringDistance(a, al, b, bl); if (d1 >= 1) return 1.0; double d2 = stringDistance(b, bl, a, al); if (d2 >= 1) return 1.0; return (max(d1, d2) + d1 + d2)/3.0; } int getNumberSuffix(const string &str) { int pos = str.length(); while (pos>1 && (str[pos-1] & (~127)) == 0 && (isspace(str[pos-1]) || isdigit(str[pos-1]))) { pos--; } if (pos == str.length()) return 0; return atoi(str.c_str() + pos); } int getNumberSuffix(const wstring &str) { int pos = str.length(); while (pos>1 && (str[pos-1] & (~127)) == 0 && (isspace(str[pos-1]) || isdigit(str[pos-1]))) { pos--; } if (pos == str.length()) return 0; return _wtoi(str.c_str() + pos); } int extractAnyNumber(const wstring &str, wstring &prefix, wstring &suffix) { const wchar_t *ptr = (const wchar_t*)str.c_str(); for (size_t k = 0; k &dec) { if (name.empty()) return; dec.push_back(wstring()); for (size_t i = 0; i < name.size(); i++) { int bchar = toLowerStripped(name[i]); if (myIsSpace(bchar) || bchar == '-' || bchar == 160) { if (!dec.back().empty()) dec.push_back(wstring()); continue; } if (!dec.back().empty()) { int last = *dec.back().rbegin(); bool lastNum = last >= '0' && last <= '9'; bool isNum = bchar >= '0' && bchar <= '9'; if (lastNum^isNum) dec.push_back(wstring()); // Change num/ non-num } dec.back().push_back(bchar); } if (dec.back().empty()) dec.pop_back(); sort(dec.begin(), dec.end()); } /** Matches H21 L with H21 Lång and H21L but not Violet with Violet Court, which is obviously wrong. */ bool compareClassName(const wstring &a, const wstring &b) { if (a == b) return true; vector acanon; vector bcanon; decomposeClassName(a, acanon); decomposeClassName(b, bcanon); if (acanon.size() != bcanon.size()) return false; for (size_t k = 0; k < acanon.size(); k++) { if (acanon[k] == bcanon[k]) continue; int sample = acanon[k][0]; if (sample >= '0' && sample <= '9') return false; // Numbers must match if (acanon[k][0] == bcanon[k][0] && (acanon[k].length() == 1 || bcanon[k].length() == 1)) continue; // Abbrevation W <-> Women etc return false; // No match } return true; // All parts matched } wstring getErrorMessage(int code) { LPVOID msg; if (code == ERROR_INTERNET_TIMEOUT) { return L"Timeout"; } int s = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &msg, 0, NULL); if (s==0 || !msg) { if (code != 0) { wchar_t ch[128]; swprintf_s(ch, L"Error code: %d", code); return ch; } return L""; } wstring str = LPCTSTR(msg); if (str.empty() && code>0) { wchar_t ch[128]; swprintf_s(ch, L"Error code: %d", code); str = ch; } LocalFree(msg); return str; } #define HLSMAX 252 /* H,L, and S vary over 0-HLSMAX */ #define RGBMAX 255 /* R,G, and B vary over 0-RGBMAX */ /* HLSMAX BEST IF DIVISIBLE BY 6 */ /* RGBMAX, HLSMAX must each fit in a byte. */ /* Hue is undefined if Saturation is 0 (grey-scale) */ #define UNDEFINED (HLSMAX*2/3) HLS &HLS::RGBtoHLS(DWORD lRGBColor) { WORD R,G,B; /* input RGB values */ BYTE cMax,cMin; /* max and min RGB values */ WORD Rdelta,Gdelta,Bdelta; /* intermediate value: % of spread from max */ /* get R, G, and B out of DWORD */ R = GetRValue(lRGBColor); G = GetGValue(lRGBColor); B = GetBValue(lRGBColor); WORD &L = lightness; WORD &H = hue; WORD &S = saturation; /* calculate lightness */ cMax = (BYTE)max( max(R,G), B); cMin = (BYTE)min( min(R,G), B); L = ( ((cMax+cMin)*HLSMAX) + RGBMAX )/(2*RGBMAX); if (cMax == cMin) { /* r=g=b --> achromatic case */ S = 0; /* saturation */ H = UNDEFINED; /* hue */ } else { /* chromatic case */ /* saturation */ if (L <= (HLSMAX/2)) S = ( ((cMax-cMin)*HLSMAX) + ((cMax+cMin)/2) ) / (cMax+cMin); else S = ( ((cMax-cMin)*HLSMAX) + ((2*RGBMAX-cMax-cMin)/2) ) / (2*RGBMAX-cMax-cMin); /* hue */ Rdelta = ( ((cMax-R)*(HLSMAX/6)) + ((cMax-cMin)/2) ) / (cMax-cMin); Gdelta = ( ((cMax-G)*(HLSMAX/6)) + ((cMax-cMin)/2) ) / (cMax-cMin); Bdelta = ( ((cMax-B)*(HLSMAX/6)) + ((cMax-cMin)/2) ) / (cMax-cMin); if (R == cMax) H = Bdelta - Gdelta; else if (G == cMax) H = (HLSMAX/3) + Rdelta - Bdelta; else /* B == cMax */ H = ((2*HLSMAX)/3) + Gdelta - Rdelta; if (H < 0) H += HLSMAX; if (H > HLSMAX) H -= HLSMAX; } return *this; } /* utility routine for HLStoRGB */ WORD HLS::HueToRGB(WORD n1, WORD n2, WORD hue) const { /* range check: note values passed add/subtract thirds of range */ if (hue < 0) hue += HLSMAX; if (hue > HLSMAX) hue -= HLSMAX; /* return r,g, or b value from this tridrant */ if (hue < (HLSMAX/6)) return ( n1 + (((n2-n1)*hue+(HLSMAX/12))/(HLSMAX/6)) ); if (hue < (HLSMAX/2)) return ( n2 ); if (hue < ((HLSMAX*2)/3)) return ( n1 + (((n2-n1)*(((HLSMAX*2)/3)-hue)+(HLSMAX/12))/(HLSMAX/6)) ); else return ( n1 ); } DWORD HLS::HLStoRGB() const { const WORD &lum = lightness; const WORD &sat = saturation; WORD R,G,B; /* RGB component values */ WORD Magic1,Magic2; /* calculated magic numbers (really!) */ if (sat == 0) { /* achromatic case */ R=G=B=(lum*RGBMAX)/HLSMAX; if (hue != UNDEFINED) { /* ERROR */ } } else { /* chromatic case */ /* set up magic numbers */ if (lum <= (HLSMAX/2)) Magic2 = (lum*(HLSMAX + sat) + (HLSMAX/2))/HLSMAX; else Magic2 = lum + sat - ((lum*sat) + (HLSMAX/2))/HLSMAX; Magic1 = 2*lum-Magic2; /* get RGB, change units from HLSMAX to RGBMAX */ R = (HueToRGB(Magic1,Magic2,hue+(HLSMAX/3))*RGBMAX + (HLSMAX/2))/HLSMAX; G = (HueToRGB(Magic1,Magic2,hue)*RGBMAX + (HLSMAX/2)) / HLSMAX; B = (HueToRGB(Magic1,Magic2,hue-(HLSMAX/3))*RGBMAX + (HLSMAX/2))/HLSMAX; } return(RGB(R,G,B)); } void HLS::lighten(double f) { lightness = min(HLSMAX, WORD(f*lightness)); } void HLS::saturate(double s) { saturation = min(HLSMAX, WORD(s*saturation)); } void HLS::colorDegree(double d) { } bool isAscii(const string &s) { for (size_t k = 0; k 0; } bool isAscii(const wstring &s) { for (size_t k = 0; k 0; } int convertDynamicBase(const wstring &s, long long &out) { out = 0; if (s.empty()) return 0; bool alpha = false; bool general = false; int len = s.length(); for (int k = 0; k < len; k++) { unsigned c = s[k]; if (c >= '0' && c <= '9') continue; if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) { alpha = true; continue; } general = true; if (c<32) return 0; // Not a supported character } int base = general ? 256-32 : (alpha ? 36 : 10); long long factor = 1; for (int k = len-1; k >= 0; k--) { unsigned c = s[k]&0xFF; if (general) c -= 32; else { if (c >= '0' && c <= '9') c -= '0'; else if (c >= 'A' && c <= 'Z') c -= 'A'-10; else if (c >= 'a' && c <= 'z') c -= 'a'-10; } out += factor * c; factor *= base; } return base; } void convertDynamicBase(long long val, int base, wchar_t out[16]) { int len = 0; while (val != 0) { unsigned int c = val % base; val = val / base; char cc; if (base == 10) cc = '0' + c; else if (base == 36) { if (c < 10) cc = '0' + c; else cc = 'A' + c - 10; } else { cc = c+32; } out[len++] = cc; } out[len] = 0; reverse(out, out+len); } bool expandDirectory(const wchar_t *file, const wchar_t *filetype, vector &res) { WIN32_FIND_DATA fd; wchar_t dir[MAX_PATH]; wchar_t fullPath[MAX_PATH]; if (file[0] == '.') { GetCurrentDirectory(MAX_PATH, dir); wcscat_s(dir, file+1); } else wcscpy_s(dir, MAX_PATH, file); if (dir[wcslen(dir)-1]!='\\') wcscat_s(dir, MAX_PATH, L"\\"); wcscpy_s(fullPath, MAX_PATH, dir); wcscat_s(dir, MAX_PATH, filetype); HANDLE h=FindFirstFile(dir, &fd); if (h == INVALID_HANDLE_VALUE) return false; bool more = true; while (more) { if (fd.cFileName[0] != '.') { //Avoid .. and . wchar_t fullPathFile[MAX_PATH]; wcscpy_s(fullPathFile, MAX_PATH, fullPath); wcscat_s(fullPathFile, MAX_PATH, fd.cFileName); res.push_back(fullPathFile); } more=FindNextFile(h, &fd)!=0; } FindClose(h); return true; } wstring encodeSex(PersonSex sex) { if (sex == sFemale) return L"F"; else if (sex == sMale) return L"M"; else if (sex == sBoth) return L"B"; else return L""; } PersonSex interpretSex(const wstring &sex) { if (sex == L"F" || sex == L"K" || sex == L"W") return sFemale; else if (sex == L"M" || sex == L"H") return sMale; else if (sex == L"B") return sBoth; else return sUnknown; } bool matchNumber(int a, const wchar_t *b) { if (a == 0 && b[0]) return false; wchar_t bf[32]; _itow_s(a, bf, 10); // Check matching substring for (int k = 0; k < 12; k++) { if (b[k] == 0) return true; if (bf[k] != b[k]) return false; } return false; } wstring makeValidFileName(const wstring &input, bool strict) { wstring out; out.reserve(input.size()); if (strict) { for (size_t k = 0; k < input.length(); k++) { wchar_t b = input[k]; if ( (b>='0' && b<='9') || (b>='a' && b<='z') || (b>='A' && b<='Z') || b == '_' || b=='.' ) out.push_back(b); else if (b == ' ' || b == ',') out.push_back('_'); else { b = toLowerStripped(b); if (b >= 'a' && b <= 'z') b = b; else if ( b == L'ö') b = 'o'; else if (b == L'ä' || b == L'å' || b== L'à' || b == L'á' || b == L'â' || b == L'ã' || b == L'æ') b = 'a'; else if (b == L'ç') b = 'c'; else if (b == L'è' || b == L'é' || b == L'ê' || b == L'ë') b = 'e'; else if (b == L'ð') b = 't'; else if (b == L'ï' || b == L'ì' || b == L'ï' || b == L'î' || b == L'í') b = 'i'; else if (b == L'ò' || b == L'ó' || b == L'ô' || b == L'õ' || b == L'ø') b = 'o'; else if (b == L'ù' || b == L'ú' || b == L'û' || b == L'ü') b = 'u'; else if (b == L'ý') b = 'y'; else b = '-'; out.push_back(b); } } } else { for (size_t k = 0; k < input.length(); k++) { wchar_t b = input[k]; if (b < 32 || b == '*' || b == '?' || b==':' || b=='/' || b == '\\') b = '_'; out.push_back(b); } } return out; } string makeValidFileName(const string& input, bool strict) { string out; out.reserve(input.size()); if (strict) { for (size_t k = 0; k < input.length(); k++) { char b = input[k]; if ((b >= '0' && b <= '9') || (b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || b == '_' || b == '.') out.push_back(b); else if (b == ' ' || b == ',') out.push_back('_'); else { b = toLowerStripped(b); if (b >= 'a' && b <= 'z') b = b; else if (b == 'ö') b = 'o'; else if (b == 'ä' || b == 'å' || b == 'à' || b == 'á' || b == 'â' || b == 'ã' || b == 'æ') b = 'a'; else if (b == 'ç') b = 'c'; else if (b == 'è' || b == 'é' || b == 'ê' || b == 'ë') b = 'e'; else if (b == 'ð') b = 't'; else if (b == 'ï' || b == 'ì' || b == 'ï' || b == 'î' || b == 'í') b = 'i'; else if (b == 'ò' || b == 'ó' || b == 'ô' || b == 'õ' || b == 'ø') b = 'o'; else if (b == 'ù' || b == 'ú' || b == 'û' || b == 'ü') b = 'u'; else if (b == 'ý') b = 'y'; else b = '-'; out.push_back(b); } } } else { for (size_t k = 0; k < input.length(); k++) { char b = input[k]; if (b < 32 || b == '*' || b == '?' || b == ':' || b == '/' || b == '\\') b = '_'; out.push_back(b); } } return out; } void capitalize(wstring &str) { if (str.length() > 0) { auto bf = str.c_str(); CharUpperBuff(const_cast(bf), 1); } } bool checkValidDate(const wstring &date) { SYSTEMTIME st; if (convertDateYMD(date, st, false) <= 0) return false; st.wHour = 12; SYSTEMTIME utc; if (!TzSpecificLocalTimeToSystemTime(0, &st, &utc)) { return false; } return true; } /** Return bias in seconds. UTC = local time + bias. */ int getTimeZoneInfo(const wstring &date) { static wchar_t lastDate[16] = {0}; static int lastValue = -1; // Local caching if (lastValue != -1 && lastDate == date) { return lastValue; } wcscpy_s(lastDate, 16, date.c_str()); // TIME_ZONE_INFORMATION tzi; SYSTEMTIME st; convertDateYMD(date, st, false); st.wHour = 12; SYSTEMTIME utc; if (!TzSpecificLocalTimeToSystemTime(0, &st, &utc)) { lastValue = 0; return 0; } int datecode = ((st.wYear * 12 + st.wMonth) * 31) + st.wDay; int datecodeUTC = ((utc.wYear * 12 + utc.wMonth) * 31) + utc.wDay; int daydiff = 0; if (datecodeUTC > datecode) daydiff = 1; else if (datecodeUTC < datecode) daydiff = -1; int t = st.wHour * timeConstSecPerHour; int tUTC = daydiff * 24 * timeConstSecPerHour + utc.wHour * timeConstSecPerHour + utc.wMinute * timeConstSecPerMin + utc.wSecond; lastValue = tUTC - t; return lastValue; } wstring getTimeZoneString(const wstring &date) { int a = getTimeZoneInfo(date); if (a == 0) return L"+00:00"; else if (a>0) { wchar_t bf[12]; swprintf_s(bf, L"-%02d:%02d", a/timeConstSecPerHour, (a/timeConstMinPerHour)%60); return bf; } else { wchar_t bf[12]; swprintf_s(bf, L"+%02d:%02d", a/-timeConstSecPerHour, (a/-timeConstMinPerHour)%60); return bf; } } bool compareBib(const wstring &b1, const wstring &b2) { int l1 = b1.length(); int l2 = b2.length(); if (l1 != l2) return l1 < l2; wchar_t maxc = 0, minc = numeric_limits::max(); for (int k = 0; k < l1; k++) { wchar_t b = b1[k]; maxc = max(maxc, b); minc = min(minc, b); } for (int k = 0; k < l2; k++) { wchar_t b = b2[k]; maxc = max(maxc, b); minc = min(minc, b); } unsigned coeff = maxc-minc + 1; unsigned z1 = 0; for (int k = 0; k < l1; k++) { wchar_t b = b1[k]-minc; z1 = coeff * z1 + b; } unsigned z2 = 0; for (int k = 0; k < l2; k++) { wchar_t b = b2[k]-minc; z2 = coeff * z2 + b; } return z1 < z2; } /// Split a name into first name and last name int getNameCommaSplitPoint(const wstring &name) { int commaSplit = -1; for (unsigned k = 1; k + 1 < name.size(); k++) { if (name[k] == ',') { commaSplit = k; break; } } if (commaSplit >= 0) { commaSplit += 2; } return commaSplit; } /// Split a name into first name and last name int getNameSplitPoint(const wstring &name) { int split[10]; int nSplit = 0; for (unsigned k = 1; k + 1=9 ) break; } } if (nSplit == 1) return split[0] + 1; else if (nSplit == 0) return -1; else { const oWordList &givenDB = lang.get().getGivenNames(); int sp_ix = 0; for (int k = 1; k= 'a' && c <= 'z' && !noCapitalize(str, i)) str[i] = c + ('A' - 'a'); init = iswspace(c) != 0 || c == '/' || c == '-'; } } void MeOSFileLock::unlockFile() { if (lockedFile != INVALID_HANDLE_VALUE) CloseHandle(lockedFile); lockedFile = INVALID_HANDLE_VALUE; } void MeOSFileLock::lockFile(const wstring &file) { unlockFile(); lockedFile = CreateFile(file.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); //lockedFile = _open(file.c_str(), _O_RDWR); if (lockedFile == INVALID_HANDLE_VALUE) { int err = GetLastError(); if (err == ERROR_SHARING_VIOLATION) throw meosException("open_error_locked"); else { TCHAR buff[256]; FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0, err, 0, buff, sizeof(buff), 0); throw meosException(L"open_error#" + file + L"#" + buff); } } } void processGeneralTime(const wstring &generalTime, wstring &meosTime, wstring &meosDate) { meosTime = L""; meosDate = L""; vector parts; split(generalTime, L":-,. /\t", parts); // Indices into parts int year = -2; int month = -2; int day = -2; int hour = -2; int minute = -2; int second = -2; int subsecond = -2; int found = 0, base = -1, iter = 0; bool pm = wcsstr(generalTime.c_str(), L"PM") != 0 || wcsstr(generalTime.c_str(), L"pm") != 0; while (iter < 2 && second==-2) { if (base == found) iter++; base = found; for (size_t k = 0; k < parts.size(); k++) { if (parts[k].empty()) continue; int number = _wtoi(parts[k].c_str()); if (number == 0 && parts[k][0] != '0') number = -1; // Not a number if (iter == 0) { // Date if (number > 1900 && number < 3000 && year < 0) { found++; year = k; } else if (number >= 1 && number <= 12 && month < 0 && (year == k+1 || year == k-1) ) { month = k; found++; } else if (number >= 1 && number <=31 && day < 0 && (month == k+1 || month == k-1)) { day = k; found++; iter++; break; } else if (number > 1011900 && number < 30000101 && year < 0 && month < 0 && day < 0) { day = k; //Date with format 20160906 or 06092016 month = k; year = k; found++; break; } } else if (iter == 1) { // Time if (number >= 0 && number <= 24 && year != k && day != k && month != k && hour < 0) { hour = k; found++; } else if (number >= 0 && number <= 59 && minute < 0 && hour == k-1) { minute = k; found++; } else if (number >= 0 && number <= 59 && second < 0 && minute == k-1) { second = k; found++; } else if (number >= 0 && number < 1000 && subsecond < 0 && second == k-1 && k != year) { subsecond = k; found++; iter++; break; } } } } if (second >= 0 && minute >= 0 && hour>= 0) { if (!pm) meosTime = parts[hour] + L":" + parts[minute] + L":" + parts[second]; else { int rawHour = _wtoi(parts[hour].c_str()); if (rawHour < 12) rawHour+=12; meosTime = itow(rawHour) + L":" + parts[minute] + L":" + parts[second]; } } if (year >= 0 && month >= 0 && day >= 0) { int y = -1, m = -1, d = -1; if (year != month) { y = _wtoi(parts[year].c_str()); m = _wtoi(parts[month].c_str()); d = _wtoi(parts[day].c_str()); //meosDate = parts[year] + "-" + parts[month] + "-" + parts[day]; } else { int td = _wtoi(parts[year].c_str()); int y1 = td / 10000; int m1 = (td / 100) % 100; int d1 = td % 100; bool ok = y1 > 2000 && y1 < 3000 && m1>=1 && m1<=12 && d1 >= 1 && d1 <= 31; if (!ok) { y1 = td % 10000; m1 = (td / 10000) % 100; d1 = (td / 1000000); ok = y1 > 2000 && y1 < 3000 && m1>=1 && m1<=12 && d1 >= 1 && d1 <= 31; } if (ok) { y = y1; m = m1; d = d1; } meosDate = itow(y1) + L"-" + itow(m1) + L"-" + itow(d1); } if (y > 0) { wchar_t bf[24]; swprintf_s(bf, 24, L"%d-%02d-%02d", y, m, d); meosDate = bf; } } } void string2Wide(const string &in, wstring &out) { int cp = defaultCodePage; if (in.empty()) { out = L""; return; } out.reserve(in.size() + 1); out.resize(in.size(), 0); MultiByteToWideChar(cp, MB_PRECOMPOSED, in.c_str(), in.size(), &out[0], out.size() * sizeof(wchar_t)); } void wide2String(const wstring &in, string &out) { out.clear(); out.insert(out.begin(), in.begin(), in.end());// XXX Simple extend } void checkWriteAccess(const wstring &file) { if (_waccess(file.c_str(), 4) == 0) return; auto h = CreateFile(file.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_READ, 0, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0); if (h == INVALID_HANDLE_VALUE) { wchar_t absPath[260]; _wfullpath(absPath, file.c_str(), 260); throw meosException(wstring(L"Du saknar behörighet att skriva till 'X'.#") + absPath); } CloseHandle(h); } int compareStringIgnoreCase(const wstring &a, const wstring &b) { return CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, a.c_str(), a.length(), b.c_str(), b.length()) - CSTR_EQUAL; } const char* meosException::narrow(const wstring& msg) { static string nmsg(msg.begin(), msg.end()); return nmsg.c_str(); } int parseRelativeTime(const char *data) { if (data) { int ret = atoi(data); if (timeConstSecond > 1) { int j = 0; while (data[j]) { if (data[j] == '.') { int t = data[j + 1] - '0'; if (t > 0 && t < 10) { if (ret < 0 || data[0] == '-') return ret * timeConstSecond - t; else return ret * timeConstSecond + t; } break; } j++; } } if (ret == -1) return ret; // Special value return ret * timeConstSecond; } return 0; } int parseRelativeTime(const wchar_t *data) { if (data) { int ret = _wtoi(data); if (timeConstSecond > 1) { int j = 0; while (data[j]) { if (data[j] == '.') { int t = data[j + 1] - '0'; if (t > 0 && t < 10) { if (ret < 0 || data[0] == '-') return ret * timeConstSecond - t; else return ret * timeConstSecond + t; } break; } j++; } } if (ret == -1) return ret; // Special value return ret * timeConstSecond; } return 0; } const wstring &codeRelativeTimeW(int rt) { wchar_t bf[32]; int subSec = timeConstSecond == 1 ? 0 : rt % timeConstSecond; if (timeConstSecond == 1 || rt == -1) return itow(rt); else if (subSec == 0 && rt != -10) return itow(rt / timeConstSecond); else if (rt > 0) { swprintf_s(bf, L"%d.%d", rt / timeConstSecond, rt % timeConstSecond); } else { rt = -rt; swprintf_s(bf, L"-%d.%d", rt / timeConstSecond, rt % timeConstSecond); } wstring &res = StringCache::getInstance().wget(); res = bf; return res; } const string &codeRelativeTime(int rt) { char bf[32]; int subSec = timeConstSecond == 1 ? 0 : rt % timeConstSecond; if (timeConstSecond == 1 || rt == -1) return itos(rt); else if (subSec == 0 && rt != -10) return itos(rt / timeConstSecond); else if (rt > 0) { sprintf_s(bf, "%d.%d", rt / timeConstSecond, rt % timeConstSecond); } else { rt = -rt; sprintf_s(bf, "-%d.%d", rt / timeConstSecond, rt % timeConstSecond); } string &res = StringCache::getInstance().get(); res = bf; return res; }