Files
pip/libs/main/core/piinit.cpp
peri4 caa7880cc4 get rid of piForeach
apply some code analyzer recommendations
ICU flag now check if libicu exists
prepare for more accurate growth of containers (limited PoT, then constantly increase size)
2024-11-20 20:01:47 +03:00

403 lines
10 KiB
C++

/*
PIP - Platform Independent Primitives
Initialization
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "piinit.h"
#include "piincludes_p.h"
#ifndef MICRO_PIP
# include "pidir.h"
# include "piobject.h"
# include "piprocess.h"
# include "piresourcesstorage.h"
# include "pisignals.h"
# include "pisysteminfo.h"
# include "pitime.h"
# ifdef ESP_PLATFORM
# include "esp_system.h"
# endif
# include <codecvt>
# ifdef WINDOWS
# include <winsock2.h>
extern FILETIME __pi_ftjan1970;
extern PINtQueryTimerResolution getTimerResolutionAddr;
extern PINtSetTimerResolution setTimerResolutionAddr;
void __PISetTimerResolution() {
if (setTimerResolutionAddr == NULL || getTimerResolutionAddr == NULL) return;
ULONG _max(0), _min(0), _cur(0);
// printf("getTimerResolution ...\n");
LONG q = getTimerResolutionAddr(&_max, &_min, &_cur);
// printf("getTimerResolution %d %lu %lu %lu\n", q, _min, _max, _cur);
if (q == 0) setTimerResolutionAddr(_min, TRUE, &_cur);
// printf("setTimerResolution %lu\n", cur);
}
# else
# include <pthread.h>
# include <pwd.h>
# include <sys/utsname.h>
# ifdef BLACKBERRY
# include <signal.h>
# else
# include <csignal>
# endif
# endif
# ifdef MAC_OS
# include <mach/clock.h>
# include <mach/mach.h>
# include <mach/mach_traps.h>
extern clock_serv_t __pi_mac_clock;
# endif
# ifdef PIP_ICU
# define U_NOEXCEPT
# include <unicode/uclean.h>
# include <unicode/ucnv.h>
# endif
# ifdef HAS_LOCALE
static locale_t currentLocale_t = 0;
# endif
PRIVATE_DEFINITION_START(PIInit)
# ifdef WINDOWS
HMODULE ntlib;
ULONG prev_res;
# endif
bool delete_locs;
PRIVATE_DEFINITION_END(PIInit)
void __sighandler__(PISignals::Signal s) {
// piCout << Hex << int(s);
if (s == PISignals::StopTTYInput || s == PISignals::StopTTYOutput) piMSleep(10);
if (s == PISignals::UserDefined1)
dumpApplicationToFile(PIDir::home().path() + PIDir::separator + PIStringAscii("_PIP_DUMP_") +
PIString::fromNumber(PIProcess::currentPID()));
}
PIInit::PIInit() {
PISystemInfo * sinfo = PISystemInfo::instance();
sinfo->execDateTime = PIDateTime::current();
# ifndef ANDROID
PISignals::setSlot(__sighandler__);
PISignals::grabSignals(PISignals::UserDefined1);
# ifndef WINDOWS
PISignals::grabSignals(PISignals::StopTTYInput | PISignals::StopTTYOutput);
sigset_t ss;
sigemptyset(&ss);
sigaddset(&ss, SIGALRM);
sigprocmask(SIG_BLOCK, &ss, 0);
pthread_sigmask(SIG_BLOCK, &ss, 0);
signal(SIGPIPE, SIG_IGN);
PIStringList ifpathes;
ifpathes << PIStringAscii("/bin/ifconfig") << PIStringAscii("/sbin/ifconfig") << PIStringAscii("/usr/bin/ifconfig")
<< PIStringAscii("/usr/sbin/ifconfig");
for (const auto & i: ifpathes) {
if (fileExists(i)) {
sinfo->ifconfigPath = i;
break;
}
}
# else // WINDOWS
// OS version
DWORD dwVersion = GetVersion();
DWORD dwMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
DWORD dwMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion)));
sinfo->OS_version = PIString::fromNumber(dwMajorVersion) + "." + PIString::fromNumber(dwMinorVersion);
// WinSock inint
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
// Timers init
SYSTEMTIME jan1970 = {1970, 1, 4, 1, 0, 0, 0, 0};
SystemTimeToFileTime(&jan1970, &__pi_ftjan1970);
LARGE_INTEGER pf;
pf.QuadPart = -1;
if (QueryPerformanceFrequency(&pf) != 0) __pi_perf_freq = pf.QuadPart;
if (__pi_perf_freq == 0) __pi_perf_freq = -1;
// Sleep precision init
PRIVATE->ntlib = LoadLibraryA("ntdll.dll");
if (PRIVATE->ntlib) {
getTimerResolutionAddr = (PINtQueryTimerResolution)GetProcAddress(PRIVATE->ntlib, "NtQueryTimerResolution");
setTimerResolutionAddr = (PINtSetTimerResolution)GetProcAddress(PRIVATE->ntlib, "NtSetTimerResolution");
__PISetTimerResolution();
}
# endif // WINDOWS
# ifdef HAS_LOCALE
// std::cout << "has locale" << std::endl;
if (currentLocale_t != 0) {
freelocale(currentLocale_t);
currentLocale_t = 0;
}
currentLocale_t = newlocale(LC_ALL, setlocale(LC_ALL, "C"), 0);
setlocale(LC_CTYPE, "en_US.UTF-8");
// std::ios_base::sync_with_stdio(false);
// std::locale utf8( std::locale(), new std::codecvt_utf8<wchar_t> );
// std::wcout.imbue(utf8);
# else // HAS_LOCALE
setlocale(LC_ALL, "");
setlocale(LC_NUMERIC, "C");
# endif // HAS_LOCALE
# endif // ANDROID
PRIVATE->delete_locs = false;
__syslocname__ = __sysoemname__ = 0;
__utf8name__ = const_cast<char *>("UTF-8");
# ifdef PIP_ICU
UErrorCode e((UErrorCode)0);
u_init(&e);
# ifdef WINDOWS
PRIVATE->delete_locs = true;
CPINFOEX cpinfo;
int l = 0;
GetCPInfoEx(CP_OEMCP, 0, &cpinfo);
for (l = 0; l < MAX_PATH; ++l)
if (cpinfo.CodePageName[l] == '\0' || cpinfo.CodePageName[l] == ' ') break;
__sysoemname__ = new char[256];
memset(__sysoemname__, 0, 256);
memcpy(__sysoemname__, "ibm-", 4);
memcpy(&(__sysoemname__[4]), cpinfo.CodePageName, l);
# else
/*PIString en(getenv("LANG"));
if (!en.isEmpty())
en = en.mid(en.find(".") + 1);
PIByteArray enba = en.toByteArray();
memcpy(__syslocname__, enba.data(), enba.size_s());*/
# endif
// piCout << __syslocname__;
// piCout << __sysoemname__;
# else // PIP_ICU
# ifdef WINDOWS
__syslocname__ = (char *)CP_ACP;
__sysoemname__ = (char *)CP_OEMCP;
__utf8name__ = (char *)CP_UTF8;
# endif
# endif // PIP_ICU
# ifdef MAC_OS
host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &__pi_mac_clock);
# endif
char cbuff[1024];
memset(cbuff, 0, 1024);
if (gethostname(cbuff, 1023) == 0) {
sinfo->hostname = cbuff;
}
# ifdef WINDOWS
SYSTEM_INFO sysinfo;
GetSystemInfo(&sysinfo);
sinfo->processorsCount = sysinfo.dwNumberOfProcessors;
switch (sysinfo.wProcessorArchitecture) {
case PROCESSOR_ARCHITECTURE_AMD64: sinfo->architecture = PIStringAscii("x86_64"); break;
case PROCESSOR_ARCHITECTURE_ARM: sinfo->architecture = PIStringAscii("arm"); break;
case PROCESSOR_ARCHITECTURE_IA64: sinfo->architecture = PIStringAscii("Intel Itanium-based"); break;
case PROCESSOR_ARCHITECTURE_INTEL: sinfo->architecture = PIStringAscii("x86"); break;
case PROCESSOR_ARCHITECTURE_UNKNOWN:
default: sinfo->architecture = PIStringAscii("unknown"); break;
}
int argc_(0);
wchar_t ** argv_ = CommandLineToArgvW(GetCommandLineW(), &argc_);
if (argc_ > 0 && argv_ != 0) sinfo->execCommand = argv_[0];
LocalFree(argv_);
memset(cbuff, 0, 1024);
ulong unlen = 1023;
if (GetUserNameA(cbuff, &unlen) != 0) sinfo->user = cbuff;
# else // WINDOWS
sinfo->processorsCount = piMaxi(1, int(sysconf(_SC_NPROCESSORS_ONLN)));
passwd * ps = getpwuid(getuid());
if (ps)
sinfo->user = ps->pw_name;
else {
memset(cbuff, 0, 1024);
char * l = getlogin();
if (l) sinfo->user = l;
}
struct utsname uns;
if (uname(&uns) == 0) {
sinfo->OS_version = uns.release;
sinfo->architecture = uns.machine;
}
# endif // WINDOWS
# ifdef ESP_PLATFORM
esp_chip_info_t chip_info;
esp_chip_info(&chip_info);
sinfo->processorsCount = chip_info.cores;
sinfo->architecture = "Xtensa LX6";
// printf("silicon revision %d, ", chip_info.revision);
sinfo->OS_version = esp_get_idf_version();
# endif
sinfo->OS_name =
# ifdef WINDOWS
PIStringAscii("Windows");
# elif defined(QNX)
PIStringAscii("QNX");
# elif defined(MAC_OS)
PIStringAscii("MacOS");
# elif defined(ANDROID)
PIStringAscii("Android");
# elif defined(FREE_BSD)
PIStringAscii("FreeBSD");
# elif defined(FREERTOS)
PIStringAscii("FreeRTOS");
# elif defined(MICRO_PIP)
PIStringAscii("MicroPIP");
# else
uns.sysname;
# endif
}
PIInit::~PIInit() {
PIResourcesStorage::instance()->clear();
# ifdef WINDOWS
WSACleanup();
if (PRIVATE->ntlib) FreeLibrary(PRIVATE->ntlib);
PRIVATE->ntlib = 0;
# endif
# ifdef MAC_OS
mach_port_deallocate(mach_task_self(), __pi_mac_clock);
# endif
if (PRIVATE->delete_locs) {
if (__syslocname__) delete __syslocname__;
if (__sysoemname__) delete __sysoemname__;
}
# ifdef PIP_ICU
u_cleanup();
# endif
}
bool PIInit::isBuildOptionEnabled(PIInit::BuildOption o) {
switch (o) {
case boICU:
return
# ifdef PIP_ICU
true;
# else
false;
# endif
case boUSB:
return
# ifdef PIP_USB
true;
# else
false;
# endif
case boCrypt:
return
# ifdef PIP_CRYPT
true;
# else
false;
# endif
case boIntrospection:
return
# ifdef PIP_INTROSPECTION
true;
# else
false;
# endif
case boFFTW:
return
# ifdef PIP_FFTW
true;
# else
false;
# endif
case boCompress:
return
# ifdef PIP_COMPRESS
true;
# else
false;
# endif
case boOpenCL:
return
# ifdef PIP_OPENCL
true;
# else
false;
# endif
case boCloud:
return
# ifdef PIP_CLOUD
true;
# else
false;
# endif
case boConsole:
return
# ifdef PIP_CONSOLE
true;
# else
false;
# endif
default: return false;
}
return false;
}
PIStringList PIInit::buildOptions() {
PIStringList ret;
if (isBuildOptionEnabled(boICU)) ret << "ICU";
if (isBuildOptionEnabled(boUSB)) ret << "USB";
if (isBuildOptionEnabled(boCrypt)) ret << "Crypt";
if (isBuildOptionEnabled(boIntrospection)) ret << "Introspection";
if (isBuildOptionEnabled(boFFTW)) ret << "FFTW";
if (isBuildOptionEnabled(boCompress)) ret << "Compress";
if (isBuildOptionEnabled(boOpenCL)) ret << "OpenCL";
if (isBuildOptionEnabled(boCloud)) ret << "Cloud";
if (isBuildOptionEnabled(boConsole)) ret << "Console";
return ret;
}
bool PIInit::fileExists(const PIString & p) {
FILE * f = fopen(p.data(), "r");
if (f == 0) return false;
fclose(f);
return true;
}
int __PIInit_Initializer__::count_(0);
PIInit * __PIInit_Initializer__::__instance__(0);
__PIInit_Initializer__::__PIInit_Initializer__() {
count_++;
if (count_ > 1) return;
// piCout << "create PIInit";
__instance__ = new PIInit();
}
__PIInit_Initializer__::~__PIInit_Initializer__() {
count_--;
if (count_ > 0) return;
// piCout << "delete PIInit";
if (__instance__ != 0) {
delete __instance__;
__instance__ = 0;
}
}
#endif // MICRO_PIP