📄 ptypes_test.cxx
字号:
/*
*
* C++ Portable Types Library (PTypes)
* Version 1.8.3 Released 25-Aug-2003
*
* Copyright (c) 2001, 2002, 2003 Hovik Melikyan
*
* http://www.melikyan.com/ptypes/
* http://ptypes.sourceforge.net/
*
*/
#include <stdlib.h>
#include <stdio.h>
#include "pport.h"
#include "ptypes.h"
#include "pstreams.h"
#include "pinet.h"
#include "ptime.h"
#ifndef PTYPES_ST
#include "pasync.h"
#endif
USING_PTYPES
void showstr(const char* shouldbe, const char* is)
{
pout.putf("[%s] %s\n", shouldbe, is);
}
void showstr(const char* shouldbe, const string& is)
{
showstr(shouldbe, pconst(is));
}
void showhex(const char* shouldbe, const char* is, int islen)
{
string s;
int i;
for (i = 0; i < islen; i++)
s += itobase((unsigned char)is[i], 16, 2);
s = lowercase(s);
showstr(shouldbe, s);
}
void showint(int shouldbe, int is)
{
pout.putf("[%d] %d\n", shouldbe, is);
}
void showint(large shouldbe, large is)
{
pout.putf("[%lld] %lld\n", shouldbe, is);
}
void showchar(char shouldbe, char is)
{
pout.putf("[%c] %c\n", shouldbe, is);
}
//
// string test
//
void string_test1()
{
pout.put("\n--- STRING CLASS\n");
static char strbuf[10] = "STRING";
char c = 'A';
string s1 = "string";
s1 = s1;
s1 += s1;
del(s1, 6, 6);
string s2 = s1;
string s3;
string s4(strbuf, strlen(strbuf));
string s5 = 'A';
string s6 = c;
showstr("string", s1);
showstr(s1, s2);
showstr("", s3);
showstr("STRING", s4);
showint(6, length(s4));
showint(2, refcount(s1));
clear(s2);
showint(1, refcount(s1));
s2 = s1;
unique(s1);
showint(1, refcount(s1));
setlength(s1, 64);
string s7 = s1;
setlength(s1, 3);
showstr("str", s1);
showstr("strING", s1 += copy(s4, 3, 3));
del(s1, 3, 3);
showstr("str", s1);
ins("ing", s1, 0);
showstr("ingstr", s1);
s2 = "str" + s1 + "ing";
showstr("stringstring", s2);
s3 = s2;
s3 = "strungstrung";
s3 = s2;
s3 = "strung";
s2 = "str" + s1;
s2 = s1 + "str";
s2 += "str";
s2 = 's' + s1;
s2 = s1 + 's';
s2 += 's';
s2 = c + s1;
s2 = s1 + c;
s2 += c;
s2 = 'a';
s2 = c;
}
void string_test2()
{
pout.put("\n--- STRING CLASS\n");
string s1 = "ingstr";
string s2 = "stringstring";
string s4 = "STRING";
showint(1, pos('t', s2));
showint(2, pos("ri", s2));
showint(3, pos(s1, s2));
showint(1, contains("tr", s2, 1));
showint(0, contains("tr", s2, 2));
showint(1, s4 == "STRING");
showchar('R', s4[2]);
showstr("123456789", itostring(123456789));
showstr("123", itostring(char(123)));
showstr("-000123", itostring(-123, 10, 7, '0'));
showstr("0ABCDE", itostring(0xabcde, 16, 6));
showstr("-9223372036854775808", itostring(LARGE_MIN));
showstr("18446744073709551615", itostring(ULARGE_MAX));
showint(1234, (int)stringtoi("1234"));
showint(large(0x15AF), stringtoue("15AF", 16));
showint(LARGE_MAX, stringtoue("5zzzzzzzzzz", 64));
try
{
// out of range by 1
stringtoue("18446744073709551616", 10);
fatal(0xb0, "Conversion overflow not detected");
}
catch (econv* e)
{
showstr("Out of range: ...", e->get_message());
delete e;
}
showint(large(123), stringtoie("123"));
showint(large(-123), stringtoie("-123"));
showint(LARGE_MIN, stringtoie("-9223372036854775808"));
showint(LARGE_MAX, stringtoie("9223372036854775807"));
try
{
// out of range by 1
stringtoie("9223372036854775808");
fatal(0xb0, "Conversion overflow not detected");
}
catch (econv* e)
{
showstr("Out of range: ...", e->get_message());
delete e;
}
showstr("abcabc", lowercase(s1 = "aBCAbc"));
showstr("abcabc", lowercase(s1));
}
void string_benchmarks()
{
pout.put("\n--- STRING BENCHMARKS\n");
int i;
string s1 = "string";
string s2;
// for the first time we run the test to let the VM settle down and stop swapping
for (i = 0; i < 156000; i++)
s2 += s1;
// here is the actual test
clear(s2);
datetime start = now();
for (i = 0; i < 156000; i++)
s2 += s1;
datetime diff = now() - start;
pout.putf("Performance index compared to WinNT on P3/800MHz:\n%.3f\n", diff / 1000.0);
}
//
// cset test
//
void cset_test()
{
pout.put("\n--- CSET CLASS\n");
cset s1 = "~09~0a~0d~F0 A-Z~~";
cset s2 = "A-F";
char c = 'B';
showstr("~09~0a~0d A-Z~~~f0", asstring(s1));
s1 -= char(0xf0);
s1 -= cset("~00-~20");
showstr("A-Z~~", asstring(s1));
s1 -= s2;
showstr("G-Z~~", asstring(s1));
s1 += s2;
s1 += ' ';
showstr(" A-Z~~", asstring(s1));
showint(1, s2 == cset("A-F"));
showint(1, s2 <= s1);
s1 -= 'A';
s1 -= c;
showint(0, s2 <= s1);
s1 = s1 + char(0xf1);
showint(1, char(0xf1) & s1);
showint(0, char(0xf2) & s1);
}
//
// objlist
//
class known: public unknown {
public:
int value;
known(int ivalue): unknown(), value(ivalue) {}
virtual ~known() {}
};
typedef tobjlist<known> knownlist;
string ol_asstring(const knownlist& s) {
string ret = "{";
for (int i = 0; i < length(s); i++) {
if (i > 0)
concat(ret, ", ");
ret += itostring(s[i]->value);
}
concat(ret, '}');
return ret;
}
void objlist_test() {
pout.put("\n--- OBJLIST CLASS\n");
knownlist s1(true);
known* obj;
add(s1, new known(10));
ins(s1, 0, new known(5));
ins(s1, 2, obj = new known(20));
add(s1, new known(30));
add(s1, new known(40));
del(s1, 4);
del(s1, 1);
get(s1, 0);
showint(3, length(s1));
showint(1, indexof(s1, obj));
showstr("{5, 20, 30}", ol_asstring(s1));
clear(s1);
showstr("{}", ol_asstring(s1));
}
//
// strlist
//
typedef tstrlist<known> knownstrlist;
string sl_asstring(const knownstrlist& s) {
string ret = "{";
for (int i = 0; i < length(s); i++) {
if (i > 0)
concat(ret, ", ");
ret += getstr(s, i) + ":" + itostring(s[i]->value);
}
concat(ret, '}');
return ret;
}
void strlist_test() {
pout.put("\n--- STRLIST CLASS\n");
knownstrlist s1(SL_OWNOBJECTS);
known* obj;
add(s1, "ten", new known(10));
ins(s1, 0, "five", new known(5));
ins(s1, 2, "twenty", obj = new known(20));
add(s1, "thirty", new known(30));
add(s1, "forty", new known(40));
del(s1, 4);
del(s1, 1);
showint(3, length(s1));
showint(1, indexof(s1, obj));
showint(2, find(s1, "thirty"));
showint(2, find(s1, "THIRTY"));
showint(-1, find(s1, "forty"));
showstr("{five:5, twenty:20, thirty:30}", sl_asstring(s1));
knownstrlist s2(slflags(SL_OWNOBJECTS | SL_SORTED | SL_CASESENS));
add(s2, "five", new known(5));
add(s2, "ten", new known(10));
add(s2, "twenty", new known(20));
add(s2, "thirty", new known(30));
add(s2, "forty", new known(40));
showint(5, length(s2));
showint(3, find(s2, "thirty"));
showint(-1, find(s2, "THIRTY"));
showint(-1, find(s2, "hovik"));
showstr("{five:5, forty:40, ten:10, thirty:30, twenty:20}", sl_asstring(s2));
clear(s2);
showstr("{}", sl_asstring(s2));
strlist s3(slflags(SL_OWNOBJECTS | SL_SORTED | SL_DUPLICATES));
add(s3, "a", nil);
add(s3, "b", nil);
add(s3, "b", nil);
add(s3, "b", nil);
add(s3, "b", nil);
add(s3, "b", nil);
add(s3, "b", nil);
add(s3, "c", nil);
showint(1, find(s3, "b"));
}
void strmap_test() {
pout.put("\n--- STRMAP CLASS\n");
tstrmap<known> s(SL_OWNOBJECTS);
put(s, "five", new known(5));
put(s, "ten", new known(10));
put(s, "twenty", new known(20));
put(s, "thirty", new known(30));
put(s, "forty", new known(40));
showint(20, get(s, "twenty")->value);
showint(0, int(get(s, "hovik")));
showint(5, length(s));
put(s, "twenty", nil);
showint(4, length(s));
}
//
// textmap
//
void textmap_test()
{
pout.put("\n--- TEXTMAP CLASS\n");
textmap c;
put(c, "name1", "value1");
put(c, "name2", "value2");
put(c, "name1", "value3");
put(c, "name2", "");
showint(1, length(c));
showstr("value3", get(c, "name1"));
showstr("", get(c, "name2"));
}
//
// streams
//
char buf1[] = "This is a test.";
char buf2[] = "The file should contain readable human text. :)";
const char* fname = "stmtest.txt";
void outfile_test()
{
pout.put("\n--- OUTFILE CLASS\n");
outfile f(fname, false);
f.set_umode(0600);
f.set_bufsize(3);
f.open();
f.put(buf1[0]);
f.put(buf1[1]);
f.put("is is a test.");
f.puteol();
f.close();
f.set_append(true);
f.open();
f.write(buf2, strlen(buf2));
f.puteol();
f.close();
pnull.put("This should go to nowhere I");
pnull.put("This should go to nowhere II");
}
void infile_test()
{
pout.put("\n--- INFILE CLASS\n");
infile f(fname);
f.set_bufsize(3);
char temp[4];
f.open();
pout.putf("%c", f.get());
pout.putf("%s\n", pconst(f.line()));
f.read(temp, sizeof temp - 1);
temp[sizeof temp - 1] = 0;
pout.putf("%s", temp);
f.get();
f.putback();
pout.putf("%s", pconst(f.token(cset("~20-~FF"))));
f.preview();
if (f.get_eol())
{
f.skipline();
pout.put("\n");
}
if (f.get_eof())
pout.put("EOF\n");
// f.error(1, "Test error message");
}
void mem_test()
{
pout.put("\n--- OUT/IN MEMORY CLASS\n");
outmemory m(12, 5);
m.open();
m.put("Memory");
m.put(" c");
m.put("lass is working");
string s(m.get_data(), m.tell());
showstr("Memory class", s);
}
#ifndef PTYPES_ST
//
// multithreading
//
//
// rwlock test
//
const int rw_max_threads = 30;
const int rw_max_tries = 30;
const int rw_max_delay = 20;
const int rw_rw_ratio = 5;
const bool rw_swap = false;
class rwthread: public thread
{
protected:
virtual void execute();
public:
rwthread(): thread(false) {}
virtual ~rwthread() { waitfor(); }
};
rwlock rw;
int reader_cnt = 0;
int writer_cnt = 0;
int total_writers = 0;
int total_readers = 0;
int max_readers = 0;
int prand(int max)
{
return rand() % max;
}
void rwthread::execute()
{
for(int i = 0; i < rw_max_tries; i++)
{
psleep(prand(rw_max_delay));
bool writer = prand(rw_rw_ratio) == 0;
if (writer ^ rw_swap)
{
rw.wrlock();
pout.put('w');
if (pincrement(&writer_cnt) > 1)
fatal(0xa0, "Writer: Huh?! Writers in here?");
pincrement(&total_writers);
}
else
{
rw.rdlock();
pout.put('.');
int t;
if ((t = pincrement(&reader_cnt)) > max_readers)
max_readers = t;
if (writer_cnt > 0)
fatal(0xa1, "Reader: Huh?! Writers in here?");
pincrement(&total_readers);
}
psleep(prand(rw_max_delay));
if (writer ^ rw_swap)
pdecrement(&writer_cnt);
else
pdecrement(&reader_cnt);
rw.unlock();
}
}
void rwlock_test()
{
// #ifdef __PTYPES_RWLOCK__
pout.put("\n--- RWLOCK\n");
rwthread* threads[rw_max_threads];
srand((unsigned)time(0));
int i;
for(i = 0; i < rw_max_threads; i++)
{
threads[i] = new rwthread();
threads[i]->start();
}
for(i = 0; i < rw_max_threads; i++)
delete threads[i];
pout.putf("\nmax readers: %d\n", max_readers);
pout.putline("do writers 'starve'?");
// #endif
}
const int MSG_DIAG = MSG_USER + 1;
//
// class diagmessage
//
class diagmessage: public message
{
protected:
string module;
string diagstr;
friend class diagthread;
public:
diagmessage(string imodule, string idiagstr)
: message(MSG_DIAG), module(imodule),
diagstr(idiagstr) {}
};
//
// class diagthread
//
class diagthread: public thread, protected msgqueue
{
protected:
virtual void execute(); // override thread::execute()
virtual void cleanup(); // override thread::cleanup()
virtual void msghandler(message& msg); // override msgqueue::msghandler()
public:
diagthread(): thread(false), msgqueue() { }
void postdiag(string module, string diagstr);
void postquit();
};
void diagthread::postdiag(string module, string diagstr)
{
msgqueue::post(new diagmessage(module, diagstr));
}
void diagthread::postquit()
{
msgqueue::post(MSG_QUIT);
}
void diagthread::execute()
{
// starts message queue processing; calls
// msghandler for each message
msgqueue::run();
}
void diagthread::cleanup()
{
}
void diagthread::msghandler(message& msg)
{
switch (msg.id)
{
case MSG_DIAG:
pout.putf("%s: %s\n", pconst(((diagmessage&)msg).module), pconst(((diagmessage&)msg).diagstr));
break;
default:
defhandler(msg);
}
}
//
// class testthread
//
class testthread: public thread
{
protected:
diagthread* diag;
string myname;
virtual void execute();
virtual void cleanup();
public:
semaphore sem;
tsemaphore tsem;
testthread(diagthread* idiag)
: thread(false), diag(idiag), myname("testthread"), sem(0), tsem(0) {}
};
void testthread::execute()
{
diag->postdiag(myname, "starts and enters sleep for 1 second");
psleep(1000);
diag->postdiag(myname, "signals the timed semaphore");
tsem.post();
diag->postdiag(myname, "releases the simple semaphore");
sem.post();
diag->postdiag(myname, "enters sleep for 1 more second");
psleep(1000);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -