aboutsummaryrefslogtreecommitdiff
path: root/Src/Wasabi/bfc/util
diff options
context:
space:
mode:
Diffstat (limited to 'Src/Wasabi/bfc/util')
-rw-r--r--Src/Wasabi/bfc/util/base64.cpp315
-rw-r--r--Src/Wasabi/bfc/util/base64.h16
-rw-r--r--Src/Wasabi/bfc/util/findopenrect.cpp251
-rw-r--r--Src/Wasabi/bfc/util/findopenrect.h63
-rw-r--r--Src/Wasabi/bfc/util/inifile.cpp56
-rw-r--r--Src/Wasabi/bfc/util/inifile.h28
-rw-r--r--Src/Wasabi/bfc/util/profile.c288
-rw-r--r--Src/Wasabi/bfc/util/profile.h26
-rw-r--r--Src/Wasabi/bfc/util/profiler.cpp6
-rw-r--r--Src/Wasabi/bfc/util/profiler.h128
-rw-r--r--Src/Wasabi/bfc/util/timefmt.cpp71
-rw-r--r--Src/Wasabi/bfc/util/timefmt.h46
12 files changed, 1294 insertions, 0 deletions
diff --git a/Src/Wasabi/bfc/util/base64.cpp b/Src/Wasabi/bfc/util/base64.cpp
new file mode 100644
index 00000000..1a67b9f1
--- /dev/null
+++ b/Src/Wasabi/bfc/util/base64.cpp
@@ -0,0 +1,315 @@
+/* Based on code from Dave Winer (http://www.scripting.com/midas/base64/) */
+#include "precomp_wasabi_bfc.h"
+#include "base64.h"
+
+char Base64::encodingTable [64] = {
+ 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
+ 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
+ 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
+ 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
+};
+
+int Base64::encode(MemBlock<char> &htext, MemBlock<char> &h64, int linelength) {
+ /*
+ encode the handle. some funny stuff about linelength -- it only makes
+ sense to make it a multiple of 4. if it's not a multiple of 4, we make it
+ so (by only checking it every 4 characters.
+ further, if it's 0, we don't add any line breaks at all.
+ */
+ unsigned long ixtext;
+ unsigned long lentext;
+ unsigned long origsize;
+ long ctremaining;
+ unsigned char inbuf [3] = {0}, outbuf [4] = {0};
+ short i;
+ short charsonline = 0, ctcopy;
+
+ ixtext = 0;
+
+ lentext = htext.getSize();
+
+ while (1) {
+ ctremaining = lentext - ixtext;
+
+ if (ctremaining <= 0)
+ break;
+
+ for (i = 0; i < 3; i++) {
+ unsigned long ix = ixtext + i;
+ if (ix < lentext)
+ inbuf [i] = *htext.getMemory(ix);
+ else
+ inbuf [i] = 0;
+ }
+
+ outbuf [0] = (inbuf [0] & 0xFC) >> 2;
+ outbuf [1] = ((inbuf [0] & 0x03) << 4) | ((inbuf [1] & 0xF0) >> 4);
+ outbuf [2] = ((inbuf [1] & 0x0F) << 2) | ((inbuf [2] & 0xC0) >> 6);
+ outbuf [3] = inbuf [2] & 0x3F;
+
+ origsize = h64.getSize();
+ h64.setSize(origsize + 4);
+
+ ctcopy = 4;
+
+ switch (ctremaining) {
+ case 1:
+ ctcopy = 2;
+ break;
+ case 2:
+ ctcopy = 3;
+ break;
+ }
+
+ for (i = 0; i < ctcopy; i++)
+ *h64.getMemory(origsize + i) = encodingTable[outbuf[i]];
+
+ for (i = ctcopy; i < 4; i++)
+ *h64.getMemory(origsize + i) = '=';
+
+ ixtext += 3;
+ charsonline += 4;
+
+ if (linelength > 0) { /*DW 4/8/97 -- 0 means no line breaks*/
+ if (charsonline >= linelength) {
+ charsonline = 0;
+ origsize = h64.getSize();
+ h64.setSize(origsize + 1);
+ *h64.getMemory() = '\n';
+ }
+ }
+ }
+ return 1;
+}
+int Base64::encode(MemBlock<char> &htext, MemBlock<wchar_t> &h64, int linelength) {
+ /*
+ encode the handle. some funny stuff about linelength -- it only makes
+ sense to make it a multiple of 4. if it's not a multiple of 4, we make it
+ so (by only checking it every 4 characters.
+ further, if it's 0, we don't add any line breaks at all.
+ */
+ unsigned long ixtext;
+ unsigned long lentext;
+ unsigned long origsize;
+ long ctremaining;
+ unsigned char inbuf [3] = {0}, outbuf [4] = {0};
+ short i;
+ short charsonline = 0, ctcopy;
+
+ ixtext = 0;
+
+ lentext = htext.getSize();
+
+ while (1) {
+ ctremaining = lentext - ixtext;
+
+ if (ctremaining <= 0)
+ break;
+
+ for (i = 0; i < 3; i++) {
+ unsigned long ix = ixtext + i;
+ if (ix < lentext)
+ inbuf [i] = *htext.getMemory(ix);
+ else
+ inbuf [i] = 0;
+ }
+
+ outbuf [0] = (inbuf [0] & 0xFC) >> 2;
+ outbuf [1] = ((inbuf [0] & 0x03) << 4) | ((inbuf [1] & 0xF0) >> 4);
+ outbuf [2] = ((inbuf [1] & 0x0F) << 2) | ((inbuf [2] & 0xC0) >> 6);
+ outbuf [3] = inbuf [2] & 0x3F;
+
+ origsize = h64.getSize();
+ h64.setSize(origsize + 4);
+
+ ctcopy = 4;
+
+ switch (ctremaining) {
+ case 1:
+ ctcopy = 2;
+ break;
+ case 2:
+ ctcopy = 3;
+ break;
+ }
+
+ for (i = 0; i < ctcopy; i++)
+ *h64.getMemory(origsize + i) = encodingTable[outbuf[i]];
+
+ for (i = ctcopy; i < 4; i++)
+ *h64.getMemory(origsize + i) = '=';
+
+ ixtext += 3;
+ charsonline += 4;
+
+ if (linelength > 0) { /*DW 4/8/97 -- 0 means no line breaks*/
+ if (charsonline >= linelength) {
+ charsonline = 0;
+ origsize = h64.getSize();
+ h64.setSize(origsize + 1);
+ *h64.getMemory() = '\n';
+ }
+ }
+ }
+ return 1;
+}
+
+
+int Base64::decode(MemBlock<char> &h64, MemBlock<char> &htext) {
+ unsigned long ixtext;
+ unsigned long lentext;
+ unsigned long origsize;
+ unsigned char ch;
+ unsigned char inbuf [4] = {0}, outbuf [4] = {0};
+ short i, ixinbuf;
+ boolean flignore;
+ boolean flendtext = false;
+
+ ixtext = 0;
+
+ lentext = h64.getSize();
+
+ ixinbuf = 0;
+
+ while (true) {
+ if (ixtext >= lentext)
+ break;
+ ch = *h64.getMemory(ixtext++);
+
+ flignore = 0;
+
+ if ((ch >= 'A') && (ch <= 'Z'))
+ ch = ch - 'A';
+ else if ((ch >= 'a') && (ch <= 'z'))
+ ch = ch - 'a' + 26;
+ else if ((ch >= '0') && (ch <= '9'))
+ ch = ch - '0' + 52;
+ else if (ch == '+')
+ ch = 62;
+ else if (ch == '=') /*no op -- can't ignore this one*/
+ flendtext = true;
+ else if (ch == '/')
+ ch = 63;
+ else
+ flignore = true;
+
+ if (!flignore) {
+ short ctcharsinbuf = 3;
+ boolean flbreak = false;
+
+ if (flendtext) {
+ if (ixinbuf == 0)
+ break;
+
+ if ((ixinbuf == 1) || (ixinbuf == 2))
+ ctcharsinbuf = 1;
+ else
+ ctcharsinbuf = 2;
+
+ ixinbuf = 3;
+ flbreak = 1;
+ }
+
+ inbuf [ixinbuf++] = ch;
+
+ if (ixinbuf == 4) {
+ ixinbuf = 0;
+
+ outbuf [0] = (inbuf [0] << 2) | ((inbuf [1] & 0x30) >> 4);
+ outbuf [1] = ((inbuf [1] & 0x0F) << 4) | ((inbuf [2] & 0x3C) >> 2);
+ outbuf [2] = ((inbuf [2] & 0x03) << 6) | (inbuf [3] & 0x3F);
+
+ origsize = htext.getSize();
+ htext.setSize(origsize + ctcharsinbuf);
+
+ for (i = 0; i < ctcharsinbuf; i++)
+ *htext.getMemory(origsize + i) = outbuf[i];
+ }
+
+ if (flbreak)
+ break;
+ }
+ }
+
+ return 1;
+}
+int Base64::decode(MemBlock<wchar_t> &h64, MemBlock<char> &htext) {
+ unsigned long ixtext;
+ unsigned long lentext;
+ unsigned long origsize;
+ unsigned char ch;
+ unsigned char inbuf [4] = {0}, outbuf [4] = {0};
+ short i, ixinbuf;
+ boolean flignore;
+ boolean flendtext = false;
+
+ ixtext = 0;
+
+ lentext = h64.getSize();
+
+ ixinbuf = 0;
+
+ while (true) {
+ if (ixtext >= lentext)
+ break;
+ ch = (unsigned char)*h64.getMemory(ixtext++);
+
+ flignore = 0;
+
+ if ((ch >= 'A') && (ch <= 'Z'))
+ ch = ch - 'A';
+ else if ((ch >= 'a') && (ch <= 'z'))
+ ch = ch - 'a' + 26;
+ else if ((ch >= '0') && (ch <= '9'))
+ ch = ch - '0' + 52;
+ else if (ch == '+')
+ ch = 62;
+ else if (ch == '=') /*no op -- can't ignore this one*/
+ flendtext = true;
+ else if (ch == '/')
+ ch = 63;
+ else
+ flignore = true;
+
+ if (!flignore) {
+ short ctcharsinbuf = 3;
+ boolean flbreak = false;
+
+ if (flendtext) {
+ if (ixinbuf == 0)
+ break;
+
+ if ((ixinbuf == 1) || (ixinbuf == 2))
+ ctcharsinbuf = 1;
+ else
+ ctcharsinbuf = 2;
+
+ ixinbuf = 3;
+ flbreak = 1;
+ }
+
+ inbuf [ixinbuf++] = ch;
+
+ if (ixinbuf == 4) {
+ ixinbuf = 0;
+
+ outbuf [0] = (inbuf [0] << 2) | ((inbuf [1] & 0x30) >> 4);
+ outbuf [1] = ((inbuf [1] & 0x0F) << 4) | ((inbuf [2] & 0x3C) >> 2);
+ outbuf [2] = ((inbuf [2] & 0x03) << 6) | (inbuf [3] & 0x3F);
+
+ origsize = htext.getSize();
+ htext.setSize(origsize + ctcharsinbuf);
+
+ for (i = 0; i < ctcharsinbuf; i++)
+ *htext.getMemory(origsize + i) = outbuf[i];
+ }
+
+ if (flbreak)
+ break;
+ }
+ }
+
+ return 1;
+}
+
+
diff --git a/Src/Wasabi/bfc/util/base64.h b/Src/Wasabi/bfc/util/base64.h
new file mode 100644
index 00000000..fc4fd658
--- /dev/null
+++ b/Src/Wasabi/bfc/util/base64.h
@@ -0,0 +1,16 @@
+#ifndef _BASE64_H
+#define _BASE64_H
+
+#include <bfc/memblock.h>
+
+class Base64 {
+public:
+ static int decode(MemBlock<wchar_t> &h64, MemBlock<char> &htext);
+ static int decode(MemBlock<char> &h64, MemBlock<char> &htext);
+ static int encode(MemBlock<char> &htext, MemBlock<char> &h64, int linelength);
+ static int encode(MemBlock<char> &htext, MemBlock<wchar_t> &h64, int linelength);
+private:
+ static char encodingTable[64];
+};
+
+#endif
diff --git a/Src/Wasabi/bfc/util/findopenrect.cpp b/Src/Wasabi/bfc/util/findopenrect.cpp
new file mode 100644
index 00000000..537651d2
--- /dev/null
+++ b/Src/Wasabi/bfc/util/findopenrect.cpp
@@ -0,0 +1,251 @@
+#include <precomp.h>
+#include "findopenrect.h"
+
+#include <bfc/pair.h>
+
+//CUT #define MAXTRIALS 10000 // unless time runs out
+#define MOUSEPENALTY 65536
+
+FindOpenRect::FindOpenRect()
+{
+ timelimit = 100;
+ iters = 0;
+ xdiv = ydiv = 1;
+ fn = compare_overlapArea;
+ userdata = userdata2 = 0;
+ bsfval = bsfdist = 0;
+}
+
+void FindOpenRect::setCompareRectsFn(compareRectsFn _fn)
+{
+ fn = _fn;
+}
+
+RECT FindOpenRect::find(const RECT &vr, const PtrList<RECT> &list, const RECT &prev, unsigned long userdata, unsigned long userdata2)
+{
+ beginFind(vr, list, prev, userdata, userdata2);
+ return findMore();
+}
+
+void FindOpenRect::beginFind(const RECT &viewport, const PtrList<RECT> &_list,
+ const RECT &_prev, unsigned long _userdata, unsigned long _userdata2)
+{
+ vr = viewport;
+ list.copyFrom(&_list);
+ prev = _prev;
+ userdata = _userdata;
+ userdata2 = _userdata2;
+
+ // reset best rect found so far
+ //CUT bsf_nooverlap = prev;
+ //CUT found_nooverlap=0;
+ //CUT bsf_overlap = prev;
+ //CUT bsfval_nooverlap = 1e100;
+ //CUT bsfval_overlap = 1e100;
+ bsfrect = prev;
+ bsfval = 10e10;
+ bsfdist = 10e10;
+
+ //CUT POINT mousepos;
+ //CUT Std::getMousePos(&mousepos);
+}
+
+RECT FindOpenRect::findMore()
+{
+ int w = prev.right - prev.left, h = prev.bottom - prev.top;
+ int vw = vr.right - vr.left;
+ int vh = vr.bottom - vr.top;
+
+ if (vw <= w || vh <= h)
+ {
+ DebugStringW(L"findopenrect: window too big for viewport");
+ }
+
+
+ double started = Wasabi::Std::getTimeStampMS();
+
+ for (int c = 0; /*CUTc < MAXTRIALS*/; c++)
+ {
+
+ // too bad = crashy crash :P love, BU
+ if (c != 0 && (vw <= w || vh <= h))
+ break;
+
+ // set the trial rect
+ RECT tr;
+ if (iters == 0)
+ { // try prev
+ tr = prev;
+ }
+ else
+ {
+ int x = Wasabi::Std::random32(vw - w) + vr.top;
+ int y = Wasabi::Std::random32(vh - h) + vr.left;
+ if (xdiv != 1) x -= x % xdiv;
+ if (ydiv != 1) y -= y % ydiv;
+ tr = Wasabi::Std::makeRect(x, y, x + w, y + h);
+ }
+
+ // add up the coverage of trial position
+ trySingleRect(tr, TRUE);
+
+ if (timelimit > 0 && c > 0 && (int)((Wasabi::Std::getTimeStampMS() - started)*1000.f) > timelimit)
+ {
+ // DebugString("FindOpenRect::find() timeout, %d iters", c);
+ break;
+ }
+ }
+
+ return getBestRectSoFar();
+}
+
+typedef Pair<RECT, double> RectV;
+
+namespace
+{
+ class Sorter
+ {
+ public:
+ static int compareItem(RectV *p1, RectV* p2)
+ {
+ return -CMP3(p1->b, p2->b);
+ }
+ };
+};
+
+double FindOpenRect::trySingleRect(const RECT &tr, int early_out)
+{
+#if 0
+ PtrListQuickSorted<RectV, Sorter> candidates(list.getNumItems());
+ foreach(list)
+ double d = compare_overlapArea(tr, *list.getfor());
+ candidates.addItem(new RectV(*list.getfor(), d));
+ endfor
+ candidates.sort();
+#else
+ PtrList<RECT> candidates;
+ candidates.copyFrom(&list);
+#endif
+
+ double trarea = 0;
+
+ foreach(candidates)
+#if 0
+ RECT *wr = &candidates.getfor()->a;
+#else
+ RECT *wr = candidates.getfor();
+#endif
+ //CUT double bsf = MIN(found_nooverlap ? 0 : bsfval_nooverlap, bsfval_overlap);
+ trarea += (*fn)(tr, *wr, userdata, userdata2, foreach_index, bsfval);
+
+ // early quit if not breaking any records
+ if (early_out && trarea >= bsfval) break;
+
+ endfor
+
+#if 0
+ candidates.deleteAll();
+#endif
+
+ if (trarea < 0.005) trarea = 0;
+
+#if 0
+ // found one that does not overlap!
+ if (trarea == 0)
+ {
+ if (val < bsfval_nooverlap)
+ { // if it's closer than prev closest, save it
+ bsf_nooverlap = tr;
+ bsfval_nooverlap = val;
+ found_nooverlap = 1;
+ }
+ }
+ else
+ {
+ if (trarea < bsfval_overlap)
+ { // overlaps least stuff
+ bsf_overlap = tr;
+ bsfval_overlap = trarea;
+ }
+ }
+#endif
+ if (trarea == 0)
+ {
+ // find the distance from the previous
+ double val = SQRT(SQR(prev.left - tr.left) + SQR(prev.top - tr.top));
+ if (bsfdist > val)
+ {
+ bsfrect = tr;
+ bsfdist = val;
+ }
+ }
+ else
+ {
+ if (trarea < bsfval)
+ {
+ bsfrect = tr;
+ bsfval = trarea;
+ }
+ }
+ iters++;
+ return trarea;
+}
+
+double FindOpenRect::compare_overlapArea(const RECT &rect, const RECT &dest, unsigned long userdata, unsigned long userdata2, int index, double bsf)
+{
+ RECT intersection;
+ if (Wasabi::Std::rectIntersect(rect, dest, &intersection))
+ {
+ intersection.right -= intersection.left;
+ intersection.bottom -= intersection.top;
+ return intersection.right * intersection.bottom;
+ }
+ return 0;
+}
+
+void FindOpenRect::setTimeLimit(int ms)
+{
+ timelimit = ms;
+}
+
+int FindOpenRect::getNumIters()
+{
+ return iters;
+}
+
+void FindOpenRect::resetNumIters()
+{
+ iters = 0;
+}
+
+double FindOpenRect::getBestValSoFar()
+{
+ return (bsfval == 10e10) ? 0 : bsfval;
+}
+
+RECT FindOpenRect::getBestRectSoFar()
+{
+ return bsfrect;
+}
+
+void FindOpenRect::setBestSoFar(double bsf, const RECT &bestrect)
+{
+ if (bsf > 0 && bsfval > bsf)
+ {
+ bsfval = bsf;
+ bsfrect = bestrect;
+ bsfdist = SQRT(SQR(prev.left - bsfrect.left) + SQR(prev.top - bsfrect.top));
+ //CUTDebugString("*******************8 better BSF ****************");
+ }
+}
+
+RECT FindOpenRect::getOriginalRect()
+{
+ return prev;
+}
+
+void FindOpenRect::setCoordDivisor(int _xdiv, int _ydiv)
+{
+ xdiv = MAX(_xdiv, 1);
+ ydiv = MAX(_ydiv, 1);
+}
diff --git a/Src/Wasabi/bfc/util/findopenrect.h b/Src/Wasabi/bfc/util/findopenrect.h
new file mode 100644
index 00000000..97fdc5cb
--- /dev/null
+++ b/Src/Wasabi/bfc/util/findopenrect.h
@@ -0,0 +1,63 @@
+#ifndef _FINDOPENRECT_H
+#define _FINDOPENRECT_H
+
+#include <bfc/wasabi_std.h>
+#include <bfc/ptrlist.h>
+
+class FindOpenRect
+{
+public:
+ FindOpenRect();
+
+ typedef double (*compareRectsFn)(const RECT &rect, const RECT &dest, unsigned long userdata, unsigned long userdata2, int index, double bsf);
+ static double compare_overlapArea(const RECT &rect, const RECT &dest, unsigned long userdata = 0, unsigned long userdata2 = 0, int index = 0, double bsf = 0);
+
+ void setCompareRectsFn(compareRectsFn fn);
+
+ // this one does it all in one call
+ RECT find(const RECT &viewport, const PtrList<RECT> &list,
+ const RECT &prev, unsigned long userdata = 0, unsigned long userdata2 = 0);
+
+ // these let you do it over time
+ void beginFind(const RECT &viewport, const PtrList<RECT> &list,
+ const RECT &prev, unsigned long userdata = 0, unsigned long userdata2 = 0);
+ RECT findMore();
+
+ double trySingleRect(const RECT &r, int early_out = FALSE);
+
+ void setTimeLimit(int ms);
+ int getNumIters();
+ void resetNumIters();
+
+ double getBestValSoFar();
+ RECT getBestRectSoFar();
+
+ // this only sets it if it's a better value
+ void setBestSoFar(double bsf, const RECT &bestrect);
+
+ RECT getOriginalRect();
+
+ void setCoordDivisor(int xdiv, int ydiv);
+
+private:
+ RECT vr, prev;
+ PtrList<RECT> list;
+ compareRectsFn fn;
+ unsigned long userdata, userdata2;
+
+ int timelimit;
+ int iters;
+
+ int xdiv, ydiv;
+
+ RECT bsfrect;
+ double bsfval;
+ double bsfdist;
+ //CUT RECT bsf_nooverlap;
+ //CUT int found_nooverlap;
+ //CUT RECT bsf_overlap;
+ //CUT double bsfval_nooverlap;
+ //CUT double bsfval_overlap;
+};
+
+#endif
diff --git a/Src/Wasabi/bfc/util/inifile.cpp b/Src/Wasabi/bfc/util/inifile.cpp
new file mode 100644
index 00000000..dba5a9b5
--- /dev/null
+++ b/Src/Wasabi/bfc/util/inifile.cpp
@@ -0,0 +1,56 @@
+#include <precomp.h>
+
+#include "inifile.h"
+#include <bfc/nsguid.h>
+
+#ifndef WIN32
+#include "profile.h"
+#endif
+
+IniFile::IniFile(const wchar_t *_filename) : filename(_filename) { }
+
+void IniFile::setString(const wchar_t *section, const wchar_t *tagname, const wchar_t *val) {
+ WritePrivateProfileStringW(section, tagname, val, filename);
+}
+
+wchar_t *IniFile::getString(const wchar_t *section, const wchar_t *tagname, wchar_t *buf, int buflen, const wchar_t *default_val) {
+ GetPrivateProfileStringW(section, tagname, default_val, buf, buflen, filename);
+ return buf;
+}
+
+StringW IniFile::getString(const wchar_t *section, const wchar_t *tagname, const wchar_t *default_val) {
+ wchar_t buf[WA_MAX_PATH]=L"";
+ getString(section, tagname, buf, WA_MAX_PATH-1, default_val);
+ return StringW(buf);
+}
+
+void IniFile::setInt(const wchar_t *section, const wchar_t *tagname, int val) {
+ setString(section, tagname, StringPrintfW(val));
+}
+
+int IniFile::getInt(const wchar_t *section, const wchar_t *tagname, int default_val) {
+ wchar_t buf[MAX_PATH] = {0};
+ getString(section, tagname, buf, sizeof(buf), StringPrintfW(default_val));
+ return WTOI(buf);
+}
+
+int IniFile::getBool(const wchar_t *section, const wchar_t *tagname, int default_val) {
+ wchar_t buf[MAX_PATH] = {0};
+ getString(section, tagname, buf, sizeof(buf), default_val ? L"true" : L"false");
+ if (!_wcsicmp(buf, L"true")) return 1;
+ return 0;
+}
+
+void IniFile::setBool(const wchar_t *section, const wchar_t *tagname, int val) {
+ setString(section, tagname, val ? L"true" : L"false");
+}
+
+GUID IniFile::getGuid(const wchar_t *section, const wchar_t *tagname, GUID default_val) {
+ wchar_t buf[MAX_PATH] = {0};
+ getString(section, tagname, buf, sizeof(buf), StringPrintfW(default_val));
+ return nsGUID::fromCharW(buf);
+}
+
+void IniFile::setGuid(const wchar_t *section, const wchar_t *tagname, const GUID &val) {
+ setString(section, tagname, StringPrintfW(val));
+}
diff --git a/Src/Wasabi/bfc/util/inifile.h b/Src/Wasabi/bfc/util/inifile.h
new file mode 100644
index 00000000..6ce7b151
--- /dev/null
+++ b/Src/Wasabi/bfc/util/inifile.h
@@ -0,0 +1,28 @@
+#ifndef _INIFILE_H
+#define _INIFILE_H
+
+#include <bfc/string/StringW.h>
+
+class IniFile
+{
+public:
+ IniFile(const wchar_t *_filename);
+
+ void setString(const wchar_t *section, const wchar_t *tagname, const wchar_t *val);
+ wchar_t *getString(const wchar_t *section, const wchar_t *tagname, wchar_t *buf, int buflen, const wchar_t *default_val = L""); // returns buf
+ StringW getString(const wchar_t *section, const wchar_t *tagname, const wchar_t *default_val=L"");
+
+ void setInt(const wchar_t *section, const wchar_t *tagname, int val);
+ int getInt(const wchar_t *section, const wchar_t *tagname, int default_val = 0);
+
+ int getBool(const wchar_t *section, const wchar_t *tagname, int default_val = 0);
+ void setBool(const wchar_t *section, const wchar_t *tagname, int val);
+
+ GUID getGuid(const wchar_t *section, const wchar_t *tagname, GUID default_val = INVALID_GUID);
+ void setGuid(const wchar_t *section, const wchar_t *tagname, const GUID &val);
+
+private:
+ StringW filename;
+};
+
+#endif
diff --git a/Src/Wasabi/bfc/util/profile.c b/Src/Wasabi/bfc/util/profile.c
new file mode 100644
index 00000000..3049945a
--- /dev/null
+++ b/Src/Wasabi/bfc/util/profile.c
@@ -0,0 +1,288 @@
+#pragma warn -aus
+//----------------------------------------------------------------------------
+// MS Windows Style .ini File Interface for C++
+// This is the first version.
+// Programed by xuyifeng, 1995.10, china
+//----------------------------------------------------------------------------
+// Test history:
+// Compiler OS TEST
+// ---------------------------------------------------------------
+// Watcom C++ 10.0a Rational System DOS4GW 100% tested
+// Borland C++ 3.1 DOS 100% tested
+// 10/4/97 - Bugfix: added fclose(is); at the end of getProfileString -lonerunnr/ags
+//----------------------------------------------------------------------------
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/io.h>
+#include <string.h>
+#include <ctype.h>
+#ifdef LINUX
+#include <X11/Xos.h>
+#define _strnicmp strncasecmp
+#endif
+
+#include "profile.h"
+
+#define False 0
+#define True 1
+
+//------------------------------------------------------------------------------
+// titlePos: get a section title position & length in a string.
+//------------------------------------------------------------------------------
+static char *titlePos( char *buf, int *len )
+{
+ char *p = buf, *q;
+
+ while( *p && isspace(*p) ) p++;
+ if( *p != '[' )
+ return 0;
+
+ q = p+1;
+ while( *q && *q != ']' ) q++;
+ if( *q != ']' )
+ return 0;
+ if( len )
+ *len = (int)(q - p - 1);
+ return p+1;
+}
+
+//------------------------------------------------------------------------------
+// isTitleLine: check if a string is a section title line
+//------------------------------------------------------------------------------
+static int isTitleLine( char *bufPtr )
+{
+ return titlePos( bufPtr, 0 ) != 0;
+}
+
+//------------------------------------------------------------------------------
+// containTitle: check if a string contain a section a title
+//------------------------------------------------------------------------------
+static int containTitle( char *buf, const char *section )
+{
+ int len = 0;
+ char *p = titlePos(buf, &len);
+ if (p)
+ {
+ if( strlen( section ) == len && _strnicmp( section, p, len ) == 0 )
+ return True;
+ }
+ return False;
+}
+
+//------------------------------------------------------------------------------
+// gotoSection: move file position to start line of a section
+//------------------------------------------------------------------------------
+static int gotoSection( FILE *is, const char *section )
+{
+ char line[256] = {0};
+ while( fgets(line, 256, is) != NULL)
+ if( containTitle( line, section ) )
+ return True;
+ return False;
+}
+
+//------------------------------------------------------------------------------
+// textPos: get content's position of a entry
+//------------------------------------------------------------------------------
+static char *textPos( char *buf, const char *entry )
+{
+ if( buf[0] == ';' ) // it is comment line
+ return 0;
+
+ char *p = strchr( buf, '=' );
+ if (!p)
+ return 0;
+
+ int len = (int)(p - buf);
+ if( strlen(entry) == len && _strnicmp( buf, entry, len ) == 0 )
+ return p+1;
+
+ return 0;
+}
+
+//------------------------------------------------------------------------------
+// stripQuotationChar: strip a pair of quotation chars in a string
+//------------------------------------------------------------------------------
+static void stripQuotationChar( char *buf )
+{
+ char *p = buf;
+ while( *p && isspace(*p) ) p++;
+
+ if( !(*p == '\"' || *p == '\'') )
+ return;
+
+ char *q = p+strlen(p);
+ while( *q != *p && q > p ) q--;
+ if( q == p )
+ return;
+ int len = (int)(q - p - 1);
+ memmove( buf, p+1, len );
+ buf[len] = 0;
+}
+
+//------------------------------------------------------------------------------
+// readEntry: read content of entry
+//------------------------------------------------------------------------------
+static int readEntry( FILE *is, const char *entry, char *buf, int bufSize,
+ int strip )
+{
+ char lineBuf[256] = {0};
+ char *cur = buf;
+ *cur = '\0';
+ int len = -1;
+ while( fgets(lineBuf, 256, is) != NULL)
+ {
+ if (lineBuf[strlen(lineBuf)-1] == '\n')
+ lineBuf[strlen(lineBuf)-1] = 0;
+
+ if( isTitleLine( lineBuf ) ) // section is ended
+ break;
+
+ char *p = textPos( lineBuf, entry ); // not equal this entry
+ if( p == 0 )
+ continue;
+
+ if( strip )
+ stripQuotationChar( p );
+
+ len = strlen(p);
+ if( bufSize-1 < len )
+ len = bufSize-1;
+
+ strncpy( cur, p, len );
+ cur[len] = 0;
+ break;
+ }
+
+ return len;
+}
+
+//------------------------------------------------------------------------------
+// getProfileString:
+//------------------------------------------------------------------------------
+int GetPrivateProfileString( const char *section,
+ const char *entry,
+ const char *defaultString,
+ char *buffer,
+ int bufLen,
+ const char *fileName )
+{
+ FILE *is;
+ int len = -1;
+
+ is = fopen(fileName, "rt");
+
+ if( is && gotoSection( is, section ) )
+ len = readEntry(is, entry, buffer, bufLen, True);
+
+ if (len < 0) //can not read entry, use default string
+ {
+ strncpy( buffer, defaultString, bufLen-1 );
+ buffer[bufLen-1] = 0;
+ len = strlen(buffer);
+ }
+ if (is) fclose(is);
+ return len;
+}
+
+//----------------------------------------------------------------------------
+// getProfileInt:
+//----------------------------------------------------------------------------
+long GetPrivateProfileInt( const char *section,
+ const char *entry,
+ long defaultInt,
+ const char *fileName )
+{
+ char buf[256];
+ char iBuf[34]; //"34" is max space "_itoa" required under 32 bit C++
+
+ sprintf(iBuf, "%d", defaultInt);
+ GetPrivateProfileString( section, entry, iBuf, buf, 256, fileName );
+ return atol( buf );
+}
+
+static void writeEntry( FILE *os, const char *entry, const char *string )
+{
+ fprintf(os, "%s=%s\n", entry, string);
+}
+
+//------------------------------------------------------------------------------
+// writeProfileString:
+//------------------------------------------------------------------------------
+int WritePrivateProfileString( const char *section,
+ const char *entry,
+ const char *string,
+ const char *fileName )
+{
+ char path [8192] = {0};
+ char drive[256] = {0};
+ char dir [256] = {0};
+ char file [256] = {0};
+ char ext [256] = {0};
+ char buf [256] = {0};
+
+ int titleFound;
+
+ // work better on network!
+ _splitpath( path, drive, dir, file, ext );
+ _makepath( path, drive, dir, mkstemp("iniXXXXXX"), "" );
+
+ FILE *is = fopen(fileName, "rt");
+ FILE *os = fopen(path, "wt");
+
+ if(!is || !os || entry == 0) // maybe can not create file or invalid entry
+ {
+ if (is) fclose(is);
+ if (os) fclose(os);
+ return 0;
+ }
+
+ titleFound = False;
+ if (is)
+ {
+ while (fgets(buf, 256, is) != NULL)
+ {
+ fputs(buf, os);
+ if( containTitle(buf, section) )
+ {
+ titleFound = True;
+ break;
+ }
+ }
+ }
+
+ if (!titleFound) // add section
+ {
+ fprintf(os, "[%s]\n", section);
+ writeEntry( os, entry, string );
+ }
+ else
+ {
+ while (fgets(buf, 256, is) != NULL)
+ {
+ if (isTitleLine(buf)) // section ended, but still not found the entry
+ break;
+
+ if (textPos(buf, entry)) // entry found, so rewrite it
+ {
+ break;
+ }
+ fputs(buf, os);
+ }
+
+ writeEntry(os, entry, string);
+
+ if (is)
+ {
+ while(fgets(buf, 256, is) != NULL) // copy left lines
+ fputs(buf, os);
+ }
+ }
+ if (is) fclose(is);
+ if (os) fclose(os);
+ unlink(fileName);
+ rename(path, fileName);
+ return strlen(string);
+}
+
+#pragma warn .aus \ No newline at end of file
diff --git a/Src/Wasabi/bfc/util/profile.h b/Src/Wasabi/bfc/util/profile.h
new file mode 100644
index 00000000..9d0df724
--- /dev/null
+++ b/Src/Wasabi/bfc/util/profile.h
@@ -0,0 +1,26 @@
+//
+// profile.h
+// Profile support.
+// Programed by XuYiFeng 1995.4.25, All rights reserved.
+//
+
+#ifndef __PROFILE_H
+#define __PROFILE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+long GetPrivateProfileInt( const char *section, const char *entry, long defaultInt,
+ const char *fileName );
+int GetPrivateProfileString( const char *section, const char *entry,
+ const char *defaultString, char *buffer,
+ int bufLen, const char *fileName );
+int WritePrivateProfileString( const char *section, const char *entry,
+ const char *string, const char *fileName );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/Src/Wasabi/bfc/util/profiler.cpp b/Src/Wasabi/bfc/util/profiler.cpp
new file mode 100644
index 00000000..3871434f
--- /dev/null
+++ b/Src/Wasabi/bfc/util/profiler.cpp
@@ -0,0 +1,6 @@
+#include <precomp.h>
+#include "profiler.h"
+
+PtrListInsertSorted<__ProfilerEntry, __ProfilerEntrySort> __profiler_entries;
+
+int __profiler_indent;
diff --git a/Src/Wasabi/bfc/util/profiler.h b/Src/Wasabi/bfc/util/profiler.h
new file mode 100644
index 00000000..e7b71e81
--- /dev/null
+++ b/Src/Wasabi/bfc/util/profiler.h
@@ -0,0 +1,128 @@
+#ifndef _PROFILER_H
+#define _PROFILER_H
+
+#include <bfc/wasabi_std.h>
+#include <bfc/string/bfcstring.h>
+#include <bfc/ptrlist.h>
+
+
+#ifdef NO_PROFILING
+#define PR_ENTER(msg)
+#define PR_LEAVE()
+#else
+
+#define _PR_ENTER(msg, line) { __Profiler __prx##line(msg)
+#define _PR_ENTER2(msg, msg2, line) { __Profiler __prx##line(msg, msg2)
+#define PR_ENTER(msg) _PR_ENTER(msg, line)
+#define PR_ENTER2(msg, msg2) _PR_ENTER2(msg, msg2, line)
+#define PR_LEAVE() }
+
+class __ProfilerEntry {
+ public:
+ __ProfilerEntry(const char *txt) { text = txt; totaltime = 0; totaln = 0; subcount = 0; lastcps = -1;}
+ virtual ~__ProfilerEntry() {}
+
+ void add(float ms) { totaltime += ms; totaln++;
+ if (subcount == 0) {
+ firstcall = Wasabi::Std::getTimeStampMS();
+ }
+ if (Wasabi::Std::getTimeStampMS() - firstcall < 1) {
+ subcount++;
+ } else {
+ lastcps = subcount;
+ subcount = 0;
+ }
+ }
+ float getAverage() { if (totaln == 0) return 0; return totaltime / (float)totaln; }
+ float getTotal() { return totaltime; }
+ const char *getText() { return text; }
+ int getLastCPS() { return lastcps; }
+
+ private:
+ float totaltime;
+ int totaln;
+ stdtimevalms firstcall;
+ int lastcps;
+ int subcount;
+ String text;
+};
+
+class __ProfilerEntrySort {
+public:
+ static int compareAttrib(const wchar_t *attrib, void *item) {
+ return STRICMP((const char *)attrib, ((__ProfilerEntry*)item)->getText());
+ }
+ static int compareItem(void *i1, void *i2) {
+ return STRICMP(((__ProfilerEntry*)i1)->getText(), ((__ProfilerEntry*)i2)->getText());
+ }
+};
+
+extern COMEXP PtrListInsertSorted<__ProfilerEntry, __ProfilerEntrySort> __profiler_entries;
+extern COMEXP int __profiler_indent;
+
+class __ProfilerManager {
+ public:
+ static void log(const char *txt, float ms, float *total, float *average, int *lastcps) {
+ int pos=-1;
+ __ProfilerEntry *e = __profiler_entries.findItem((const wchar_t *)txt, &pos);
+ if (pos < 0 || e == NULL) {
+ e = new __ProfilerEntry(txt);
+ __profiler_entries.addItem(e);
+ }
+ if (e != NULL) {
+ e->add(ms);
+ if (total != NULL) *total = e->getTotal();
+ if (average != NULL) *average = e->getAverage();
+ if (lastcps != NULL) *lastcps = e->getLastCPS();
+ }
+ }
+};
+
+#undef USE_TICK_COUNT
+
+class __Profiler {
+public:
+ __Profiler(const char *text, const char *text2="") : str(text), str2(text2) {
+ if (!str2.isempty()) str2 += " ";
+#ifdef USE_TICK_COUNT
+ ts1 = GetTickCount();
+#else
+ ts1 = Wasabi::Std::getTimeStampMS();
+#endif
+ __profiler_indent++;
+ }
+ ~__Profiler() {
+ __profiler_indent--;
+#ifdef USE_TICK_COUNT
+ stdtimevalms ts2 = GetTickCount();
+#else
+ stdtimevalms ts2 = Wasabi::Std::getTimeStampMS();
+#endif
+ float ms = (float)((ts2 - ts1)
+#ifndef USE_TICK_COUNT
+*1000.0
+#endif
+);
+ float total=0;
+ float average=0;
+ int lastcps=0;
+ __ProfilerManager::log(str, ms, &total, &average, &lastcps);
+ char buf[4096];
+ if (lastcps >= 0)
+ sprintf(buf, "%*sProfiler: %s: %s%6.4f ms (total: %6.4f ms, average: %6.4f ms, calls per second : %d)\n", __profiler_indent*4, " ", str.getValue(), str2.getValue(), ms, total, average, lastcps);
+ else
+ sprintf(buf, "%*sProfiler: %s: %s%6.4f ms (total: %6.4f ms, average: %6.4f ms)\n", __profiler_indent*4, " ", str.getValue(), str2.getValue(), ms, total, average);
+#ifdef _WIN32
+ OutputDebugStringA(buf);
+#else
+#warning port me
+#endif
+ }
+private:
+ String str, str2;
+ stdtimevalms ts1;
+};
+
+#endif//!NO_PROFILING
+
+#endif
diff --git a/Src/Wasabi/bfc/util/timefmt.cpp b/Src/Wasabi/bfc/util/timefmt.cpp
new file mode 100644
index 00000000..f0968ac6
--- /dev/null
+++ b/Src/Wasabi/bfc/util/timefmt.cpp
@@ -0,0 +1,71 @@
+#include <precomp.h>
+#include <bfc/wasabi_std.h>
+#include <time.h>
+#include "timefmt.h"
+
+void TimeFmt::printMinSec(int sec, wchar_t *buf, int buflen)
+{
+ int minutes, seconds;
+ int negative = sec < 0;
+
+ if (buf == NULL) return;
+
+ if (sec == -1)
+ {
+ *buf = 0;
+ return;
+ }
+
+ seconds = sec % 60;
+ sec /= 60;
+ minutes = sec;
+
+ StringPrintfW sp(L"%s%d:%02d", (minutes == 0 && negative) ? L"-" : L"", minutes, ABS(seconds));
+ WCSCPYN(buf, sp, buflen);
+}
+
+void TimeFmt::printHourMinSec(int sec, wchar_t *buf, int buflen, int hoursonlyifneeded)
+{
+ int hours, minutes, seconds;
+ int negative = sec < 0;
+
+ sec = ABS(sec);
+ if (buf == NULL) return;
+
+ if (sec == -1) {
+ *buf = 0;
+ return;
+ }
+
+ hours = sec / 3600;
+ sec -= hours * 3600;
+ seconds = sec % 60;
+ sec /= 60;
+ minutes = sec;
+
+ StringW sp;
+ if (hoursonlyifneeded && hours == 0)
+ sp = StringPrintfW(L"%s%d:%02d", (minutes == 0 && negative) ? L"-" : L"", minutes, seconds);
+ else
+ sp = StringPrintfW(L"%s%d:%02d:%02d", (hours == 0 && negative) ? L"-" : L"", hours, minutes, seconds);
+
+ WCSCPYN(buf, sp, buflen);
+}
+
+void TimeFmt::printTimeStamp(wchar_t *buf, int bufsize, int ts)
+{
+ if (ts == 0)
+ {
+ WCSCPYN(buf, L"Never", bufsize); // FUCKO: load from lang pack
+ return;
+ }
+
+ struct tm *tm_now;
+ tm_now = localtime((const time_t *)&ts);
+ if (tm_now == NULL)
+ {
+ *buf = 0;
+ return;
+ }
+ wcsftime(buf, bufsize, L"%a %b %Y %d %I:%M:%S %p", tm_now);
+}
diff --git a/Src/Wasabi/bfc/util/timefmt.h b/Src/Wasabi/bfc/util/timefmt.h
new file mode 100644
index 00000000..b24e0a99
--- /dev/null
+++ b/Src/Wasabi/bfc/util/timefmt.h
@@ -0,0 +1,46 @@
+//PORTABLE
+#ifndef _TIMEFMT_H
+#define _TIMEFMT_H
+
+/**
+ Simple time formatting. Can format into a minutes:seconds style
+ display based on count in seconds only.
+
+ Can also format a timestamp into human readable format.
+
+ @author Nullsoft
+ @ver 1.0
+*/
+class TimeFmt {
+public:
+ /**
+ Formats a time value in seconds to minute:seconds.
+
+ If the buffer is too small, the string will be
+ truncated.
+
+ @param seconds Time value to convert.
+ @param buf Buffer to receive formatted string.
+ @param buflen Length of the buffer.
+ */
+ static void printMinSec(int seconds, wchar_t *buf, int buflen);
+ static void printHourMinSec(int seconds, wchar_t *buf, int buflen, int hoursonlyifneeded=0);
+
+ /**
+ Formats a time value (from unix timestamp) to
+ human readable format.
+
+ If the buffer is too small, the string will be
+ truncated.
+
+ Example of formatted output:
+ Tue Sep 10 18:34:42 PDT 2002
+
+ @param buf Buffer to receive the formatted string.
+ @param bufsize Length of the buffer.
+ @param ts The timestamp to use.
+ */
+ static void printTimeStamp(wchar_t *buf, int bufsize, int ts);
+};
+
+#endif