mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-15 14:16:07 -06:00
331 lines
6.5 KiB
C++
331 lines
6.5 KiB
C++
#include "Core.h"
|
|
|
|
NAMESPACE_UPP
|
|
|
|
#ifdef PLATFORM_WINCE
|
|
const char *FromSysChrSet(const wchar *s)
|
|
{
|
|
static char out[256];
|
|
FromUnicode(out, s, wstrlen(s), CHARSET_DEFAULT);
|
|
return out;
|
|
}
|
|
|
|
const wchar *ToSysChrSet(const char *s)
|
|
{
|
|
static wchar out[1024];
|
|
ToUnicode(out, s, strlen(s), CHARSET_DEFAULT);
|
|
return out;
|
|
}
|
|
#endif
|
|
|
|
LogStream::LogStream()
|
|
{
|
|
#ifdef PLATFORM_POSIX
|
|
hfile = -1;
|
|
#else
|
|
hfile = INVALID_HANDLE_VALUE;
|
|
#endif
|
|
part = 0;
|
|
sizelimit = 0;
|
|
*filename = 0;
|
|
options = LOG_FILE;
|
|
depth = 0;
|
|
bol = false;
|
|
}
|
|
|
|
LogStream::~LogStream() {}
|
|
|
|
void LogStream::Close()
|
|
{
|
|
#ifdef PLATFORM_POSIX
|
|
if(hfile >= 0)
|
|
close(hfile);
|
|
hfile = -1;
|
|
#else
|
|
if(hfile != INVALID_HANDLE_VALUE)
|
|
CloseHandle(hfile);
|
|
hfile = INVALID_HANDLE_VALUE;
|
|
#endif
|
|
}
|
|
|
|
bool LogStream::Delete()
|
|
{
|
|
Close();
|
|
if(*filename) {
|
|
if(!FileDelete(filename)) {
|
|
BugLog() << "Error deleting " << filename << ": " << GetLastErrorMessage();
|
|
return false;
|
|
}
|
|
*filename = 0;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void LogStream::Create(const char *path, bool append)
|
|
{
|
|
Close();
|
|
|
|
strcpy(filename, path);
|
|
strcpy(backup, filename);
|
|
strcat(backup, ".old");
|
|
|
|
#if defined(PLATFORM_WIN32)
|
|
|
|
#if defined(PLATFORM_WINCE)
|
|
wchar_t pwcs[512];
|
|
mbstowcs(pwcs, backup, strlen(backup));
|
|
DeleteFile(pwcs);
|
|
#else
|
|
DeleteFile(backup);
|
|
#endif
|
|
|
|
#elif defined(PLATFORM_POSIX)
|
|
unlink(backup);
|
|
#else
|
|
#error
|
|
#endif
|
|
|
|
#if defined(PLATFORM_WIN32)
|
|
#if defined(PLATFORM_WINCE)
|
|
wchar_t wfilename[512];
|
|
mbstowcs(wfilename, filename, strlen(filename));
|
|
MoveFile(wfilename, pwcs);
|
|
#else
|
|
MoveFile(filename, backup);
|
|
#endif
|
|
#elif defined(PLATFORM_POSIX)
|
|
rename(filename, backup);
|
|
#else
|
|
#error
|
|
#endif
|
|
|
|
filesize = 0;
|
|
|
|
#ifdef PLATFORM_WIN32
|
|
hfile = CreateFile(ToSysChrSet(filename),
|
|
GENERIC_READ|GENERIC_WRITE,
|
|
FILE_SHARE_READ|FILE_SHARE_WRITE,
|
|
NULL,
|
|
append ? OPEN_ALWAYS : CREATE_ALWAYS,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL
|
|
);
|
|
if(append)
|
|
filesize = (int)SetFilePointer(hfile, 0, NULL, FILE_END);
|
|
#else
|
|
hfile = open(filename, append ? O_CREAT|O_RDWR : O_CREAT|O_RDWR|O_TRUNC, 0644);
|
|
if(append)
|
|
filesize = (int)lseek(hfile, 0, SEEK_END);
|
|
#endif
|
|
wrlim = ptr = (byte *)this;
|
|
p = buffer;
|
|
|
|
Time t = GetSysTime();
|
|
#ifdef PLATFORM_WINCE
|
|
wchar exe[512];
|
|
#else
|
|
char exe[512];
|
|
#endif
|
|
char user[500];
|
|
*user = 0;
|
|
|
|
#ifdef PLATFORM_WIN32
|
|
GetModuleFileName(AppGetHandle(), exe, 512);
|
|
#ifndef PLATFORM_WINCE
|
|
dword w = 2048;
|
|
GetUserName(user, &w);
|
|
#endif
|
|
#else //#
|
|
const char *procexepath_();
|
|
strcpy(exe, procexepath_());
|
|
const char *uenv = getenv("USER");
|
|
strcpy(user, uenv ? uenv : "boot");
|
|
#endif
|
|
|
|
char h[1000];
|
|
sprintf(h, "* %s %02d.%02d.%04d %02d:%02d:%02d, user: %s\n",
|
|
FromSysChrSet(exe),
|
|
t.day, t.month, t.year, t.hour, t.minute, t.second, user);
|
|
#ifdef PLATFORM_WIN32
|
|
dword n;
|
|
WriteFile(hfile, h, (dword)strlen(h), &n, NULL);
|
|
if(part) {
|
|
sprintf(h, ", #%d", part);
|
|
WriteFile(hfile, h, (dword)strlen(h) , &n, NULL);
|
|
}
|
|
WriteFile(hfile, "\r\n", 2, &n, NULL);
|
|
#else
|
|
write(hfile, h, strlen(h));
|
|
if(part) {
|
|
sprintf(h, ", #%d", part);
|
|
write(hfile, h, strlen(h));
|
|
}
|
|
write(hfile, "\r\n", 2);
|
|
#endif
|
|
}
|
|
|
|
void LogStream::Flush()
|
|
{
|
|
int count = (int)(p - buffer);
|
|
if(count == 0) return;
|
|
if(options & LOG_COUT)
|
|
Cout().Put(buffer, count);
|
|
if(options & LOG_CERR)
|
|
Cerr().Put(buffer, count);
|
|
#ifdef PLATFORM_WIN32
|
|
if(options & LOG_FILE)
|
|
if(hfile != INVALID_HANDLE_VALUE) {
|
|
dword n;
|
|
WriteFile(hfile, buffer, count, &n, NULL);
|
|
}
|
|
if(options & LOG_DBG) {
|
|
*p = 0;
|
|
::OutputDebugString((LPCSTR)buffer);
|
|
}
|
|
#else
|
|
if(options & LOG_FILE)
|
|
if(hfile >= 0)
|
|
write(hfile, buffer, count);
|
|
if(options & LOG_DBG)
|
|
Cerr().Put(buffer, count);
|
|
#endif
|
|
filesize += count;
|
|
p = buffer;
|
|
if(sizelimit > 0 && filesize > sizelimit)
|
|
Create(filename, false);
|
|
}
|
|
|
|
void LogStream::Put0(int w)
|
|
{
|
|
if(w == LOG_BEGIN)
|
|
depth++;
|
|
else
|
|
if(w == LOG_END)
|
|
depth--;
|
|
else {
|
|
if(bol) {
|
|
bol = false;
|
|
for(int q = depth; q--;)
|
|
Put0('\t');
|
|
}
|
|
*p++ = w;
|
|
if(w == '\n') {
|
|
Flush();
|
|
bol = true;
|
|
}
|
|
else
|
|
if(p == buffer + 512)
|
|
Flush();
|
|
}
|
|
}
|
|
|
|
void LogStream::_Put(int w)
|
|
{
|
|
CriticalSection::Lock __(cs);
|
|
Put0(w);
|
|
}
|
|
|
|
void LogStream::_Put(const void *data, dword size)
|
|
{
|
|
CriticalSection::Lock __(cs);
|
|
const byte *q = (byte *)data;
|
|
while(size--)
|
|
Put0(*q++);
|
|
}
|
|
|
|
bool LogStream::IsOpen() const
|
|
{
|
|
#ifdef PLATFORM_POSIX
|
|
return hfile >= 0;
|
|
#else
|
|
return hfile != INVALID_HANDLE_VALUE;
|
|
#endif
|
|
}
|
|
|
|
static void sLarge(String& text, size_t *large, int count, const char *txt)
|
|
{
|
|
int n = min(1024, count);
|
|
Sort(large, large + n, StdLess<size_t>());
|
|
int i = 0;
|
|
while(i < n) {
|
|
size_t q = large[i];
|
|
int nn = i++;
|
|
while(i < n && large[i] == q) i++;
|
|
nn = i - nn;
|
|
if(q < 10000)
|
|
text << Format("%4d B, %5d %s (%6d KB)\r\n", (int)(uintptr_t)q, nn, txt, (int)(uintptr_t)((nn * q) >> 10));
|
|
else
|
|
text << Format("%4d`KB, %5d %s (%6d KB)\r\n", (int)(uintptr_t)(q >> 10), nn, txt, (int)(uintptr_t)((nn * q) >> 10));
|
|
}
|
|
}
|
|
|
|
String AsString(MemoryProfile& mem)
|
|
{
|
|
String text;
|
|
int acount = 0;
|
|
size_t asize = 0;
|
|
int fcount = 0;
|
|
size_t fsize = 0;
|
|
for(int i = 0; i < 1024; i++)
|
|
if(mem.allocated[i]) {
|
|
int sz = 4 * i;
|
|
text << Format("%4d B, %6d allocated (%5d KB), %6d fragmented (%5d KB)\n",
|
|
sz, mem.allocated[i], (mem.allocated[i] * sz) >> 10,
|
|
mem.fragmented[i], (mem.fragmented[i] * sz) >> 10);
|
|
acount += mem.allocated[i];
|
|
asize += mem.allocated[i] * sz;
|
|
fcount += mem.fragmented[i];
|
|
fsize += mem.fragmented[i] * sz;
|
|
}
|
|
text << Format(" TOTAL, %6d allocated (%5d KB), %6d fragmented (%5d KB)\n",
|
|
acount, int(asize >> 10), fcount, int(fsize >> 10));
|
|
text << "Free pages " << mem.freepages << " (" << mem.freepages * 4 << " KB)\n";
|
|
text << "Large block count " << mem.large_count
|
|
<< ", total size " << (mem.large_total >> 10) << " KB\n";
|
|
sLarge(text, mem.large_size, mem.large_count, "allocated");
|
|
text << "Large fragments count " << mem.large_free_count
|
|
<< ", total size " << (mem.large_free_total >> 10) << " KB\n";
|
|
sLarge(text, mem.large_free_size, mem.large_free_count, "fragments");
|
|
return text;
|
|
}
|
|
|
|
|
|
#ifdef _MULTITHREADED
|
|
|
|
StaticCriticalSection sLogLock;
|
|
|
|
void LockLog()
|
|
{
|
|
sLogLock.Enter();
|
|
}
|
|
|
|
void UnlockLog()
|
|
{
|
|
sLogLock.Leave();
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifdef flagCHECKINIT
|
|
|
|
void InitBlockBegin__(const char *fn, int line) {
|
|
RLOG(fn << " " << line << " init block");
|
|
#ifdef HEAPDBG
|
|
MemoryCheckDebug();
|
|
#else
|
|
MemoryCheck();
|
|
#endif
|
|
}
|
|
|
|
void InitBlockEnd__(const char *fn, int line) {
|
|
RLOG(fn << " " << line << " init block finished");
|
|
#ifdef HEAPDBG
|
|
MemoryCheckDebug();
|
|
#else
|
|
MemoryCheck();
|
|
#endif
|
|
}
|
|
|
|
#endif
|
|
|
|
END_UPP_NAMESPACE
|