AXCEL C++ Framework
Elegance through abstraction
|
00001 00004 #include "axcel.h" 00005 00006 namespace axcel { 00007 00008 /* 00009 string net::dns::addrs(const char* lookup) { 00010 #ifdef _WIN32 00011 WSADATA wd; 00012 WSAStartup(MAKEWORD(2, 0), &wd); 00013 #endif 00014 string s; 00015 char buf[48]; 00016 struct addrinfo *ai, *ent; 00017 if (getaddrinfo(lookup, 0, 0, &ai)) 00018 return s; 00019 for (ent = ai; ent; ent = ent->ai_next) { 00020 if (ent->ai_family == AF_INET) 00021 s += inet_ntop(AF_INET, &((struct sockaddr_in*)ent->ai_addr)->sin_addr, buf, 48); 00022 else if (ent->ai_family == AF_INET6) 00023 s += inet_ntop(AF_INET6, &((struct sockaddr_in6*)ent->ai_addr)->sin6_addr, buf, 48); 00024 s += "\n"; 00025 } 00026 freeaddrinfo(ai); 00027 #ifdef _WIN32 00028 WSACleanup(); 00029 #endif 00030 return s; 00031 }*/ 00032 string io::ios::type() { return string("io::ios"); } 00033 io::ios::operator string () { return string(); } 00034 io::ios& io::ios::operator<< (object& o) { this->output::operator<<(o); return *this; } 00035 io::ios& io::ios::operator<< (bool val) { this->output::operator<<(val); return *this; } 00036 io::ios& io::ios::operator<< (short val) { this->output::operator<<(val); return *this; } 00037 io::ios& io::ios::operator<< (unsigned short val) { this->output::operator<<(val); return *this; } 00038 io::ios& io::ios::operator<< (int val) { this->output::operator<<(val); return *this; } 00039 io::ios& io::ios::operator<< (unsigned int val) { this->output::operator<<(val); return *this; } 00040 io::ios& io::ios::operator<< (long val) { this->output::operator<<(val); return *this; } 00041 io::ios& io::ios::operator<< (unsigned long val) { this->output::operator<<(val); return *this; } 00042 io::ios& io::ios::operator<< (float val) { this->output::operator<<(val); return *this; } 00043 io::ios& io::ios::operator<< (double val) { this->output::operator<<(val); return *this; } 00044 io::ios& io::ios::operator<< (long double val) { this->output::operator<<(val); return *this; } 00045 io::ios& io::ios::operator<< (const void* val) { this->output::operator<<(val); return *this; } 00046 io::ios& io::ios::operator<< (char c) { this->output::operator<<(c); return *this; } 00047 io::ios& io::ios::operator<< (signed char c) { this->output::operator<<(c); return *this; } 00048 io::ios& io::ios::operator<< (unsigned char c) { this->output::operator<<(c); return *this; } 00049 io::ios& io::ios::operator<< (const char* s) { this->output::operator<<(s); return *this; } 00050 io::ios& io::ios::operator<< (string s) { this->output::operator<<(s); return *this; } 00051 io::ios& io::ios::put(object& o) { this->output::put(o); return *this; } 00052 io::ios& io::ios::put(string s) { this->output::put(s); return *this; } 00053 io::ios& io::ios::echo(object& o) { this->output::echo(o); return *this; } 00054 io::ios& io::ios::echo(string s) { this->output::echo(s); return *this; } 00055 io::ios& io::ios::put(bool val) { this->output::put(val); return *this; } 00056 io::ios& io::ios::put(short val) { this->output::put(val); return *this; } 00057 io::ios& io::ios::put(unsigned short val) { this->output::put(val); return *this; } 00058 io::ios& io::ios::put(int val) { this->output::put(val); return *this; } 00059 io::ios& io::ios::put(long val) { this->output::put(val); return *this; } 00060 io::ios& io::ios::put(unsigned long val) { this->output::put(val); return *this; } 00061 io::ios& io::ios::put(float val) { this->output::put(val); return *this; } 00062 io::ios& io::ios::put(double val) { this->output::put(val); return *this; } 00063 io::ios& io::ios::put(long double val) { this->output::put(val); return *this; } 00064 io::ios& io::ios::put(const void* val) { this->output::put(val); return *this; } 00065 io::ios& io::ios::put(char c) { this->output::put(c); return *this; } 00066 io::ios& io::ios::put(signed char c) { this->output::put(c); return *this; } 00067 io::ios& io::ios::put(unsigned char c) { this->output::put(c); return *this; } 00068 io::ios& io::ios::put(const char* s) { this->output::put(s); return *this; } 00069 io::ios& io::ios::echo() { this->output::echo(); return *this; } 00070 io::ios& io::ios::echo(bool val) { this->output::echo(val); return *this; } 00071 io::ios& io::ios::echo(short val) { this->output::echo(val); return *this; } 00072 io::ios& io::ios::echo(unsigned short val) { this->output::echo(val); return *this; } 00073 io::ios& io::ios::echo(int val) { this->output::echo(val); return *this; } 00074 io::ios& io::ios::echo(size_t val) { this->output::echo(val); return *this; } 00075 io::ios& io::ios::echo(long val) { this->output::echo(val); return *this; } 00076 io::ios& io::ios::echo(unsigned long val) { this->output::echo(val); return *this; } 00077 io::ios& io::ios::echo(float val) { this->output::echo(val); return *this; } 00078 io::ios& io::ios::echo(double val) { this->output::echo(val); return *this; } 00079 io::ios& io::ios::echo(long double val) { this->output::echo(val); return *this; } 00080 io::ios& io::ios::echo(const void* val) { this->output::echo(val); return *this; } 00081 io::ios& io::ios::echo(char c) { this->output::echo(c); return *this; } 00082 io::ios& io::ios::echo(signed char c) { this->output::echo(c); return *this; } 00083 io::ios& io::ios::echo(unsigned char c) { this->output::echo(c); return *this; } 00084 io::ios& io::ios::echo(const char* s) { this->output::echo(s); return *this; } 00085 io::ios& io::ios::operator>> (bool& val) { this->input::operator>>(val); return *this; } 00086 io::ios& io::ios::operator>> (short& val) { this->input::operator>>(val); return *this; } 00087 io::ios& io::ios::operator>> (unsigned short& val) { this->input::operator>>(val); return *this; } 00088 io::ios& io::ios::operator>> (int& val) { this->input::operator>>(val); return *this; } 00089 io::ios& io::ios::operator>> (unsigned int& val) { this->input::operator>>(val); return *this; } 00090 io::ios& io::ios::operator>> (long& val) { this->input::operator>>(val); return *this; } 00091 io::ios& io::ios::operator>> (unsigned long& val) { this->input::operator>>(val); return *this; } 00092 io::ios& io::ios::operator>> (long long& val) { this->input::operator>>(val); return *this; } 00093 io::ios& io::ios::operator>> (unsigned long long& val) { this->input::operator>>(val); return *this; } 00094 io::ios& io::ios::operator>> (float& val) { this->input::operator>>(val); return *this; } 00095 io::ios& io::ios::operator>> (double& val) { this->input::operator>>(val); return *this; } 00096 io::ios& io::ios::operator>> (long double& val) { this->input::operator>>(val); return *this; } 00097 io::ios& io::ios::operator>> (void*& val) { this->input::operator>>(val); return *this; } 00098 io::ios& io::ios::operator>> (char& c) { this->input::operator>>(c); return *this; } 00099 io::ios& io::ios::operator>> (char* s) { this->input::operator>>(s); return *this; } 00100 io::ios& io::ios::operator>> (string& s) { this->input::operator>>(s); return *this; } 00101 00102 struct errno_str errno_strs[] = { 00103 {0, "unknown error"}, 00104 {EPERM, "operation not permitted"}, 00105 {ENOENT, "no such file or directory"}, 00106 {ESRCH, "no such process"}, 00107 {EINTR, "interrupted function call"}, 00108 {EIO, "input/output error"}, 00109 {ENXIO, "no such device or address"}, 00110 {E2BIG, "argument list too long"}, 00111 {ENOEXEC, "exec format error"}, 00112 {EBADF, "bad file descriptor"}, 00113 {ECHILD, "no child process"}, 00114 {EAGAIN, "resource temporarily unavailable"}, 00115 {ENOMEM, "not enough space"}, 00116 {EACCES, "permission denied"}, 00117 {EFAULT, "bad address"}, 00118 {EBUSY, "device or resource busy"}, 00119 {EEXIST, "file exists"}, 00120 {EXDEV, "improper link"}, 00121 {ENODEV, "no such device"}, 00122 {ENOTDIR, "not a directory"}, 00123 {EISDIR, "is a directory"}, 00124 {ENFILE, "too many open files in system"}, 00125 {EMFILE, "too many open files"}, 00126 {ENOTTY, "inappropriate i/o control operation"}, 00127 {EFBIG, "file too large"}, 00128 {ENOSPC, "no space left on device"}, 00129 {ESPIPE, "invalid seek"}, 00130 {EROFS, "read-only file system"}, 00131 {EMLINK, "too many links"}, 00132 {EPIPE, "broken pipe"}, 00133 {EDOM, "mathematics argument out of domain of function"}, 00134 {EDEADLK, "resource deadlock avoided"}, 00135 {ENAMETOOLONG, "filename too long"}, 00136 {ENOLCK, "no locks available"}, 00137 {ENOSYS, "function not implemented"}, 00138 {ENOTEMPTY, "directory not empty"}, 00139 {EINVAL, "invalid argument"}, 00140 {ERANGE, "result too large"}, 00141 {EILSEQ, "illegal byte sequence"}, 00142 {EADDRINUSE, "address already in use"}, 00143 {EADDRNOTAVAIL, "address not available"}, 00144 {EAFNOSUPPORT, "address family not supported"}, 00145 {EALREADY, "connection already in progress"}, 00146 {EBADMSG, "bad message"}, 00147 {ECANCELED, "operation canceled"}, 00148 {ECONNABORTED, "connection aborted"}, 00149 {ECONNREFUSED, "connection refused"}, 00150 {ECONNRESET, "connection reset"}, 00151 {EDESTADDRREQ, "destination address required"}, 00152 {EHOSTUNREACH, "host is unreachable"}, 00153 {EIDRM, "identifier removed"}, 00154 {EINPROGRESS, "operation in progress"}, 00155 {EISCONN, "socket is connected"}, 00156 {ELOOP, "too many levels of symbolic links"}, 00157 {EMSGSIZE, "message too long"}, 00158 {ENETDOWN, "network is down"}, 00159 {ENETRESET, "connection aborted by network"}, 00160 {ENETUNREACH, "network unreachable"}, 00161 {ENOBUFS, "no buffer space available"}, 00162 {ENODATA, "no message is available"}, 00163 {ENOLINK, "link has been severed"}, 00164 {ENOMSG, "no message of the desired type"}, 00165 {ENOPROTOOPT, "protocol not available"}, 00166 {ENOSR, "no stream resources"}, 00167 {ENOSTR, "not a stream"}, 00168 {ENOTCONN, "the socket is not connected"}, 00169 {ENOTRECOVERABLE, "state not recoverable"}, 00170 {ENOTSOCK, "not a socket"}, 00171 {ENOTSUP, "operation not supported"}, 00172 {EOVERFLOW, "value too large too be stored in datatype"}, 00173 {EOWNERDEAD, "owner died"}, 00174 {EPROTO, "protocol error"}, 00175 {EPROTONOSUPPORT, "protocol not supported"}, 00176 {EPROTOTYPE, "protocol wrong type for socket"}, 00177 {ETIME, "timer expired"}, 00178 {ETIMEDOUT, "connection timed out"}, 00179 {ETXTBSY, "text file busy"}, 00180 {0, 0} 00181 }; 00182 00183 exception::exception() { no = 0; } 00184 exception::exception(int number) { no = number; } 00185 exception::exception(const exception& e) { no = e.no; desc = e.desc; } 00186 exception::exception(const char* msg) { this->operator=(msg); } 00187 string exception::type() { return string("exception"); } 00188 exception& exception::operator= (int number) { no = number; return *this; } 00189 exception& exception::operator= (const exception e) { no = e.no; desc = e.desc; return *this; } 00190 exception& exception::operator= (const char* msg) { 00191 register int i; 00192 for (i = 0; errno_strs[i].str; i++) 00193 if (!strcmp(errno_strs[i].str, msg)) { no = errno_strs[i].no; return *this; } 00194 no = 0; 00195 return *this; 00196 } 00197 exception::operator string() { 00198 register int i; 00199 for (i = 0; errno_strs[i].str; i++) 00200 if (no == errno_strs[i].no) return string(errno_strs[i].str); 00201 return string("unknown error"); 00202 } 00203 exception object::error() { return exception(errnum); } 00204 bool exception::operator== (exception e) { return no == e.no; } 00205 bool exception::operator== (const char* s) { return this->operator string() == s; } 00206 bool exception::operator== (int num) { return no == num; } 00207 bool exception::operator!= (exception e) { return no != e.no; } 00208 bool exception::operator!= (const char* s) { return this->operator string() != s; } 00209 bool exception::operator!= (int num) { return no != num; } 00210 00211 char* strcpy2(char* s1, const char* s2) { 00212 if (s2 == NULL) return s1; 00213 return strcpy(s1, s2); 00214 } 00215 00216 char* strncpy2(char* s1, const char* s2, size_t n) { 00217 if (s2 == NULL) return s1; 00218 return strncpy(s1, s2, n); 00219 } 00220 00221 data console::dump() { 00222 data d; 00223 char c; 00224 do { c = this->getche(); d << c; } while (c); 00225 //while (this->kbhit()) d << this->getche(); 00226 return d; 00227 } 00228 00229 string fs::tmpnam() { 00230 string s; 00231 s.realloc(256); 00232 ::tmpnam(s.buf); 00233 return s; 00234 } 00235 00236 data& data::operator= (const char* s) { 00237 if (buf) free(buf); 00238 rewind(); 00239 realloc(strlen(s) + 1); 00240 strcpy(buf, s); 00241 return *this; 00242 } 00243 data& data::operator= (object& o) { 00244 if (buf) free(buf); 00245 rewind(); 00246 realloc(((string)o).len() + 1); 00247 string q = (string)o; 00248 strcpy(buf, q.buf); 00249 return *this; 00250 } 00251 00252 //object::operator const char* () { static string cstrbuf = this->operator string (); return cstrbuf.buf; } 00253 string io::iofmt::type() { return string("io::iofmt"); } 00254 string io::iob::type() { return string("io::iob"); } 00255 string io::input::type() { return string("io::input"); } 00256 string io::output::type() { return string("io::output"); } 00257 string fs::file::type() { return string("fs::file"); } 00258 string net::socket::tcp::type() { return string("net::socket::tcp"); } 00259 string string::type() { return string("string"); } 00260 string console::type() { return string("console"); } 00261 string timer::type() { return string("timer"); } 00262 string proc::thread::type() { return string("proc::thread"); } 00263 string proc::library::type() { return string("proc::library"); } 00264 string net::irc::msg::type() { return string("net::irc::msg"); } 00265 string proc::mutex::type() { return string("proc::mutex"); } 00266 string proc::semaphore::type() { return string("proc::semaphore"); } 00267 net::irc::msg::operator string () { return buf; } 00268 00269 io::iofmt::operator string () { 00270 string s; 00271 s.printf("%d", width); 00272 return s; 00273 } 00274 io::iob::operator string () { 00275 string s; 00276 if (ok()) s = "ok"; 00277 else if (hurt()) s = "hurt"; 00278 else if (dead()) s = "dead"; 00279 else if (eof()) s = "eof"; 00280 return s; 00281 } 00282 00283 fs::file::operator string () { return filename; } 00284 net::socket::tcp::operator string () { return ip(); } 00285 string::operator string () { return *this; } 00286 console::operator string () { string s; s.printf("io::input: %d io::output: %d", ::fileno(in), ::fileno(out)); return s; } 00287 timer::operator string () { return str(); } 00288 proc::thread::operator string () { string s; s.printf("%ld", tid); return s; } 00289 proc::library::operator string () { return libraryname; } 00290 proc::mutex::operator string () { string s; s.printf("%ld", id); return s; } 00291 proc::semaphore::operator string () { string s; s.printf("%ld", id); return s; } 00292 00300 io::output& io::output::operator<< (object& o) { this->operator<< (((string)o).buf); return *this; } 00301 00309 io::output& io::output::put(object& o) { return this->operator<<(((string)o).buf); } 00310 00319 io::output& io::output::echo(object& o) { this->operator<<(((string)o).buf); this->operator<<('\n'); return *this; } 00320 //io::output& io::output::operator<< (string s) { this->operator<< (s.buf); return *this; } 00321 io::output& io::output::put(string s) { return this->operator<<(s.buf); } 00322 io::output& io::output::echo(string s) { this->operator<<(s.buf); this->operator<<('\n'); return *this; } 00323 00324 io::iofmt::iofmt() { 00325 lfmt = 0; 00326 dec(1); 00327 ltrim(1); 00328 width = 0; 00329 precis = 0; 00330 ltrim(1); 00331 } 00332 00333 bool io::iofmt::gsbit(int i, long j) { 00334 if (i == -1) return lfmt & j; 00335 else if (i) lfmt |= j; 00336 else lfmt &= ~j; 00337 return i; 00338 } 00339 00340 //bool io::iofmt::num(int i) { return gsbit(i, 1); } 00341 00342 00351 bool io::iofmt::bin(int i) { return gsbit(i, 1); } 00352 00361 bool io::iofmt::btoa(int i) { return gsbit(i, 1 << 1); } 00362 00376 bool io::iofmt::base(int i) { return gsbit(i, 1 << 2); } 00377 00388 bool io::iofmt::zpad(int i) { return gsbit(i, 1 << 3); } 00389 00400 bool io::iofmt::sign(int i) { return gsbit(i, 1 << 4); } 00401 00411 bool io::iofmt::deaf(int i) { return gsbit(i, 1 << 5); } 00412 00421 bool io::iofmt::dec(int i) { if (i == 1) { lfmt &= ~(1 << 7); lfmt &= ~(1 << 8); }return gsbit(i, 1 << 6); } 00422 00431 bool io::iofmt::hex(int i) { if (i == 1) { lfmt &= ~(1 << 6); lfmt &= ~(1 << 8); } return gsbit(i, 1 << 7); } 00432 00441 bool io::iofmt::oct(int i) { if (i == 1) { lfmt &= ~(1 << 6); lfmt &= ~(1 << 7); } return gsbit(i, 1 << 8); } 00442 00451 bool io::iofmt::ltrim(int i) { return gsbit(i, 1 << 9); } 00452 00461 bool io::iofmt::endnl(int i) { return gsbit(i, 1 << 10); } 00462 00474 bool io::iofmt::left(int i) { return gsbit(i, 1 << 11); } 00475 00486 bool io::iofmt::right(int i) { return left(0); } 00487 00498 bool io::iofmt::fix(int i) { if (i == 1) lfmt &= ~(1 << 13); return gsbit(i, 1 << 12); } 00499 00512 bool io::iofmt::sci(int i) { if (i == 1) lfmt &= ~(1 << 12); return gsbit(i, 1 << 13); } 00513 00517 bool io::iob::ok() { return istat & 1; } 00518 00522 bool io::iob::hurt() { return istat & (1 << 1); } 00523 00527 bool io::iob::dead() { return istat & (1 << 2); } 00528 00533 bool io::iob::eof() { return istat & (1 << 3); } 00534 00539 void io::iob::heal() { istat = 1; } 00540 00546 void io::iob::hit() { istat = 1 << 1; } 00547 00553 void io::iob::kill() { istat = 1 << 2; } 00554 00560 void io::iob::drain() { istat = 1 << 3; } 00561 00572 char* io::input::gets(char* s, int size) { 00573 register int c; 00574 for (c = getc(); size ? size > 0 : 1; c = getc(), s++) { 00575 switch (c) { 00576 case EOF: *s = 0; s = NULL; break; 00577 case '\n': *s = '\n'; *(++s) = 0; return s; 00578 default: *s = c; 00579 } 00580 if (size) size--; 00581 } 00582 if (s) *s = 0; 00583 return s; 00584 } 00585 00586 /*Charp io::input::gets(int size) { 00587 Charp s; 00588 int i = 32, j = 0; 00589 register int c; 00590 s.ptr = (char*)malloc(i); 00591 s.free = true; 00592 for (c = getc(); ; c = getc(), j++) { 00593 if (size) if (j >= size) break; 00594 if (j >= i - 4) { i *= 2; s.ptr = (char*)realloc(s, i); } 00595 switch (c) { 00596 case EOF: s.ptr[0] = 0; return s; 00597 case '\n': s.ptr[j] = '\n'; s.ptr[++j] = 0; return s; 00598 default: s.ptr[j] = c; 00599 } 00600 } 00601 s.ptr[j] = 0; 00602 return s; 00603 }*/ 00604 00615 size_t io::input::read(char* ptr, size_t size, size_t nmemb) { 00616 register int c; 00617 size_t i, j; 00618 for (i = 0; i < nmemb; i++) 00619 for (j = 0; j < size; j++) { 00620 c = getc(); 00621 if (!ok()) return i; 00622 else ptr[size * i + j] = c; 00623 } 00624 return i; 00625 } 00626 00696 int io::input::scanf(const char* format, ...) { 00697 int \ 00698 matched = 0, //Number of matched tokens 00699 mods, //Conversion modifier flags 00700 base; //for numeric base 00701 size_t i; //a loopy thing 00702 size_t width; //field width 00703 register int last; //Char accumulator 00704 bool \ 00705 sign, //signed or unsigned flag 00706 ate = false; //leftover character input from last token? 00707 const char* cp; 00708 std::deque<unsigned char> b; //THE BUFFER 00709 char* tomato; 00710 va_list v; //... 00711 //modifier flags 00712 enum { 00713 unclog = 1, //Flush stream after reading? 00714 discard = 1 << 1, //Discard input 00715 mb = 1 << 2, //byte 00716 mh = 1 << 3, //half 00717 mw = 1 << 4, //word 00718 ml = 1 << 5, //long 00719 addws = 1 << 6, //do not discard leading whitespace? 00720 dienl = 1 << 7 //End input on newline? 00721 }; 00722 //flush an existing tied stream 00723 //if (knot) knot->flush(); 00724 va_start(v, format); 00725 //Loop through format string 00726 for (; *format; format++) { 00727 mods = 0; 00728 width = 0; 00729 b.clear(); 00730 if (*format == '%') { 00731 format++; 00732 for (; !isdigit(*format) && !isalpha(*format); format++) { 00733 switch (*format) { 00734 case '*': mods |= discard; break; 00735 case '^': mods |= addws; break; 00736 case '$': mods |= dienl; break; 00737 case '%': 00738 if (!ate) if ((last = getc()) == EOF) goto in_scanf_end; 00739 if (last != '%') { hit(); goto in_scanf_end; } 00740 ate = false; 00741 continue; 00742 } 00743 } 00744 if (isdigit(*format)) width = stoi<int>(format, 10); 00745 while (isdigit(*format)) format++; 00746 if (strpbrk(format, "bhwl") == format) { 00747 switch (format[0]) { 00748 case 'b': mods |= mb; break; 00749 case 'h': mods |= mh; break; 00750 case 'w': mods |= mw; break; 00751 case 'l': mods |= ml; break; 00752 } 00753 format++; 00754 } 00755 if (strpbrk(format, "DOXIdoxi") == format) { 00756 if (!ate) if ((last = getc()) == EOF) goto in_scanf_end; 00757 if (!(mods & addws)) 00758 for (; isspace(last); ) 00759 if ((last = getc()) == EOF) goto in_scanf_end; 00760 if (last == EOF) goto in_scanf_end; 00761 else b.push_back(last); 00762 if ((last == '+' || last == '-')) 00763 if (isupper(*format)) { 00764 hurt(); goto in_scanf_end; 00765 } else if ((last = getc()) == EOF) { goto in_scanf_end; 00766 } else { b.push_back(last); } 00767 00768 if (last == '0') {; 00769 if ((last = getc()) == EOF) goto in_scanf_end; 00770 else b.push_back(last); 00771 if ((last = 'x' || last == 'X') && (strpbrk(format, "XxIi") != format)) { 00772 hit(); goto in_scanf_end; 00773 } else if (strpbrk(format, "OoIi") != format) { 00774 hit(); goto in_scanf_end; 00775 } 00776 } 00777 for (;;) { 00778 if ((last = getc()) == EOF) break; 00779 if (!(mods & dienl)) 00780 if (!(islower(*format) == 'x' ? isxdigit(last) : isdigit(last))) 00781 break; 00782 if (last == '\n') break; 00783 b.push_back(last); 00784 if (width) if (b.size() == width) break; 00785 } 00786 ate = true; 00787 if (mods & discard) break; 00788 //null terminate string! 00789 b.push_back(0); 00790 //Get numeric base 00791 switch (*format) { 00792 case 'D': case 'd': base = 10; break; 00793 case 'O': case 'o': base = 8; break; 00794 case 'X': case 'x': base = 16; break; 00795 case 'I': case 'i': base = 0; break; 00796 } 00797 //Apply modifiers and convert to number 00798 if (mods & mb) { 00799 if (isupper(*format)) 00800 *(va_arg(v, unsigned char*)) = stoi<unsigned char>((char*)&(b[0]), base); 00801 else 00802 *(va_arg(v, signed char*)) = stoi<signed char>((char*)&(b[0]), base); 00803 } else if (mods & mh) { 00804 if (isupper(*format)) 00805 *(va_arg(v, unsigned short*)) = stoi<unsigned short>((char*)&(b[0]), base); 00806 else 00807 *(va_arg(v, signed short*)) = stoi<signed short>((char*)&(b[0]), base); 00808 } else if (mods & mw) { 00809 if (isupper(*format)) 00810 *(va_arg(v, unsigned long*)) = stoi<unsigned long>((char*)&(b[0]), base); 00811 else 00812 *(va_arg(v, signed long*)) = stoi<signed long>((char*)&(b[0]), base); 00813 } else if (mods & ml) { 00814 if (isupper(*format)) 00815 *(va_arg(v, unsigned long long*)) = stoi<unsigned long long>((char*)&(b[0]), base); 00816 else 00817 *(va_arg(v, signed long long*)) = stoi<signed long long>((char*)&(b[0]), base); 00818 } else { 00819 if (isupper(*format)) 00820 *(va_arg(v, unsigned int*)) = stoi<unsigned int>((char*)&(b[0]), base); 00821 else 00822 *(va_arg(v, signed int*)) = stoi<signed int>((char*)&(b[0]), base); 00823 } 00824 } else if (*format == 'c') { 00825 if (!ate) last = getc(); 00826 if (!(mods & addws)) 00827 for (; isspace(last); last = getc()) 00828 if (last == EOF) goto in_scanf_end; 00829 if (last != EOF) b.push_back(last); 00830 else goto in_scanf_end; 00831 if (!width) width = 1; 00832 for (i = 1; ; i++) { 00833 if (!(mods & dienl)) if (i == width) break; 00834 if (last == EOF) goto in_scanf_end; 00835 if (last == '\n') break; 00836 b.push_back(last); 00837 last = getc(); 00838 } 00839 if (!(mods & discard)) { 00840 tomato = va_arg(v, char*); 00841 for (; !b.empty(); b.pop_front(), tomato++) 00842 *tomato = b.front(); 00843 } 00844 ate = false; 00845 } else if (*format == 's') { 00846 if (!ate) if ((last = getc()) == EOF) 00847 goto in_scanf_end; 00848 if (!(mods & addws)) { 00849 for (; isspace(last); last = getc()) 00850 if (last == EOF) goto in_scanf_end; 00851 } else { 00852 for (; isspace(last); last = getc()) 00853 if (last == EOF) goto in_scanf_end; 00854 else b.push_back(last); 00855 } 00856 for (i = 1; ; i++) { 00857 if (last == EOF) break; 00858 if (!(mods & dienl)) { 00859 if (isspace(last)) { ate = false; break; } 00860 } else if (last == '\n') { ate = false; break; } 00861 if (width) if (i == width) { ate = true; break; } 00862 b.push_back(last); 00863 last = getc(); 00864 } 00865 b.push_back(0); 00866 if (mods & discard) continue; 00867 tomato = va_arg(v, char*); 00868 for (; !b.empty(); b.pop_front(), tomato++) 00869 *tomato = b.front(); 00870 } else if (*format == 'f') { 00871 sign = false; 00872 if (!ate) last = getc(); 00873 if (!(mods & addws)) 00874 for (; isspace(last); ) 00875 if ((last = getc()) == EOF) goto in_scanf_end; 00876 if (last != EOF) b.push_back(last); 00877 else goto in_scanf_end; 00878 if (!( 00879 last == '+' || 00880 last == '-' || 00881 isdigit(last) 00882 )) { hit(); goto in_scanf_end; } 00883 for (;;) { 00884 if ((last = getc()) == EOF) break; 00885 if (!(mods & dienl)) { 00886 if (last == '.' && sign) break; 00887 if (!isdigit(last) && last != '.') break; 00888 } 00889 if (last == '\n') break; 00890 else if (last == '.') sign = true; 00891 b.push_back(last); 00892 if (width) if (b.size() == width) break; 00893 } 00894 b.push_back(0); 00895 ate = true; 00896 if (mods & discard) break; 00897 if (mods & mw) 00898 *(va_arg(v, double*)) = stof<double>((char*)&(b[0])); 00899 else if (mods & ml) 00900 *(va_arg(v, long double*)) = stof<long double>((char*)&(b[0])); 00901 else 00902 *(va_arg(v, float*)) = stof<float>((char*)&(b[0])); 00903 } 00904 matched++; 00905 } else if (isspace(*format)) { 00906 do format++; while (isspace(*format)); 00907 format--; 00908 if (!ate) if ((last = getc()) == EOF) goto in_scanf_end; 00909 if (isspace(last)) ate = false; 00910 while (isspace(last)) 00911 if ((last = getc()) == EOF) goto in_scanf_end; 00912 if (!isspace(last)) ate = true; 00913 } else { 00914 if (!ate) if ((last = getc()) == EOF) goto in_scanf_end; 00915 if (last != *format) { hit(); goto in_scanf_end; } 00916 ate = false; 00917 } 00918 } // 149 00919 in_scanf_end: 00920 va_end(v); 00921 return matched; 00922 } 00923 00924 char* io::input::in_fmt(char* s, char d, char m) { 00925 int i = 0; 00926 if (fmt.hex()) { 00927 if (isupper(d)) d = 'X'; 00928 else d = 'x'; 00929 } else if (fmt.oct()) { 00930 if (isupper(d)) d = 'O'; 00931 else d = 'o'; 00932 } 00933 s[i++] = '%'; 00934 if (!fmt.ltrim()) s[i++] = '^'; 00935 if (fmt.endnl()) s[i++] = '$'; 00936 if (fmt.deaf()) s[i++] = '*'; 00937 i += sprintf(&(s[i]), "%d", fmt.width); 00938 if (m) s[i++] = m; 00939 s[i++] = d; 00940 s[i] = 0; 00941 return s; 00942 } 00943 00944 io::input& io::input::operator>> (bool& val) { 00945 if (fmt.bin()) { 00946 read((char*)&val, sizeof(bool), 1); 00947 return *this; 00948 } 00949 char s[8]; 00950 char t[24]; 00951 if (fmt.btoa()) { 00952 scanf(in_fmt(t, 's', 0), s); 00953 if (!fmt.deaf()) { 00954 if (!strcmp(s, "true")) val = true; 00955 else val = false; 00956 } 00957 } else { 00958 scanf(in_fmt(t, 'd', 'b'), &val); 00959 } 00960 return *this; 00961 } 00962 io::input& io::input::operator>> (short& val) { 00963 if (fmt.bin()) { 00964 read((char*)&val, sizeof(short), 1); 00965 return *this; 00966 } 00967 char s[24]; 00968 scanf(in_fmt(s, 'd', 'h'), &val); 00969 return *this; 00970 } 00971 io::input& io::input::operator>> (unsigned short &val) { 00972 if (fmt.bin()) { 00973 read((char*)&val, sizeof(unsigned short), 1); 00974 return *this; 00975 } 00976 char s[24]; 00977 scanf(in_fmt(s, 'D', 'h'), &val); 00978 return *this; 00979 } 00980 io::input& io::input::operator>> (int& val) { 00981 if (fmt.bin()) { 00982 read((char*)&val, sizeof(int), 1); 00983 return *this; 00984 } 00985 char s[24]; 00986 scanf(in_fmt(s, 'd', 0), &val); 00987 return *this; 00988 } 00989 io::input& io::input::operator>> (unsigned int& val) { 00990 if (fmt.bin()) { 00991 read((char*)&val, sizeof(unsigned int), 1); 00992 return *this; 00993 } 00994 char s[24]; 00995 scanf(in_fmt(s, 'D', 0), &val); 00996 return *this; 00997 } 00998 io::input& io::input::operator>> (long& val) { 00999 if (fmt.bin()) { 01000 read((char*)&val, sizeof(long), 1); 01001 return *this; 01002 } 01003 char s[24]; 01004 scanf(in_fmt(s, 'd', 'w'), &val); 01005 return *this; 01006 } 01007 io::input& io::input::operator>> (unsigned long& val) { 01008 if (fmt.bin()) { 01009 read((char*)&val, sizeof(unsigned long), 1); 01010 return *this; 01011 } 01012 char s[24]; 01013 scanf(in_fmt(s, 'D', 'w'), &val); 01014 return *this; 01015 } 01016 io::input& io::input::operator>> (long long& val) { 01017 if (fmt.bin()) { 01018 read((char*)&val, sizeof(long long), 1); 01019 return *this; 01020 } 01021 char s[24]; 01022 scanf(in_fmt(s, 'd', 'l'), &val); 01023 return *this; 01024 } 01025 io::input& io::input::operator>> (unsigned long long& val) { 01026 if (fmt.bin()) { 01027 read((char*)&val, sizeof(unsigned long long), 1); 01028 return *this; 01029 } 01030 char s[24]; 01031 scanf(in_fmt(s, 'D', 'l'), &val); 01032 return *this; 01033 } 01034 io::input& io::input::operator>> (float& val) { 01035 if (fmt.bin()) { 01036 read((char*)&val, sizeof(float), 1); 01037 return *this; 01038 } 01039 char s[24]; 01040 scanf(in_fmt(s, 'f', 0), &val); 01041 return *this; 01042 } 01043 io::input& io::input::operator>> (double& val) { 01044 if (fmt.bin()) { 01045 read((char*)&val, sizeof(double), 1); 01046 return *this; 01047 } 01048 char s[24]; 01049 scanf(in_fmt(s, 'f', 'w'), &val); 01050 return *this; 01051 } 01052 io::input& io::input::operator>> (long double& val) { 01053 if (fmt.bin()) { 01054 read((char*)&val, sizeof(long double), 1); 01055 return *this; 01056 } 01057 char s[24]; 01058 scanf(in_fmt(s, 'f', 'l'), &val); 01059 return *this; 01060 } 01061 io::input& io::input::operator>> (void*& val) { 01062 if (fmt.bin()) { 01063 read((char*)&val, sizeof(void*), 1); 01064 return *this; 01065 } 01066 char s[24]; 01067 scanf(in_fmt(s, 'X', 'w'), &val); 01068 return *this; 01069 } 01070 io::input& io::input::operator>> (char& c) { 01071 if (fmt.bin()) { 01072 read(&c, sizeof(char), 1); 01073 return *this; 01074 } 01075 char s[24]; 01076 scanf(in_fmt(s, 'c', 0), &c); 01077 return *this; 01078 } 01079 io::input& io::input::operator>> (char* s) { 01080 if (fmt.bin()) { 01081 register int i; 01082 int j; 01083 for (i = 0, j = getc(); j; j = getc(), i++) { 01084 if (j == -1) break; 01085 s[i] = j; 01086 } 01087 s[i] = 0; 01088 return *this; 01089 } 01090 char t[24]; 01091 scanf(in_fmt(t, 's', 0), s); 01092 return *this; 01093 } 01094 01101 int io::output::puts(const char* s) { 01102 register const char* t = s; 01103 for (; *t; t++) 01104 if (putc(*t) == EOF) 01105 return EOF; 01106 return t - s; 01107 } 01108 01118 size_t io::output::write(const char* ptr, size_t size, size_t nmemb) { 01119 size_t i, j; 01120 for (i = 0; i < nmemb; i++) 01121 for (j = 0; j < size; j++) { 01122 putc(ptr[size * i + j]); 01123 if (!ok()) return i; 01124 } 01125 return i; 01126 } 01127 01137 int io::output::printf(const char* format, ...) { 01138 char* s; 01139 va_list v; 01140 size_t i; 01141 int ret = 0; 01142 i = 32; 01143 va_start(v, format); 01144 s = (char*)malloc(i); 01145 #ifndef _WIN32 01146 while ((ret = vsnprintf(s, i, format, v)) >= i) { 01147 i *= 2; 01148 s = (char*)::realloc(s, i); 01149 } 01150 #else 01151 for (;;) { 01152 ret = vsnprintf(s, i, format, v); 01153 if (ret != -1 && ret < i) break; 01154 i *= 2; 01155 s = (char*)::realloc(s, i); 01156 } 01157 #endif 01158 if (ret == -1) { hit(); free(s); va_end(v); return -1; } 01159 puts(s); 01160 free(s); 01161 va_end(v); 01162 return ret; 01163 } 01164 01165 char* io::output::out_fmt(char* s, char t, const char* m) { 01166 int i = 0; 01167 switch (t) { 01168 case 'd': case 'i': case 'o': case 'u': 01169 case 'x': case 'X': 01170 if (fmt.hex()) { 01171 if (isupper(t)) t = 'X'; 01172 else t = 'x'; 01173 } else if (fmt.oct()) { 01174 if (isupper(t)) t = 'O'; 01175 else t = 'o'; 01176 } 01177 default: ; 01178 } 01179 if (t == 'G') 01180 if (fmt.fix()) t = 'F'; 01181 else if (fmt.sci()) t = 'E'; 01182 s[i++] = '%'; 01183 if (fmt.base()) s[i++] = '#'; 01184 if (fmt.zpad()) s[i++] = '0'; 01185 if (fmt.left()) s[i++] = '-'; 01186 if (fmt.sign()) s[i++] = '+'; 01187 if (fmt.width) i += sprintf(&(s[i]), "%d", fmt.width); 01188 if (fmt.precis) { 01189 s[i++] = '.'; 01190 i += sprintf(&(s[i]), "%d", fmt.precis); 01191 } 01192 if (m) { strcpy(s + i, m); i += strlen(m); } 01193 s[i++] = t; 01194 s[i] = 0; 01195 return s; 01196 } 01197 io::output& io::output::operator<< (bool val) { 01198 if (fmt.bin()) { 01199 write((const char*)&val, sizeof(bool), 1); 01200 return *this; 01201 } 01202 if (fmt.btoa()) { 01203 if (val) puts("true"); 01204 else puts("false"); 01205 } else printf("%hhd", val); 01206 return *this; 01207 } 01208 io::output& io::output::operator<< (short val) { 01209 if (fmt.bin()) { 01210 write((const char*)&val, sizeof(short), 1); 01211 return *this; 01212 } 01213 char s[24]; 01214 printf(out_fmt(s, 'd', "h"), val); 01215 return *this; 01216 } 01217 io::output& io::output::operator<< (unsigned short val) { 01218 if (fmt.bin()) { 01219 write((const char*)&val, sizeof(unsigned short), 1); 01220 return *this; 01221 } 01222 char s[24]; 01223 printf(out_fmt(s, 'u', "h"), val); 01224 return *this; 01225 } 01226 io::output& io::output::operator<< (int val) { 01227 if (fmt.bin()) { 01228 write((const char*)&val, sizeof(int), 1); 01229 return *this; 01230 } 01231 char s[24]; 01232 printf(out_fmt(s, 'd', 0), val); 01233 return *this; 01234 } 01235 io::output& io::output::operator<< (unsigned int val) { 01236 if (fmt.bin()) { 01237 write((const char*)&val, sizeof(unsigned int), 1); 01238 return *this; 01239 } 01240 char s[24]; 01241 printf(out_fmt(s, 'u', 0), val); 01242 return *this; 01243 } 01244 io::output& io::output::operator<< (long val) { 01245 if (fmt.bin()) { 01246 write((const char*)&val, sizeof(long), 1); 01247 return *this; 01248 } 01249 char s[24]; 01250 printf(out_fmt(s, 'd', "l"), val); 01251 return *this; 01252 } 01253 io::output& io::output::operator<< (unsigned long val) { 01254 if (fmt.bin()) { 01255 write((const char*)&val, sizeof(unsigned long), 1); 01256 return *this; 01257 } 01258 char s[24]; 01259 printf(out_fmt(s, 'u', "l"), val); 01260 return *this; 01261 } 01262 io::output& io::output::operator<< (float val) { 01263 if (fmt.bin()) { 01264 write((const char*)&val, sizeof(float), 1); 01265 return *this; 01266 } 01267 char s[24]; 01268 printf(out_fmt(s, 'G', 0), val); 01269 return *this; 01270 } 01271 io::output& io::output::operator<< (double val) { 01272 if (fmt.bin()) { 01273 write((const char*)&val, sizeof(double), 1); 01274 return *this; 01275 } 01276 char s[24]; 01277 printf(out_fmt(s, 'G', 0), val); 01278 return *this; 01279 } 01280 io::output& io::output::operator<< (long double val) { 01281 if (fmt.bin()) { 01282 write((const char*)&val, sizeof(long double), 1); 01283 return *this; 01284 } 01285 char s[24]; 01286 printf(out_fmt(s, 'G', "L"), val); 01287 return *this; 01288 } 01289 io::output& io::output::operator<< (const void* val) { 01290 if (fmt.bin()) { 01291 write((const char*)&val, sizeof(const void*), 1); 01292 return *this; 01293 } 01294 char s[24]; 01295 printf(out_fmt(s, 'p', 0), val); 01296 return *this; 01297 } 01298 io::output& io::output::operator<< (char c) { 01299 if (fmt.bin()) { 01300 write((const char*)&c, sizeof(char), 1); 01301 return *this; 01302 } 01303 char s[24]; 01304 printf(out_fmt(s, 'c', 0), c); 01305 return *this; 01306 } 01307 io::output& io::output::operator<< (signed char c) { 01308 if (fmt.bin()) { 01309 write((const char*)&c, sizeof(signed char), 1); 01310 return *this; 01311 } 01312 char s[24]; 01313 printf(out_fmt(s, 'c', 0), c); 01314 return *this; 01315 } 01316 io::output& io::output::operator<< (unsigned char c) { 01317 if (fmt.bin()) { 01318 write((const char*)&c, sizeof(unsigned char), 1); 01319 return *this; 01320 } 01321 char s[24]; 01322 printf(out_fmt(s, 'c', 0), c); 01323 return *this; 01324 } 01325 io::output& io::output::operator<< (const char* s) { 01326 if (fmt.bin()) { 01327 register int i; 01328 for (i = 0; s[i]; i++); 01329 write((const char*)&s, sizeof(char), ++i); 01330 return *this; 01331 } 01332 char t[24]; 01333 printf(out_fmt(t, 's', 0), s); 01334 return *this; 01335 } 01336 /*io::output& io::output::echo(string s) { 01337 operator<<(s.buf); 01338 putc('\n'); 01339 return *this; 01340 } 01341 io::output& io::output::put(string s) { 01342 operator<<(s.buf); 01343 return *this; 01344 } 01345 io::output& io::output::echo(timer c) { 01346 operator<<(c.str().buf); 01347 putc('\n'); 01348 return *this; 01349 } 01350 io::output& io::output::put(timer c) { 01351 operator<<(c.str().buf); 01352 return *this; 01353 }*/ 01354 01355 string net::dgram::type() { return string("net::dgram"); } 01356 net::dgram::operator string () { string s; s << ip << '/' << port; return s; } 01357 01358 data fs::fbread(const char* fname, size_t len) { 01359 FILE* f; 01360 data d; 01361 if (!len) len = fsize(fname); 01362 if ((f = fopen(fname, "rb")) == NULL) return d; 01363 d.realloc(len); 01364 fread(d.buf, 1, len, f); 01365 return d; 01366 } 01367 01368 size_t fs::fbwrite(const char* fname, data d, size_t len) { 01369 FILE* f; 01370 if ((f = fopen(fname, "w+b")) == NULL) return 0; 01371 if (!len) len = d.len(); 01372 register size_t i = fwrite(d.buf, 1, len, f); 01373 return i; 01374 } 01375 01376 string data::type() { return string("data"); } 01377 data::operator string() { 01378 string s; 01379 register size_t i; 01380 for (i = 0; i < slen; i++) 01381 s.printf("%02x ", ((unsigned char*)buf)[i]); 01382 return s; 01383 } 01384 size_t data::len() const { return slen; } 01385 bool data::operator== (data d) { if (len() != d.len()) return false; return !memcmp(buf, d.buf, len()); } 01386 bool data::operator!= (data d) { return !memcmp(buf, d.buf, len()); } 01387 data::data(const data& d) { 01388 fmt.bin(1); 01389 buf = 0; pos = 0; mlen = 0; slen = 0; 01390 realloc(d.len()); 01391 memmove(buf, d.buf, d.len()); 01392 } 01393 char& data::operator [](int i) { realloc(i + 1); return buf[i]; } 01394 data& data::operator= (data d) { 01395 if (buf) free(buf); 01396 rewind(); 01397 buf = d.buf; 01398 slen = d.len(); 01399 d.buf = 0; 01400 return *this; 01401 } 01402 01403 void data::realloc(size_t i) { 01404 slen = i; 01405 register size_t n = i; 01406 while (n & (n - 1)) n++; 01407 if (mlen < n) { 01408 if (buf) buf = (char*)::realloc(buf, n); 01409 else { buf = (char*)malloc(n); buf[0] = 0; } 01410 mlen = n; 01411 buf[i - 1] = 0; 01412 } 01413 } 01414 data::data() { fmt.bin(1); buf = 0; pos = 0; mlen = 0; slen = 0; } 01415 data::~data() { if (buf) free(buf); } 01416 int string::getc() { 01417 if (pos > mlen) { kill(); return -1; } 01418 unsigned char c = buf[pos++]; 01419 if (!c) { drain(); return -1; } 01420 else { heal(); return c; } 01421 } 01422 01423 int data::getc() { 01424 if (pos > mlen) { drain(); return -1; } 01425 unsigned char c = buf[pos++]; 01426 heal(); 01427 return c; 01428 } 01429 int data::putc(int c) { 01430 (this->operator[] (pos++)) = c; 01431 heal(); return c; 01432 } 01433 bool data::seek(long offset, int whence) { 01434 if (whence == SEEK_SET) pos = offset; 01435 else if (whence == SEEK_END) pos = len() + offset; 01436 else if (whence == SEEK_CUR) pos += offset; 01437 else pos = offset + whence; 01438 if (pos > len()) return false; 01439 return true; 01440 } 01441 size_t data::tell() { return pos; } 01442 void data::rewind() { pos = 0; } 01443 void data::unwind() { pos = len(); } 01444 bool data::ffwd(size_t offset) { 01445 pos += offset; 01446 if (pos > len()) return false; 01447 return true; 01448 } 01449 bool data::prev(size_t offset) { 01450 pos -= offset; 01451 if (pos > len()) return false; 01452 return true; 01453 } 01454 01455 string::string() { fmt.bin(0); buf = 0; pos = 0; mlen = 0; } 01456 01457 string::string(const char* s) { 01458 fmt.bin(0); 01459 buf = 0; pos = 0; mlen = 0; 01460 if (s) { 01461 size_t i = strlen(s) + 1; 01462 while (i & (i - 1)) i++; 01463 buf = (char*)malloc(i); 01464 mlen = i; 01465 strcpy(buf, s); 01466 } 01467 } 01468 01469 string::string(size_t n) { fmt.bin(0); buf = 0; pos = 0; mlen = 0; realloc(n); buf[0] = 0; } 01470 01471 string::string(const string& s) { 01472 fmt.bin(0); 01473 buf = 0; pos = 0; mlen = s.msize(); 01474 if (s.buf) { 01475 buf = (char*)malloc(mlen); 01476 strcpy(buf, s.buf); 01477 } 01478 } 01479 01480 string::~string() { if (buf) { free(buf); buf = 0; }} 01481 01482 /*int string::getc() { 01483 unsigned char c = buf[pos++]; 01484 if (!c) { drain(); return -1; } 01485 else { heal(); return c; } 01486 }*/ 01487 01488 int string::putc(int c) { 01489 if (!buf) realloc(2); 01490 if (buf[pos] == 0 || pos >= mlen) { 01491 realloc(pos + 4); 01492 buf[pos + 1] = 0; 01493 } 01494 buf[pos++] = c; heal(); return c; 01495 } 01496 /* 01497 bool string::seek(long offset, int whence) { 01498 if (whence == SEEK_SET) pos = offset; 01499 else if (whence == SEEK_END) pos = len() + offset; 01500 else if (whence == SEEK_CUR) pos += offset; 01501 else pos = offset + whence; 01502 if (pos > len()) return false; 01503 return true; 01504 } 01505 size_t string::tell() { return pos; } 01506 string& string::rewind() { pos = 0; return *this; } 01507 string& string::unwind() { pos = len(); return *this; } 01508 bool string::ffwd(size_t offset) { 01509 pos += offset; 01510 if (pos > len()) return false; 01511 return true; 01512 } 01513 bool string::prev(size_t offset) { 01514 pos -= offset; 01515 if (pos > len()) return false; 01516 return true; 01517 }*/ 01518 01538 string string::esc(const char* format, int (*charfilter)(int)) { 01539 if (empty()) return string(); 01540 string s; 01541 size_t i = tell(); 01542 register int c; 01543 char d; 01544 rewind(); 01545 for (c = getc(); c != EOF; c = getc()) { 01546 d = c; 01547 if (charfilter == NULL) s.printf(format, d); 01548 else if (charfilter(d)) s.printf(format, d); 01549 else s.putc(d); 01550 } 01551 seek(i, SEEK_SET); 01552 return s; 01553 } 01554 01569 string string::esc(const char* format, const char* chrs) { 01570 string s; 01571 size_t i = tell(); 01572 register int c; 01573 char d; 01574 rewind(); 01575 for (c = getc(); c != EOF; c = getc()) { 01576 d = c; 01577 if (strchr(chrs, d)) s.printf(format, d); 01578 else s.putc(d); 01579 } 01580 seek(i, SEEK_SET); 01581 return s; 01582 } 01583 01594 string string::uesc(const char* format, const char* chrs) { 01595 string s(buf); 01596 string t; 01597 char c[2]; 01598 c[1] = 0; 01599 for (*c = 0; *c < CHAR_MAX; (*c)++) { 01600 if (strchr(chrs, *c)) { 01601 t.printf(format, *c); 01602 s = s.rep(t, c); 01603 } 01604 t.clear(); 01605 } 01606 t.clear(); 01607 if (strchr(chrs, *c)) { 01608 t.printf(format, *c); 01609 s = s.rep(t, c); 01610 } 01611 return s; 01612 } 01613 01624 string string::uesc(const char* format, int (*charfilter)(int)) { 01625 string s(buf); 01626 string t; 01627 char c[2]; 01628 c[1] = 0; 01629 for (*c = 0; *c < CHAR_MAX; (*c)++) { 01630 if (charfilter == NULL) { 01631 t.printf(format, *c); 01632 s = s.rep(t, c); 01633 } else if (charfilter(*c)) { 01634 t.printf(format, *c); 01635 s = s.rep(t, c); 01636 } 01637 t.clear(); 01638 } 01639 t.clear(); 01640 if (charfilter == NULL) { 01641 t.printf(format, *c); 01642 s = s.rep(t, c); 01643 } else if (charfilter(*c)) { 01644 t.printf(format, *c); 01645 s = s.rep(t, c); 01646 } 01647 return s; 01648 } 01649 01650 /*string string::gets(int size) { 01651 string s; 01652 int i = 32, j = 0; 01653 register int c; 01654 s.realloc(i); 01655 for (c = getc(); ; c = getc(), j++) { 01656 if (size) if (j >= size) break; 01657 if (j >= i - 4) { i *= 2; s.realloc(i); } 01658 switch (c) { 01659 case EOF: s.buf[0] = 0; return s; 01660 case '\n': s.buf[j] = '\n'; s.buf[++j] = 0; return s; 01661 default: s.buf[j] = c; 01662 } 01663 } 01664 s.buf[j] = 0; 01665 return s; 01666 }*/ 01667 01671 string string::q() { 01672 register size_t i = strlen(buf); 01673 string s(i + 3); 01674 strcpy(s.buf + 1, buf); 01675 s.buf[0] = '\''; 01676 s.buf[++i] = '\''; 01677 s.buf[++i] = 0; 01678 return s; 01679 } 01680 01684 string string::qq() { 01685 register size_t i = strlen(buf); 01686 string s(i + 3); 01687 strcpy(s.buf + 1, buf); 01688 s.buf[0] = '\"'; 01689 s.buf[++i] = '\"'; 01690 s.buf[++i] = 0; 01691 return s; 01692 } 01693 01697 string string::qx() { 01698 string s; 01699 fs::file pipe; 01700 pipe.fd = popen(buf, "r"); 01701 if (!pipe.fd) return s; 01702 until (pipe.eof()) s += pipe.getc(); 01703 s = s.chop(); 01704 pclose(pipe.fd); 01705 return s; 01706 } 01707 01708 /*string string::htmlesc() { 01709 string s(buf); 01710 string t; 01711 register int i; 01712 for (i = 0; entnames[i].c; i++) 01713 t.puts(entnames[i].c); 01714 t.putc(0); 01715 s = s.esc("&#%d;", t); 01716 return s; 01717 } 01718 string string::htmluesc() { 01719 string s(buf); 01720 string t; 01721 char b[2]; 01722 register int i; 01723 b[1] = 0; 01724 for (i = 0; entnames[i].c; i++) { 01725 t.putc(entnames[i].c); 01726 b[0] = entnames[i].c; 01727 s = s.rep(entnames[i].name, b); 01728 } 01729 t.putc(0); 01730 s = s.uesc("&#%d;", t); 01731 //s = s.uesc("&#%d;", "\"'&<> ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿×÷ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿ"); 01732 return s; 01733 }*/ 01734 01738 char& string::front() { return buf[0]; }; 01739 01743 char& string::back() { return buf[strlen(buf) - 1]; } 01744 01748 string& string::clear() { realloc(2); pos = 0; buf[0] = 0; return *this; } 01749 01753 bool string::empty() { if (buf) return buf[0] == 0; else return true; } 01754 01758 size_t string::len() { if (buf) return strlen(buf); else return 0; } 01759 01760 01761 io::output& io::output::operator<< (string s) { return operator<<(s.buf); } 01762 01770 /*string& string::realloc(size_t i) { 01771 register size_t n = i; 01772 while (n & (n - 1)) n++; 01773 if (mlen < n) { 01774 if (buf) buf = (char*)::realloc(buf, n); 01775 else { buf = (char*)malloc(n); buf[0] = 0; } 01776 mlen = n; 01777 buf[i - 1] = 0; 01778 } 01779 return *this; 01780 }*/ 01781 01785 size_t string::msize() const { return mlen; } 01786 01792 string string::cat(const char* s, size_t n) { 01793 string t; 01794 register size_t i = this->len(); 01795 if (!n) n = strlen(s) + 1; 01796 t.realloc(i + n); 01797 strcpy2(t.buf, buf); 01798 for (; n > 0; i++, n--, s++) 01799 t.buf[i] = *s; 01800 t.buf[i] = 0; 01801 return t; 01802 } 01803 01804 string string::wrap(size_t len, const char* eol) { 01805 string s; 01806 size_t i, j, k = strlen(buf); 01807 for (i = 0, j = 0; i < k; i++, j++) { 01808 if (j == len) { 01809 s << eol; 01810 j = 0; 01811 } 01812 s << buf[i]; 01813 } 01814 s.rewind(); 01815 return s; 01816 } 01817 01823 string string::cat(int c, size_t n) { 01824 string t; 01825 register size_t i; 01826 if (buf) i = strlen(buf); 01827 else i = 0; 01828 t.realloc(i + n + 1); 01829 if (buf) strcpy(t.buf, buf); 01830 for (; n > 0; n--, i++) 01831 t.buf[i] = c; 01832 t.buf[i] = 0; 01833 return t; 01834 } 01835 01841 string string::prep(const char* s, size_t n) { 01842 string t; 01843 if (!n) n = strlen(s); 01844 register size_t i; 01845 if (buf) i = strlen(buf); 01846 else i = 0; 01847 t.realloc(n + i + 1); 01848 strncpy(t.buf, s, n); 01849 t.buf[n] = 0; 01850 if (buf) strcat(t.buf, buf); 01851 return t; 01852 } 01853 01859 string string::prep(int c, size_t n) { 01860 string t; 01861 register size_t i; 01862 if (buf) i = strlen(buf); 01863 01864 else i = 0; 01865 t.realloc(i + n + 1); 01866 for (i = 0; i < n; i++) t.buf[0] = c; 01867 if (buf) strcpy(&(t.buf[i]), buf); 01868 t.buf[strlen(t.buf)] = 0; 01869 return t; 01870 } 01871 01877 long string::chr(int c, size_t index) { 01878 if (len() == 0) return -1; 01879 register char* s = strchr(buf + index, c); 01880 if (s == NULL) return -1; 01881 return s - (buf + index); 01882 } 01883 01888 long string::rchr(int c) { 01889 if (len() == 0) return -1; 01890 register char* s = strrchr(buf, c); 01891 if (s == NULL) return -1; 01892 return s - buf; 01893 } 01894 01900 long string::str(const char* s, size_t index) { 01901 if (len() == 0) return -1; 01902 register char* t = strstr(buf + index, s); 01903 if (t == NULL) return -1; 01904 return t - (buf + index); 01905 } 01906 01911 long string::rstr(const char* s) { 01912 if (len() == 0) return -1; 01913 char *t, *u; 01914 for(t = strstr(buf, s), u = t; t; t = strstr(u, s)) 01915 if (t) u = t; 01916 return u - buf; 01917 } 01918 01923 size_t string::nchr(int ch) { 01924 if (len() == 0) return 0; 01925 register size_t i, j; 01926 for (i = 0, j = 0; buf[i]; i++) 01927 if (buf[i] == ch) j++; 01928 return j; 01929 } 01930 01935 size_t string::nstr(const char* str) { 01936 char* t = buf; 01937 register size_t i; 01938 size_t j = strlen(str); 01939 for (i = 0, t = strstr(t, str); t != NULL; i++, t = strstr(t, str)) 01940 t += j; 01941 return i; 01942 } 01943 01948 bool string::starts(const char* s) { if (!buf) return false; return !strncmp(buf, s, strlen(s)); } 01949 01954 bool string::starts(int c) { if (!buf) return false; return (buf[0] == c); } 01955 01960 bool string::ends(const char* s) { 01961 if (!buf) return false; 01962 register size_t i = strlen(buf), j = strlen(s); 01963 return !strncmp(buf + i - j, s, j); 01964 } 01965 01970 bool string::ends(int c) { if (!buf) return false; return (buf[strlen(buf) - 1] == c); } 01971 01976 bool string::is(const char* s) { if (!buf) return false; return !strcmp(buf, s); } 01977 01982 bool string::is(int c) { if (!buf) return false; return (buf[0] == c && buf[1] == 0); } 01983 01988 string string::left(size_t n) { 01989 string s; 01990 s.realloc(n + 1); 01991 strncpy(s.buf, buf, n); 01992 s.buf[n] = 0; 01993 return s; 01994 } 01995 02000 string string::right(size_t n) { 02001 string s; 02002 s.realloc(n + 1); 02003 strcpy(s.buf, buf + strlen(buf) - n); 02004 return s; 02005 } 02006 02013 string string::cpy(const char* src, size_t index, size_t count) { 02014 if (!count) count = strlen(src); 02015 string t(index + count + 1); 02016 strncpy(t.buf, buf, index); 02017 strncpy(t.buf + index, src, count); 02018 t.buf[index + count] = 0; 02019 return t; 02020 } 02021 02028 string string::cpy(int c, size_t index, size_t count) { 02029 string t(index + count + 1); 02030 strncpy(t.buf, buf, index); 02031 for (; count > 0; index++, count--) t.buf[index] = c; 02032 t.buf[index] = 0; 02033 return t; 02034 } 02035 02036 /* 02037 string string::ncpy(const char* src, size_t n, size_t index) { 02038 if (!n) n = strlen(src); 02039 size_t i = strlen(buf); 02040 string t(i + n + 1); 02041 strcpy(t.buf, buf); 02042 strncpy(t.buf, src, n); 02043 return t; 02044 }*/ 02045 02051 size_t string::spn(const char* accept, size_t index) { if (len() == 0) return 0; return strspn(buf + index, accept); } 02052 02058 size_t string::cspn(const char* reject, size_t index) { if (len() == 0) return 0; return strcspn(buf + index, reject); } 02059 02065 size_t string::spn(int c, size_t index) { 02066 if (len() == 0) return 0; 02067 register size_t i; 02068 for (i = 0; buf[index] == c; index++) i++; 02069 return i; 02070 } 02071 02077 size_t string::cspn(int c, size_t index) { 02078 if (len() == 0) return 0; 02079 register size_t i; 02080 for (i = 0; buf[index] != c; index++) i++; 02081 return i; 02082 } 02083 02087 string string::fry() { 02088 string t(buf); 02089 if (!buf[1]) return t; 02090 static unsigned int seed; 02091 unsigned int ck = t.cksum(); 02092 srand(seed ^ time(NULL)); 02093 char *a, *b, c; 02094 int i, j = strlen(buf); 02095 for (i = 0; i < j; i++) { 02096 a = &(t.buf[rand() % j]); 02097 b = &(t.buf[rand() % j]); 02098 c = *a; 02099 *a = *b; 02100 *b = c; 02101 } 02102 seed = rand(); 02103 if (t.cksum() == ck) t = t.fry(); 02104 return t; 02105 } 02106 02114 long string::pbrk(const char* accept, size_t index) { 02115 if (len() == 0) return 0; 02116 register char* s = strpbrk(buf + index, accept); 02117 if (s == NULL) return -1; 02118 return s - (buf + index); 02119 } 02120 02128 long string::rpbrk(const char* accept, size_t index) { 02129 if (len() == 0) return 0; 02130 char *s, *t; 02131 for(s = strpbrk(buf + index, accept), t = s; s; s = strpbrk(t + 1, accept)) 02132 if (s) t = s; 02133 return t - (buf + index); 02134 } 02135 02141 string string::substr(size_t start, size_t count) { 02142 string t; 02143 if (len() == 0) return t; 02144 t.realloc(count + 1); 02145 strncpy(t.buf, buf + start, count); 02146 t.buf[count] = 0; 02147 return t; 02148 } 02149 02158 string string::tok(size_t index, const char* delim) { 02159 if (empty()) return *this; 02160 string s(buf); 02161 char *u; 02162 s = s.squeeze(delim); 02163 while (s.pbrk(delim) == 0) s = s.shl(1); 02164 while (s.pbrk(delim) == s.len() - 1) s = s.shr(1); 02165 u = strtok(s.buf, delim); 02166 for (; index > 0 && u; index--) 02167 u = strtok(NULL, delim); 02168 if (u) memmove(s.buf, u, strlen(u) + 1); 02169 else s.clear(); 02170 return s; 02171 } 02172 02181 string string::tok(size_t index, int delim) { 02182 char x[2]; 02183 x[0] = delim; 02184 x[1] = 0; 02185 return tok(index, x); 02186 } 02187 02195 size_t string::ntok(const char* delim) { 02196 if (empty()) return 0; 02197 size_t i; 02198 char *p, *tmp = (char*)malloc(strlen(buf) + 1); 02199 strcpy(tmp, buf); 02200 for ( 02201 p = strtok(tmp, delim), i = 0; 02202 p; p = strtok(0, delim), i++ 02203 ); 02204 free(tmp); 02205 return i; 02206 } 02207 02215 size_t string::ntok(int delim) { 02216 char s[2]; s[0] = delim; s[1] = 0; 02217 return this->ntok(s); 02218 } 02219 02235 long string::itok(size_t index, const char* delim) { 02236 register long a; 02237 for (a = 0; buf[a] && index > 0; a++) { 02238 if (strchr(delim, buf[a])) { 02239 do { 02240 a++; 02241 } while (strchr(delim, buf[a])); 02242 a--; 02243 index--; 02244 } 02245 } 02246 if (buf[a] == 0) return -1; 02247 return a; 02248 } 02249 02265 long string::itok(size_t index, int delim) { 02266 char x[2]; 02267 x[0] = delim; x[1] = 0; 02268 return itok(index, x); 02269 } 02270 02278 std::deque<axcel::string> string::split(const char* delim) { 02279 std::deque<axcel::string> d; 02280 char* s = (char*)malloc(strlen(buf) + 1); 02281 strcpy(s, buf); 02282 const char* t = strtok(s, delim); 02283 for (; t != NULL; t = strtok(NULL, delim)) 02284 d.push_back(string(t)); 02285 free(s); 02286 return d; 02287 } 02288 02296 std::deque<axcel::string> string::split(int delim) { char x[2]; x[0] = delim; x[1] = 0; return split(x); } 02297 02303 string string::ins(size_t index, const char* str) { 02304 if (empty()) return string(); 02305 size_t len1 = strlen(str), len2 = strlen(buf); 02306 string s(len1 + len2 + 1); 02307 strncpy(s.buf, buf, index); 02308 s.buf[index] = 0; 02309 strncat(s.buf, str, len1); 02310 strcpy(s.buf + index + len1, buf + index); 02311 return s; 02312 } 02313 02319 string string::ins(size_t index, int c) { 02320 if (empty()) return string(); 02321 char x[2]; x[0] = c; x[1] = 0; 02322 return ins(index, x); 02323 } 02324 02330 string string::rm(size_t index, size_t n) { 02331 if (empty()) return string(); 02332 size_t i = strlen(buf); 02333 string s(i - n + 1); 02334 strncpy(s.buf, buf, index); 02335 s.buf[index] = 0; 02336 strcat(s.buf, buf + index + n); 02337 return s; 02338 } 02339 02345 string string::rev(size_t start, size_t count) { 02346 if (empty()) return string(); 02347 if (!count) count = strlen(buf) - start; 02348 string s(strlen(buf) + 1); 02349 size_t i, j; 02350 for (i = 0, j = 0; ; i++, j++) { 02351 if (j == start) { 02352 for (j += count - 1; j > start; j--, i++) 02353 s.buf[i] = buf[j]; 02354 s.buf[i++] = buf[j]; 02355 j += count; 02356 } 02357 s.buf[i] = buf[j]; 02358 if (!s.buf[i]) break; 02359 } 02360 return s; 02361 } 02362 02367 string string::dup(int i) { 02368 if (empty()) return string(); 02369 size_t n = strlen(buf); 02370 string s(n * i + 1); 02371 strcpy(s.buf, buf); 02372 for (i--; i > 0; i--) 02373 strcat(s.buf, buf); 02374 return s; 02375 } 02376 02383 string string::rol(size_t i, size_t index, size_t count) { 02384 if (empty()) return string(); 02385 if (!count) count = strlen(buf) - index; 02386 string s(strlen(buf) + 1); 02387 strncpy(s.buf, buf, index); 02388 strncpy(s.buf + index, buf + index + i, count - i); 02389 strncpy(s.buf + index + count - i, buf + index, i); 02390 s.buf[index + count] = 0; 02391 strcat(s.buf, buf + index + count); 02392 return s; 02393 } 02394 02401 string string::ror(size_t i, size_t index, size_t count) { 02402 if (empty()) return string(); 02403 if (!count) count = strlen(buf) - index; 02404 string s(strlen(buf) + 1); 02405 strncpy(s.buf, buf, index); 02406 strncpy(s.buf + index, buf + index + count - i, i); 02407 strncpy(s.buf + index + i, buf + index, count - i); 02408 s.buf[index + count] = 0; 02409 strcat(s.buf, buf + index + count); 02410 return s; 02411 } 02412 02417 string string::shl(size_t n) { 02418 if (empty()) return string(); 02419 string s(strlen(buf) - n + 1); 02420 strcpy(s.buf, buf + n); 02421 return s; 02422 } 02423 02428 string string::shr(size_t n) { 02429 if (empty()) return string(); 02430 register size_t i = strlen(buf) - n; 02431 string s(i + 1); 02432 strncpy(s.buf, buf, i); 02433 s.buf[i] = 0; 02434 return s; 02435 } 02436 02442 string string::lc(size_t start, size_t count) { 02443 if (empty()) return string(); 02444 if (!count) count = strlen(buf) - start; 02445 string s(strlen(buf) + 1); 02446 size_t i; 02447 for (i = 0; i < start; i++) s.buf[i] = buf[i]; 02448 for (; count > 0; count--, i++) s.buf[i] = tolower(buf[i]); 02449 for (; buf[i]; i++) s.buf[i] = buf[i]; 02450 s.buf[i] = 0; 02451 return s; 02452 } 02453 02454 02460 string string::uc(size_t start, size_t count) { 02461 02462 if (empty()) return string(); 02463 if (!count) count = strlen(buf) - start; 02464 string s(strlen(buf) + 1); 02465 size_t i; 02466 for (i = 0; i < start; i++) s.buf[i] = buf[i]; 02467 for (; count > 0; count--, i++) s.buf[i] = toupper(buf[i]); 02468 for (; buf[i]; i++) s.buf[i] = buf[i]; 02469 s.buf[i] = 0; 02470 return s; 02471 } 02472 02473 02477 string string::ltrim() { 02478 if (empty()) return string(); 02479 size_t i = 0; 02480 for (; ::isspace(buf[i]); i++); 02481 string s(strlen(buf + i) + 1); 02482 strcpy(s.buf, buf + i); 02483 return s; 02484 } 02485 02489 string string::rtrim() { 02490 if (empty()) return string(); 02491 size_t i = strlen(buf) - 1; 02492 for (; ::isspace(buf[i]); i--); 02493 string s(i += 2); 02494 strncpy(s.buf, buf, --i); 02495 s.buf[i] = 0; 02496 return s; 02497 } 02498 02502 string string::strip() { 02503 if (empty()) return string(); 02504 string s(buf); 02505 s = s.rtrim(); 02506 s = s.ltrim(); 02507 return s; 02508 /*size_t i = 0, j = strlen(buf) - 1, k = strlen(buf); 02509 for (; isspace(buf[i]); i++); 02510 if (i >= k) return string(); 02511 for (; isspace(buf[j]); j--); 02512 string s(k - i - (k - j) + 1); 02513 strncpy(s.buf, buf + i, j - i + 1); 02514 s.buf[j - i + 1] = 0; 02515 return s;*/ 02516 } 02517 02521 string string::chop() { 02522 string s; 02523 if (empty()) return s; 02524 size_t i = strlen(buf); 02525 if (this->ends("\r\n")) { 02526 s.realloc(--i); i--; 02527 } else s.realloc(i--); 02528 s.buf[i] = 0; 02529 strncpy(s.buf, buf, i); 02530 return s; 02531 } 02532 02533 02538 string string::chomp(const char* eat) { 02539 string s; 02540 if (empty()) return s; 02541 size_t i = strlen(buf); 02542 char* t; 02543 if (!strcmp(eat, "\r\n")) { 02544 s = buf; 02545 t = strrchr(s.buf, '\n'); 02546 if (t) *t = 0; 02547 t = strrchr(s.buf, '\r'); 02548 if (t) *t = 0; 02549 return s; 02550 } 02551 if (this->ends(eat)) { 02552 i -= strlen(eat); 02553 i++; 02554 s.realloc(i); i--; 02555 } else s.realloc(i + 1); 02556 s.buf[i] = 0; 02557 strncpy(s.buf, buf, i); 02558 return s; 02559 } 02560 02564 string string::cut() { 02565 string s; 02566 if (empty()) return s; 02567 size_t i = strlen(buf); 02568 if (this->starts("\r\n")) { 02569 s.realloc(--i); i--; 02570 } else s.realloc(i--); 02571 s.buf[i] = 0; 02572 strncpy(s.buf, buf + (strlen(buf) - i), i); 02573 return s; 02574 } 02575 02580 string string::munch(const char* eat) { 02581 string s; 02582 if (empty()) return s; 02583 if (this->starts(eat)) s = (buf + strlen(eat)); 02584 else s = buf; 02585 return s; 02586 } 02587 02588 02593 string& string::swap(string& s) { 02594 size_t i = s.msize(); 02595 char* t = s.buf; 02596 s.buf = buf; 02597 s.realloc(mlen); 02598 mlen = i; 02599 buf = t; 02600 return *this; 02601 } 02602 02603 02610 string string::center(size_t newlen, const char* left, const char* right) { 02611 string s(buf); 02612 if (newlen <= strlen(s.buf) + 1) return s; 02613 size_t i = (newlen - strlen(s.buf)) / 2; 02614 s = s.rpad(i + strlen(s.buf), right); 02615 s = s.lpad(i + strlen(s.buf), left); 02616 return s; 02617 } 02618 02625 string string::center(size_t newlen, int left, int right) { 02626 char a[2], b[2]; 02627 a[0] = left; a[1] = 0; 02628 b[0] = right; b[1] = 0; 02629 return center(newlen, a, b); 02630 } 02631 02637 string string::center(size_t newlen, const char* pad) { 02638 return center(newlen, pad, pad); 02639 } 02640 02646 string string::center(size_t newlen, int pad) { 02647 char a[2]; 02648 a[0] = pad; a[1] = 0; 02649 return center(newlen, a, a); 02650 } 02651 02657 string string::lpad(size_t newlen, const char* pad) { 02658 if (newlen <= strlen(buf)) return *this; 02659 string s(newlen + 1); 02660 size_t i, j, len1 = strlen(pad), len2 = newlen - strlen(buf); 02661 strcpy(s.buf + len2, buf); 02662 for (i = 0, j = 0; i < len2; i++, j++) { 02663 if (j == len1) j = 0; 02664 s.buf[i] = pad[j]; 02665 } 02666 return s; 02667 } 02668 02674 string string::rpad(size_t newlen, const char* pad) { 02675 if (newlen <= strlen(buf)) return *this; 02676 string s(newlen + 1); 02677 size_t i, j, len1 = strlen(pad); 02678 strcpy(s.buf, buf); 02679 for (i = strlen(buf), j = 0; i < newlen; i++, j++) { 02680 if (j == len1) j = 0; 02681 s.buf[i] = pad[j]; 02682 } 02683 s.buf[i] = 0; 02684 return s; 02685 } 02686 02692 string string::lpad(size_t newlen, int pad) { 02693 char a[2]; 02694 a[0] = pad; a[1] = 0; 02695 return lpad(newlen, a); 02696 } 02697 02703 string string::rpad(size_t newlen, int pad) { 02704 char a[2]; 02705 a[0] = pad; a[1] = 0; 02706 return rpad(newlen, a); 02707 } 02708 02713 string string::squeeze(const char* chrs) { 02714 string s(strlen(buf) + 1); 02715 size_t i, k; 02716 if (!chrs) { 02717 for (i = 0, k = 0; buf[i]; i++, k++) { 02718 s.buf[k] = buf[i]; 02719 while (buf[i] == buf[i + 1]) i++; 02720 } 02721 } else { 02722 for (i = 0, k = 0; buf[i]; i++, k++) { 02723 s.buf[k] = buf[i]; 02724 if (strchr(chrs, buf[i])) 02725 while (buf[i] == buf[i + 1]) i++; 02726 } 02727 } 02728 s.buf[k] = 0; 02729 return s; 02730 } 02731 02736 string string::squeeze(int chr) { 02737 char a[2]; 02738 a[0] = chr; a[1] = 0; 02739 return squeeze(a); 02740 } 02741 02746 string string::ctypes(int (*cfunc)(int)) { 02747 if (empty()) return *this; 02748 string s(strlen(buf) + 1); 02749 register size_t i, j; 02750 for (i = 0, j = 0; buf[i]; i++) 02751 if (cfunc(buf[i])) s.buf[j++] = buf[i]; 02752 s.buf[j] = 0; 02753 return s; 02754 } 02755 02760 string string::ctypes(const char* chrs) { 02761 if (empty()) return *this; 02762 string s(strlen(buf) + 1); 02763 register size_t i, j; 02764 for (i = 0, j = 0; buf[i]; i++) 02765 if (strchr(chrs, buf[i])) s.buf[j++] = buf[i]; 02766 s.buf[j] = 0; 02767 return s; 02768 } 02769 02774 bool string::isctype(int (*cfunc)(int)) { 02775 if (empty()) return false; 02776 register size_t i; 02777 for (i = 0; buf[i]; i++) 02778 if (!cfunc(buf[i])) return false; 02779 return true; 02780 } 02781 02786 bool string::isctype(const char* chrs) { 02787 if (empty()) return false; 02788 register size_t i; 02789 for (i = 0; buf[i]; i++) 02790 if (!strchr(chrs, buf[i])) return false; 02791 return true; 02792 } 02793 02797 string string::alnums() { return ctypes(::isalnum); } 02798 02802 string string::alphas() { return ctypes(::isalpha); } 02803 02807 string string::cntrls() { return ctypes(::iscntrl); } 02808 02812 string string::digits() { return ctypes(::isdigit); } 02813 02817 string string::graphs() { return ctypes(::isgraph); } 02818 02822 string string::puncts() { return ctypes(::ispunct); } 02823 02827 string string::lowers() { return ctypes(::islower); } 02828 02832 string string::prints() { return ctypes(::isprint); } 02833 02837 string string::spaces() { return ctypes(::isspace); } 02838 02842 string string::uppers() { return ctypes(::isupper); } 02843 02847 string string::xdigits() { return ctypes(::isxdigit); } 02848 02852 bool string::isalnum() { return isctype(::isalnum); } 02853 02857 bool string::isalpha() { return isctype(::isalpha); } 02858 02862 bool string::iscntrl() { return isctype(::iscntrl); } 02863 02867 bool string::isdigit() { return isctype(::isdigit); } 02868 02872 bool string::isgraph() { return isctype(::isgraph); } 02873 02877 bool string::islower() { return isctype(::islower); } 02878 02882 bool string::isprint() { return isctype(::isprint); } 02883 02887 bool string::ispunct() { return isctype(::ispunct); } 02888 02892 bool string::isspace() { return isctype(::isspace); } 02893 02897 bool string::isupper() { return isctype(::isupper); } 02898 02902 bool string::isxdigit() { return isctype(::isxdigit); } 02903 02913 string string::inc() { 02914 string s(buf); 02915 register char carry = 0; 02916 size_t i = strlen(s.buf) - 1; 02917 long j; 02918 do { 02919 if (s.buf[i] == 'z' || s.buf[i] == 'Z') { 02920 carry = 1; 02921 s.buf[i] = s.buf[i] - 25; 02922 } else if (s.buf[i] == '9') { 02923 carry = 1; 02924 s.buf[i] = '0'; 02925 } else if (::isalnum(s.buf[i])) { 02926 carry = 0; 02927 s.buf[i] = s.buf[i] + 1; 02928 break; 02929 } 02930 } while (i--); 02931 if (carry) { 02932 j = s.pbrk("Aa0"); 02933 if (s.buf[j] == '0') 02934 s = s.ins(j, '1'); 02935 else if (s.buf[j] == 'a') 02936 s = s.ins(j, 'a'); 02937 else if (s.buf[j] == 'A') 02938 s = s.ins(j, 'A'); 02939 } 02940 return s; 02941 } 02942 02947 string string::add(int n) { 02948 register int i; 02949 string s(buf); 02950 for (i = 0; i < n; i++) s = s.inc(); 02951 return s; 02952 } 02953 02958 string string::sub(int n) { 02959 register int i; 02960 string s(buf); 02961 for (i = 0; i < n; i++) s = s.dec(); 02962 return s; 02963 } 02964 02968 string string::incn() { 02969 string s(buf); 02970 register char carry = 0; 02971 size_t i = strlen(s.buf) - 1; 02972 long j; 02973 do { 02974 if (s.buf[i] == '9') { 02975 carry = 1; 02976 s.buf[i] = '0'; 02977 } else if (::isdigit(s.buf[i])) { 02978 carry = 0; 02979 s.buf[i] = s.buf[i] + 1; 02980 break; 02981 } 02982 } while (i--); 02983 if (carry) 02984 s = s.ins(s.chr('0'), '1'); 02985 return s; 02986 } 02987 02997 string string::dec() { 02998 string s(buf); 02999 register char borrow = 0; 03000 long last = -1; 03001 size_t i = strlen(s.buf) - 1; 03002 do { 03003 if (s.buf[i] == 'a' || s.buf[i] == 'A') { 03004 borrow = 1; 03005 s.buf[i] = s.buf[i] + 25; 03006 } else if (s.buf[i] == '0') { 03007 borrow = 1; 03008 s.buf[i] = '9'; 03009 } else if (::isalnum(s.buf[i])) { 03010 borrow = 0; 03011 s.buf[i] = s.buf[i] - 1; 03012 if (s.buf[i] == '0'/* || buf [i] == 'a' || buf[i] == 'A'*/) 03013 last = i; 03014 break; 03015 } 03016 } while (i--); 03017 if (borrow) 03018 if (s.pbrk("9zZ") != s.rpbrk("9zZ")) 03019 s = s.rm(s.pbrk("9zZ"), 1); 03020 else { 03021 long c = s.pbrk("9zZ"); 03022 if (::isalpha(s.buf[c])) s.buf[c] = s.buf[c] - 25; 03023 else if (::isdigit(s.buf[c])) s.buf[c] = '0'; 03024 } 03025 if (last > -1) 03026 if (s.pbrk("1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz") == last && 03027 s.rpbrk("1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz") != last) 03028 s = s.rm(last, 1); 03029 return s; 03030 } 03031 03035 string string::decn() { 03036 string t(buf); 03037 register char borrow = 0; 03038 long last = -1, s; 03039 size_t i = strlen(t.buf) - 1; 03040 do { 03041 if (t.buf[i] == '0') { 03042 borrow = 1; 03043 t.buf[i] = '9'; 03044 } else if (::isdigit(t.buf[i])) { 03045 borrow = 0; 03046 t.buf[i] = t.buf[i] - 1; 03047 if (t.buf[i] == '0') 03048 last = i; 03049 break; 03050 } 03051 } while (i--); 03052 if (borrow) { 03053 s = t.chr('9'); 03054 if (s != t.rchr('9')) 03055 t = t.rm(s, 1); 03056 else t.buf[s] = '0'; 03057 } 03058 if (last > -1) 03059 if (t.pbrk("1234567890") == last && 03060 t.rpbrk("1234567890") != last) 03061 t = t.rm(last, 1); 03062 return t; 03063 } 03064 03065 string string::add(const char* s) { 03066 string t(s); 03067 string u(buf); 03068 t = t.alnums(); 03069 if (t == 'a' || t == 'A' || t == '0') { 03070 u = u.inc(); 03071 return u; 03072 } else if (u == 'a' || u == 'A' || u == '0') { 03073 u = t; 03074 u = u.inc(); 03075 return u; 03076 } 03077 do { 03078 u = u.inc(); 03079 t = t.dec(); 03080 } while (t != 'a' && t != 'A' && t != '0' && t.len()); 03081 if (t == 'a' || t == 'A') u = u.inc(); 03082 return u; 03083 } 03084 string string::sub(const char* s) { 03085 string t(s); 03086 string u(buf); 03087 t = t.alnums(); 03088 if (t == 'a' || t == 'A' || t == '0') { 03089 u = u.dec(); 03090 return u; 03091 } else if (u == 'a' || u == 'A' || u == '0') { 03092 u = t; 03093 u = u.dec(); 03094 return u; 03095 } 03096 do { 03097 u = u.dec(); 03098 t = t.dec(); 03099 } while (t != 'a' && t != 'A' && t != '0' && t.len()); 03100 if (t == 'a' || t == 'A') u = u.dec(); 03101 return u; 03102 } 03103 03108 string string::chomp(char c) { 03109 char x[2]; 03110 x[0] = c; x[1] = 0; 03111 return chomp(x); 03112 } 03113 03118 string string::munch(char c) { 03119 char x[2]; 03120 x[0] = c; x[1] = 0; 03121 return munch(x); 03122 } 03123 03128 string string::addn(int n) { string s(buf); for (; n; n--) s = s.incn(); return s; } 03129 string string::addn(const char* s) { 03130 string t(s); 03131 string u(buf); 03132 u = u.addn(atoi(t.digits())); 03133 return u; 03134 } 03135 03140 string string::subn(int n) { string s(buf); for (; n; n--) s = s.decn(); return s; } 03141 string string::subn(const char* s) { 03142 string t(s); 03143 string u(buf); 03144 u = u.subn(atoi(t.digits())); 03145 return u; 03146 } 03147 03151 unsigned short string::cksum() { 03152 size_t i; 03153 unsigned short sum = 0; 03154 for (i = 0; buf[i]; i++) { 03155 sum = (sum >> 1) + ((sum & 1) << 15); 03156 sum += buf[i]; 03157 sum &= 0xffff; 03158 } 03159 return sum; 03160 } 03161 03162 string& string::operator =(string s) { 03163 if (s.empty()) { clear(); return *this; } 03164 if (buf) free(buf); 03165 buf = s.buf; 03166 mlen = s.msize(); 03167 s.buf = 0; 03168 return *this; 03169 } 03170 03171 string& string::operator =(const char* s) { 03172 if (s == 0) { clear(); return *this; } 03173 realloc(strlen(s) + 1); 03174 strcpy2(buf, s); 03175 return *this; 03176 } 03177 /*string& string::operator =(char c) { 03178 ::puts("char"); 03179 this->realloc(2); 03180 buf[0] = c; buf[1] = 0; 03181 return *this; 03182 }*/ 03183 03188 string string::operator +(const char* str) { return this->cat(str); } 03189 03194 string string::operator +(char c) { return this->cat(c); } 03195 03200 string& string::operator +=(const char* str) { *this = this->cat(str); return *this; } 03201 03206 string& string::operator +=(char c) { *this = this->cat(c); return *this; } 03207 03212 string string::operator -(const char* str) { return this->prep(str); } 03213 03218 string string::operator -(char c) { return this->prep(c); } 03219 03224 string& string::operator -=(const char* str) { *this = this->prep(str); return *this; } 03225 03230 string& string::operator -=(char c) { *this = this->prep(c); return *this; } 03231 03236 bool string::operator ==(const char* str) { if (!buf) return false; return !strcmp(buf, str); } 03237 03242 bool string::operator ==(char c) { if (!buf) return false; if (buf[0] == c && buf[1] == 0) return true; return false; } 03243 03248 bool string::operator !=(const char* str) { if (!buf) return true; return strcmp(buf, str); } 03249 03254 bool string::operator != (char c) { if (!buf) return true; if (buf[0] != c) return true; return false; } 03255 03260 char& string::operator [](int i) { realloc(i + 1); return this->buf[i]; } 03261 03266 string string::operator *(int i) { 03267 string s(strlen(buf) * i + 1); 03268 strcpy(s.buf, buf); 03269 for (i--; i > 0; i--) 03270 strcat(s.buf, buf); 03271 return s; 03272 } 03273 03278 string& string::operator *=(int i) { 03279 *this = this->operator*(i); 03280 return *this; 03281 } 03282 03286 string string::operator ()() { return this->qx(); } 03287 03291 string& string::operator ++() { *this = this->incn(); return *this; } 03292 03296 string string::operator ++(int foo) { string s(buf); *this = this->incn(); return s; } 03297 03301 string& string::operator --() { *this = this->decn(); return *this; } 03302 03306 string string::operator --(int foo) { string s(buf); *this = this->decn(); return s; } 03307 03308 //io::output& operator<< (io::output& o, string s) { o.operator<<(s.buf); return o; } 03309 //io::input& operator>> (io::input& o, string& s) { o.operator>>(s.buf); return o; } 03310 03311 io::input& io::input::operator>> (string& s) { return operator>>(s.buf); } 03312 03316 int string::cmpstr(const char* s, ...) { 03317 va_list v; 03318 va_start(v, s); 03319 const char* c; 03320 int i = 0; 03321 for (c = s; c != NULL; c = va_arg(v, const char*), i++) 03322 if (!strcmp(buf, c)) break; 03323 va_end(v); 03324 if (c == NULL) return -1; 03325 return i; 03326 } 03327 03331 int string::cmpinstr(const char* s, ...) { 03332 va_list v; 03333 va_start(v, s); 03334 const char* c; 03335 int i = 0; 03336 for (c = s; c != NULL; c = va_arg(v, const char*), i++) 03337 if (strstr(buf, c)) break; 03338 va_end(v); 03339 if (c == NULL) return -1; 03340 return i; 03341 } 03342 03346 int string::cmpleft(const char* s, ...) { 03347 va_list v; 03348 va_start(v, s); 03349 register const char* c; 03350 int i = 0; 03351 for (c = s; c != NULL; c = va_arg(v, const char*), i++) 03352 if (!strncmp(buf, c, strlen(c))) break; 03353 va_end(v); 03354 if (c == NULL) return -1; 03355 return i; 03356 } 03357 03361 int string::cmpright(const char* s, ...) { 03362 va_list v; 03363 va_start(v, s); 03364 const char* c; 03365 register size_t k = strlen(buf); 03366 int i = 0; 03367 for (c = s; c != NULL; c = va_arg(v, const char*), i++) 03368 if (!strncmp(buf + k - strlen(c), c, strlen(c))) break; 03369 va_end(v); 03370 if (c == NULL) return -1; 03371 return i; 03372 } 03373 03374 int fs::file::putc(int c) { 03375 register int i = fputc(c, fd); 03376 if (i == EOF) { 03377 errnum = errno; 03378 if (feof(fd)) drain(); 03379 else if (ferror(fd)) kill(); 03380 return EOF; 03381 } else { heal(); return i; } 03382 } 03383 03384 int fs::file::getc() { 03385 register int i = fgetc(fd); 03386 if (i == EOF) { 03387 errnum = errno; 03388 if (feof(fd)) drain(); 03389 else if (ferror(fd)) kill(); 03390 else hurt(); 03391 return EOF; 03392 } else { heal(); return i; } 03393 } 03394 03395 /*string fs::file::gets(int size) { 03396 string s; 03397 int i = 32, j = 0; 03398 register int c; 03399 s.realloc(i); 03400 for (c = getc(); ; c = getc(), j++) { 03401 if (size) if (j >= size) break; 03402 if (j >= i - 4) { i *= 2; s.realloc(i); } 03403 switch (c) { 03404 case EOF: s.buf[0] = 0; return s; 03405 case '\n': s.buf[j] = '\n'; s.buf[++j] = 0; return s; 03406 default: s.buf[j] = c; 03407 } 03408 } 03409 s.buf[j] = 0; 03410 return s; 03411 }*/ 03412 03435 FILE* fs::file::open(const char* fname, const char* mode) { 03436 filename = fname; 03437 if ((fd = fopen(fname, mode)) == NULL) { 03438 errnum = errno; 03439 kill(); 03440 } else heal(); 03441 return fd; 03442 } 03443 03456 FILE* fs::file::dopen(int fh, const char* mode) { 03457 filename.clear(); 03458 filename.printf("%ld", fd); 03459 if ((fd = fdopen(fh, mode)) == NULL) { 03460 errnum = errno; 03461 kill(); 03462 } else heal(); 03463 return fd; 03464 } 03465 03475 FILE* fs::file::reopen(const char* fname, const char* mode) { 03476 filename = fname; 03477 if (freopen(fname, mode, fd) == NULL) { 03478 errnum = errno; 03479 kill(); 03480 return NULL; 03481 } 03482 heal(); 03483 return fd; 03484 } 03485 03491 bool fs::file::close() { 03492 if (fclose(fd) == EOF) { 03493 errnum = errno; 03494 kill(); 03495 return false; 03496 } else return true; 03497 drain(); 03498 } 03499 03507 bool fs::file::flush() { 03508 if (fflush(fd) == EOF) { 03509 errnum = errno; 03510 kill(); 03511 return false; 03512 } else { heal(); return true; } 03513 } 03514 03529 bool fs::file::seek(long offset, int whence) { 03530 03531 if (!fseek(fd, offset, whence)) { 03532 heal(); 03533 return true; 03534 } else { 03535 errnum = errno; 03536 hit(); 03537 return false; 03538 } 03539 } 03540 03546 long fs::file::tell() { 03547 register long i = ftell(fd); 03548 if (i == -1) { 03549 errnum = errno; 03550 hit(); 03551 return -1; 03552 } else { 03553 heal(); 03554 return i; 03555 } 03556 } 03557 03563 bool fs::file::rewind() { return seek(0L, SEEK_SET); } 03564 03570 bool fs::file::unwind() { return seek(0L, SEEK_END); } 03571 03578 bool fs::file::ffwd(long offset) { return seek(offset, SEEK_CUR); } 03579 03585 bool fs::file::prev(long offset) { return seek(offset * -1, SEEK_CUR); } 03586 03593 bool fs::file::nobuf() { 03594 if (!setvbuf(fd, NULL, _IONBF, 0)) { 03595 heal(); return true; 03596 } else { errnum = errno; hit(); return false; } 03597 } 03598 03606 bool fs::file::lbuf() { 03607 if (!setvbuf(fd, (char*)NULL, _IOLBF, 0)) { 03608 heal(); return true; 03609 } else { errnum = errno; hit(); return false; } 03610 } 03611 03622 bool fs::file::fbuf(char* buf, size_t size) { 03623 if (!setvbuf(fd, buf, _IOFBF, size)) { 03624 heal(); return true; 03625 } else { errnum = errno; hit(); return false; } 03626 } 03627 03636 int fs::file::ungetc(int c) { 03637 register int i = ::ungetc(c, fd); 03638 if (i == EOF) { hit(); return EOF; } 03639 else { errnum = errno; heal(); return i; } 03640 } 03641 03643 fs::file::file(const char* name, const char* mode) { open(name, mode); } 03645 fs::file::file(FILE* f) { fd = f; } 03647 fs::file::file(int fh, const char* mode) { dopen(fh, mode); } 03648 03649 int net::socket::tcp::putc(int c) { 03650 char t = c; 03651 switch (::send(fd, &t, 1, 0)) { 03652 case 0: errnum = errno; hurt(); return EOF; 03653 case -1: errnum = errno; kill(); return EOF; 03654 default: heal(); return c; 03655 } 03656 } 03657 03658 int net::socket::tcp::getc() { 03659 int a; 03660 char c; 03661 switch (::recv(fd, &c, 1, 0)) { 03662 case 0: errnum = errno; drain(); return EOF; 03663 #ifdef _WIN32 03664 case SOCKET_ERROR: errnum = errno; kill(); return EOF; 03665 #else 03666 case -1: errnum = errno; kill(); return EOF; 03667 #endif 03668 default: heal(); a = c; return a; 03669 } 03670 } 03671 03681 string io::input::gets(int size) { 03682 string s; 03683 int i; 03684 register int c; 03685 for (i = 0; ; i++) { 03686 if (size) if (i >= size) return s; 03687 c = getc(); 03688 switch (c) { 03689 case EOF: return s; 03690 case '\n': s += '\n'; return s; 03691 default: s += c; 03692 } 03693 } 03694 return s; 03695 } 03696 03697 /*string net::socket::tcp::gets(int size) { 03698 string s; 03699 int i; 03700 register int c; 03701 for (i = 0; ; i++) { 03702 if (size) if (i >= size) break; 03703 c = getc(); 03704 switch (c) { 03705 case EOF: return s; 03706 case '\n': s += '\n'; return s; 03707 default: s += c; 03708 } 03709 } 03710 return s; 03711 }*/ 03712 /*string net::socket::tcp::gets(int size) { 03713 string s; 03714 int i = 32, j = 0; 03715 register int c; 03716 s.realloc(i); 03717 for (c = getc(); ; c = getc(), j++) { 03718 if (size) if (j >= size) break; 03719 if (j >= i - 4) { i *= 2; s.realloc(i); } 03720 switch (c) { 03721 case EOF: s.buf[0] = 0; return s; 03722 case '\n': s.buf[j] = '\n'; s.buf[++j] = 0; return s; 03723 default: s.buf[j] = c; 03724 } 03725 } 03726 s.buf[j] = 0; 03727 return s; 03728 }*/ 03729 03735 int net::socket::tcp::send(const char* buf, size_t len) { 03736 register int i = ::send(fd, buf, len, 0); 03737 if (i == -1) { errnum = errno; kill(); return EOF; } 03738 else if (i == 0) { errnum = errno; hurt(); return EOF; } 03739 else { heal(); return i; } 03740 } 03741 03751 int net::socket::tcp::recv(char* buf, size_t len) { 03752 register int i = ::recv(fd, buf, len, 0); 03753 if (i == -1) { errnum = errno; kill(); return EOF; } 03754 else if (i == 0) { errnum = errno; drain(); return EOF; } 03755 else { heal(); return i; } 03756 } 03757 03763 bool net::socket::tcp::connect(const char* host, const char* port) { 03764 struct addrinfo hints, *ai; 03765 memset(&hints, 0, sizeof(struct addrinfo)); 03766 hints.ai_protocol = IPPROTO_TCP; 03767 hints.ai_socktype = SOCK_STREAM; 03768 hints.ai_family = AF_UNSPEC; 03769 if (getaddrinfo(host, port, &hints, &ai)) { 03770 #ifndef _WIN32 03771 errnum = errno; 03772 #else 03773 errnum = wsatoerr(WSAGetLastError()); 03774 #endif 03775 kill(); 03776 return false; 03777 } 03778 if (ai->ai_family != af) { 03779 bool b = blocking(); 03780 fd = ::socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); 03781 #ifdef _WIN32 03782 if (fd == INVALID_SOCKET) { 03783 errnum = wsatoerr(WSAGetLastError()); 03784 #else 03785 if (fd == -1) { 03786 errnum = errno; 03787 #endif 03788 kill(); 03789 return false; 03790 } 03791 blocking(b); 03792 af = ai->ai_family; 03793 } 03794 if (::connect(fd, ai->ai_addr, ai->ai_addrlen)) { 03795 #ifndef _WIN32 03796 errnum = errno; 03797 #else 03798 errnum = wsatoerr(WSAGetLastError()); 03799 #endif 03800 kill(); 03801 return false; 03802 } 03803 heal(); 03804 freeaddrinfo(ai); 03805 return true; 03806 } 03807 03813 bool net::socket::tcp::listen(const char* port, int backlog) { 03814 struct addrinfo hints, *ai; 03815 memset(&hints, 0, sizeof(struct addrinfo)); 03816 hints.ai_family = AF_UNSPEC; 03817 hints.ai_socktype = SOCK_STREAM; 03818 hints.ai_protocol = IPPROTO_TCP; 03819 hints.ai_flags = AI_PASSIVE; 03820 if (getaddrinfo(0, port, &hints, &ai)) { 03821 #ifndef _WIN32 03822 errnum = errno; 03823 #else 03824 errnum = wsatoerr(WSAGetLastError()); 03825 #endif 03826 kill(); 03827 return false; 03828 } 03829 if (ai->ai_family != af) { 03830 bool b = blocking(); 03831 fd = ::socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); 03832 #ifdef _WIN32 03833 if (fd == INVALID_SOCKET) { 03834 errnum = wsatoerr(WSAGetLastError()); 03835 #else 03836 if (fd == -1) { 03837 errnum = errno; 03838 #endif 03839 kill(); 03840 return false; 03841 } 03842 blocking(b); 03843 af = ai->ai_family; 03844 } 03845 if (bind(fd, ai->ai_addr, ai->ai_addrlen)) { 03846 #ifndef _WIN32 03847 errnum = errno; 03848 #else 03849 errnum = wsatoerr(WSAGetLastError()); 03850 #endif 03851 freeaddrinfo(ai); return false; 03852 } 03853 freeaddrinfo(ai); 03854 if (::listen(fd, backlog) == -1) { 03855 #ifndef _WIN32 03856 errnum = errno; 03857 #else 03858 errnum = wsatoerr(WSAGetLastError()); 03859 #endif 03860 kill(); 03861 return false; 03862 } 03863 heal(); 03864 return true; 03865 } 03866 03867 03878 bool net::socket::tcp::accept(net::socket::tcp& f) { 03879 if ((f.fd = ::accept(fd, NULL, NULL)) == -1) { 03880 #ifndef _WIN32 03881 errnum = errno; 03882 #else 03883 errnum = wsatoerr(WSAGetLastError()); 03884 #endif 03885 hurt(); 03886 return false; 03887 } else return true; 03888 } 03889 03890 string::string(const data& s) { 03891 fmt.bin(0); 03892 buf = 0; pos = 0; mlen = s.len(); 03893 if (s.buf) { 03894 buf = (char*)malloc(mlen); 03895 strcpy(buf, s.buf); 03896 } 03897 } 03898 03899 string& string::operator= (const data& d) { 03900 return this->operator= (d.buf); 03901 } 03902 03903 data net::http::download(const char* url, const char* port) { 03904 data d; 03905 net::socket::tcp sock; 03906 string s = url; 03907 s = s.munch("http://"); 03908 unless (sock.connect(s.burn('/'), port)) return d; 03909 sock << "GET /" << s.slurp('/') << " HTTP/1.1\r\nHost: " << s.burn('/') << "\r\n\r\n"; 03910 s = sock.drink("\r\n\r\n"); 03911 unless (s.slurp("Content-Length: ").burn('\r').empty()) 03912 d = sock.read(1, stoi<size_t>(s.slurp("Content-Length: ").burn('\r'))); 03913 else d = sock.dump(); 03914 sock.close(); 03915 return d; 03916 } 03917 03921 bool net::socket::tcp::close() { 03922 drain(); 03923 #ifdef _WIN32 03924 if (!closesocket(fd)) 03925 { tcp(); return true; } 03926 else { errnum = wsatoerr(WSAGetLastError()); tcp();return false; } 03927 #else 03928 if (::close(fd) == -1) { 03929 errnum = errno; 03930 tcp(); 03931 return false; 03932 } else { tcp();return true;} 03933 #endif 03934 } 03935 03943 bool net::socket::tcp::blocking(int i) { 03944 #ifndef _WIN32 03945 if (i == -1) 03946 return fcntl(fd, F_GETFD) & O_NONBLOCK; 03947 else if (i == 0) 03948 return !fcntl(fd, fcntl(fd, F_GETFD) | O_NONBLOCK); 03949 else if (i) 03950 return !fcntl(fd, fcntl(fd, F_GETFD) & ~O_NONBLOCK); 03951 #else 03952 unsigned long t; 03953 if (i == -1) return blking; 03954 else if (i == 1) { 03955 t = 1; 03956 return !ioctlsocket(fd, FIONBIO, &t); 03957 } else if (i == 0) { 03958 t = 0; 03959 return !ioctlsocket(fd, FIONBIO, &t); 03960 } 03961 #endif 03962 return true; 03963 } 03964 03965 net::socket::tcp::tcp() { 03966 #ifdef _WIN32 03967 struct WSAData* wd = (struct WSAData*)malloc(sizeof(struct WSAData)); 03968 int i; 03969 if (i = WSAStartup(MAKEWORD(2, 0), wd)) { 03970 errnum = wsatoerr(i); 03971 kill(); 03972 free(wd); 03973 return; 03974 } 03975 free(wd); 03976 blking = true; 03977 #endif 03978 af = AF_INET; 03979 fd = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 03980 #ifdef _WIN32 03981 if (fd == INVALID_SOCKET) { 03982 errnum = wsatoerr(WSAGetLastError()); 03983 kill(); 03984 return; 03985 } 03986 #else 03987 if (fd == -1) { errnum = errno; kill(); return; } 03988 #endif 03989 03990 drain(); 03991 } 03992 #ifdef _WIN32 03993 net::socket::tcp::~tcp() { 03994 WSACleanup(); 03995 } 03996 #endif 03997 04001 bool net::socket::tcp::connected() { return !ip().empty(); } 04002 04006 string net::socket::tcp::ip() { 04007 string s; 04008 #ifdef _WIN32 04009 DWORD d = 40; 04010 #endif 04011 s.realloc(40); 04012 s.clear(); 04013 struct sockaddr_storage ss; 04014 socklen_t sslen = sizeof(struct sockaddr_storage); 04015 if (::getpeername(this->fd, (struct sockaddr*)&ss, &sslen)) return s; 04016 if (ss.ss_family == AF_INET) 04017 #ifndef _WIN32 04018 inet_ntop(ss.ss_family, &((struct sockaddr_in*)&ss)->sin_addr, s.buf, 40); 04019 #else 04020 WSAAddressToStringA((struct sockaddr*)&ss, sizeof(struct sockaddr_storage), 0, s.buf, &d); 04021 #endif 04022 else if (ss.ss_family == AF_INET6) 04023 #ifndef _WIN32 04024 inet_ntop(ss.ss_family, &((struct sockaddr_in6*)&ss)->sin6_addr, s.buf, 40); 04025 #else 04026 WSAAddressToStringA((struct sockaddr*)&ss, sizeof(struct sockaddr_storage), 0, s.buf, &d); 04027 #endif 04028 return s; 04029 } 04030 04034 string net::socket::tcp::name() { 04035 string s; 04036 s.realloc(256); 04037 s.clear(); 04038 struct sockaddr sa; 04039 socklen_t slen = sizeof(struct sockaddr); 04040 ::getpeername(this->fd, &sa, &slen); 04041 getnameinfo(&sa, slen, s.buf, 256, 0, 0, 0); 04042 return s; 04043 } 04044 04045 string object::type() { return string("object"); } 04046 object::operator string () { return string("(null)"); } 04047 04048 string net::ipaddr::type() { return string("net::ipaddr"); } 04049 net::ipaddr::operator string () { 04050 string s(42); 04051 #ifndef _WIN32 04052 inet_ntop(this->af, &(this->addr4), s.buf, 42); 04053 #else 04054 DWORD d = 42; 04055 struct sockaddr_in si; 04056 struct sockaddr_in6 sj; 04057 memset(&si, 0, sizeof(struct sockaddr_in)); 04058 memset(&sj, 0, sizeof(struct sockaddr_in6)); 04059 if (af == AF_INET) { 04060 si.sin_family = AF_INET; 04061 memmove(&(si.sin_addr), &(this->addr4), sizeof(struct in_addr)); 04062 WSAAddressToStringA( 04063 (struct sockaddr*)&si, 04064 sizeof(struct sockaddr_in), 04065 NULL, 04066 s.buf, 04067 &d 04068 ); 04069 } else if (af == AF_INET6) { 04070 sj.sin6_family = AF_INET6; 04071 sj.sin6_port = 0; 04072 memmove(&(sj.sin6_addr), &(this->addr6), sizeof(struct in6_addr)); 04073 WSAAddressToStringA( 04074 (struct sockaddr*)&sj, 04075 sizeof(struct sockaddr_in6), 04076 NULL, 04077 s.buf, 04078 &d 04079 ); 04080 } 04081 04082 #endif 04083 return s; 04084 } 04085 #ifdef _WIN32 04086 void net::ipaddr::initwsa() { 04087 WSAData* wd = (struct WSAData*)malloc(sizeof(struct WSAData)); 04088 WSAStartup(MAKEWORD(2, 0), wd); 04089 free(wd); 04090 } 04091 #endif 04092 net::ipaddr::ipaddr(const char* s) { 04093 #ifdef _WIN32 04094 initwsa(); 04095 #endif 04096 this->operator=(s); } 04097 net::ipaddr::ipaddr(struct in_addr* s) { 04098 #ifdef _WIN32 04099 initwsa(); 04100 #endif 04101 this->operator=(s); } 04102 net::ipaddr::ipaddr(struct in6_addr* s) { 04103 #ifdef _WIN32 04104 initwsa(); 04105 #endif 04106 this->operator=(s); } 04107 04108 bool net::ipaddr::cmp(const char* s, struct in_addr * ia4, struct in6_addr * ia6, int op) { 04109 net::ipaddr ip; 04110 register size_t t; 04111 if (s) ip = s; 04112 else if (ia4) ip = ia4; 04113 else if (ia6) ip = ia6; 04114 if (af == AF_INET) t = sizeof(struct in_addr); 04115 else if (af == AF_INET6) t = sizeof(struct in6_addr); 04116 if (ip.af != af) return false; 04117 switch (op) { 04118 case 0: /* == */ 04119 return !memcmp(&addr4, &(ip.addr4), t); 04120 case 1: /* != */ 04121 return memcmp(&addr4, &(ip.addr4), t); 04122 case 2: /* > */ 04123 return memcmp(&addr4, &(ip.addr4), t) > 0; 04124 case 3: /* >= */ 04125 return memcmp(&addr4, &(ip.addr4), t) >= 0; 04126 case 4: /* < */ 04127 return memcmp(&addr4, &(ip.addr4), t) < 0; 04128 case 5: /* <= */ 04129 return memcmp(&addr4, &(ip.addr4), t) <= 0; 04130 } 04131 return false; 04132 } 04133 04134 bool net::ipaddr::operator== (const char* s) { return this->cmp(s, 0, 0, 0); } 04135 bool net::ipaddr::operator!= (const char* s) { return this->cmp(s, 0, 0, 1); } 04136 bool net::ipaddr::operator> (const char* s) { return this->cmp(s, 0, 0, 2); } 04137 bool net::ipaddr::operator>= (const char* s) { return this->cmp(s, 0, 0, 3); } 04138 bool net::ipaddr::operator< (const char* s) { return this->cmp(s, 0, 0, 4); } 04139 bool net::ipaddr::operator<= (const char* s) { return this->cmp(s, 0, 0, 5); } 04140 bool net::ipaddr::operator== (struct in_addr * s) { return this->cmp(0, s, 0, 0); } 04141 bool net::ipaddr::operator!= (struct in_addr * s) { return this->cmp(0, s, 0, 1); } 04142 bool net::ipaddr::operator> (struct in_addr * s) { return this->cmp(0, s, 0, 2); } 04143 bool net::ipaddr::operator>= (struct in_addr * s) { return this->cmp(0, s, 0, 3); } 04144 bool net::ipaddr::operator< (struct in_addr * s) { return this->cmp(0, s, 0, 4); } 04145 bool net::ipaddr::operator<= (struct in_addr * s) { return this->cmp(0, s, 0, 5); } 04146 bool net::ipaddr::operator== (struct in6_addr * s) { return this->cmp(0, 0, s, 0); } 04147 bool net::ipaddr::operator!= (struct in6_addr * s) { return this->cmp(0, 0, s, 1); } 04148 bool net::ipaddr::operator> (struct in6_addr * s) { return this->cmp(0, 0, s, 2); } 04149 bool net::ipaddr::operator>= (struct in6_addr * s) { return this->cmp(0, 0, s, 3); } 04150 bool net::ipaddr::operator< (struct in6_addr * s) { return this->cmp(0, 0, s, 4); } 04151 bool net::ipaddr::operator<= (struct in6_addr * s) { return this->cmp(0, 0, s, 5); } 04152 04159 net::ipaddr& net::ipaddr::operator= (const char* s) { 04160 int f; 04161 string t = s; 04162 union { struct in_addr ia; struct in6_addr ia6; } a; 04163 if (t.chr(':') > -1) f = AF_INET6; 04164 else if (t.isctype(".0123456789")) f = AF_INET; 04165 else { 04166 struct addrinfo *ai; 04167 if (getaddrinfo(s, 0, 0, &ai)) return *this; 04168 af = ai->ai_family; 04169 if (af == AF_INET) 04170 memmove(&addr4, &((struct sockaddr_in*)ai->ai_addr)->sin_addr, sizeof(struct sockaddr)); 04171 else if (af == AF_INET6) 04172 memmove(&addr6, &((struct sockaddr_in6*)ai->ai_addr)->sin6_addr, sizeof(struct sockaddr)); 04173 freeaddrinfo(ai); 04174 return *this; 04175 } 04176 #ifndef _WIN32 04177 if (inet_pton(f, s, &a) < 1) return *this; 04178 #else 04179 DWORD d = 42; 04180 int z = 42, foobar; 04181 char* crap = (char*)malloc(strlen(s) + 1); 04182 strcpy(crap, s); 04183 struct sockaddr_in sa4; 04184 struct sockaddr_in6 sa6; 04185 sa4.sin_family = AF_INET; 04186 sa6.sin6_family = AF_INET6; 04187 if (f == AF_INET) { 04188 foobar = sizeof(struct sockaddr_in); 04189 z = WSAStringToAddressA( 04190 crap, 04191 f, 04192 NULL, 04193 (struct sockaddr*)&sa4, 04194 &foobar 04195 ); 04196 memmove(&(a.ia), &(sa4.sin_addr), sizeof(struct in_addr)); 04197 } else if (f == AF_INET6) { 04198 foobar = sizeof(struct sockaddr_in6); 04199 z = WSAStringToAddressA( 04200 crap, 04201 f, 04202 NULL, 04203 (struct sockaddr*)&sa6, 04204 &foobar 04205 ); 04206 memmove(&(a.ia6), &(sa6.sin6_addr), sizeof(struct in6_addr)); 04207 } 04208 free(crap); 04209 if (z) return *this; 04210 #endif 04211 af = f; 04212 if (f == AF_INET) this->operator=(&(a.ia)); 04213 else if (f == AF_INET6) this->operator=(&(a.ia6)); 04214 return *this; 04215 } 04216 net::ipaddr& net::ipaddr::operator=(struct in_addr* s) { 04217 af = AF_INET; 04218 memmove(&addr4, s, sizeof(struct in_addr)); 04219 return *this; 04220 } 04221 net::ipaddr& net::ipaddr::operator=(struct in6_addr* s) { 04222 af = AF_INET6; 04223 memmove(&addr6, s, sizeof(struct in6_addr)); 04224 return *this; 04225 } 04226 04227 net::ipaddr net::ipaddr::operator+ (int i) { 04228 int m; 04229 if (af == AF_INET) { 04230 unsigned int j = ntohl(this->addr4.s_addr); 04231 unsigned char* k = (unsigned char*)&j; 04232 struct in_addr ia; 04233 for (m = 0; m < i; m++) { 04234 k[0]++; 04235 if (k[0] == 0) { 04236 k[1]++; 04237 if (k[1] == 0) { 04238 k[2]++; 04239 if (k[2] == 0) { 04240 k[3]++; 04241 } 04242 } 04243 } 04244 } 04245 ia.s_addr = htonl(j); 04246 return net::ipaddr(&ia); 04247 } else if (af == AF_INET6) { 04248 struct in6_addr ia; 04249 memmove(&ia, &addr6, sizeof(struct in6_addr)); 04250 unsigned short* us = (unsigned short*)&(ia.s6_addr); 04251 int j; 04252 /* --------------- LIKE A BOSS --------------- */ 04253 for (j = 0; j < i; j++) { 04254 us[7] = htons(ntohs(us[7]) + 1); 04255 if (!ntohs(us[7])) { 04256 us[6] = htons(ntohs(us[6]) + 1); 04257 if (!ntohs(us[6])) { 04258 us[5] = htons(ntohs(us[6]) + 1); 04259 if (!ntohs(us[5])) { 04260 us[4] = htons(ntohs(us[4]) + 1); 04261 if (!ntohs(us[4])) { 04262 us[3] = htons(ntohs(us[3]) + 1); 04263 if (!ntohs(us[3])) { 04264 us[2] = htons(ntohs(us[2]) + 1); 04265 if (!ntohs(us[2])) { 04266 us[1] = htons(ntohs(us[1]) + 1); 04267 if (!ntohs(us[1])) { 04268 us[0] = htons(ntohs(us[0]) + 1); 04269 } 04270 } 04271 } 04272 } 04273 } 04274 } 04275 } 04276 } 04277 return net::ipaddr(&ia); 04278 } 04279 } 04280 net::ipaddr net::ipaddr::operator- (int i) { 04281 int m; 04282 if (af == AF_INET) { 04283 unsigned int j = ntohl(this->addr4.s_addr); 04284 unsigned char* k = (unsigned char*)&j; 04285 struct in_addr ia; 04286 for (m = 0; m < i; m++) { 04287 k[0]--; 04288 if (k[0] == 0xff) { 04289 k[1]--; 04290 if (k[1] == 0xff) { 04291 k[2]--; 04292 if (k[2] == 0xff) { 04293 k[3]--; 04294 } 04295 } 04296 } 04297 } 04298 ia.s_addr = htonl(j); 04299 return net::ipaddr(&ia); 04300 } else if (af == AF_INET6) { 04301 struct in6_addr ia; 04302 memmove(&ia, &addr6, sizeof(struct in6_addr)); 04303 unsigned short* us = (unsigned short*)&(ia.s6_addr); 04304 int j; 04305 /* --------------- LIKE A BOSS --------------- */ 04306 for (j = 0; j < i; j++) { 04307 us[7] = htons(ntohs(us[7]) - 1); 04308 if (ntohs(us[7]) == 0xffff) { 04309 us[6] = htons(ntohs(us[6]) - 1); 04310 if (ntohs(us[6]) == 0xffff) { 04311 us[5] = htons(ntohs(us[5]) - 1); 04312 if (ntohs(us[5]) == 0xffff) { 04313 us[4] = htons(ntohs(us[4]) - 1); 04314 if (ntohs(us[4]) == 0xffff) { 04315 us[3] = htons(ntohs(us[3]) - 1); 04316 if (ntohs(us[3]) == 0xffff) { 04317 us[2] = htons(ntohs(us[2]) - 1); 04318 if (ntohs(us[2]) == 0xffff) { 04319 us[1] = htons(ntohs(us[1]) - 1); 04320 if (ntohs(us[1]) == 0xffff) { 04321 us[0] = htons(ntohs(us[0]) - 1); 04322 } 04323 } 04324 } 04325 } 04326 } 04327 } 04328 } 04329 } 04330 return net::ipaddr(&ia); 04331 } 04332 } 04333 net::ipaddr& net::ipaddr::operator+= (int i) { *this = this->operator+(i); return *this; } 04334 net::ipaddr& net::ipaddr::operator-= (int i) { *this = this->operator-(i); return *this; } 04335 net::ipaddr& net::ipaddr::operator++ () { *this = this->operator+(1); return *this; } 04336 net::ipaddr net::ipaddr::operator++ (int foo) { net::ipaddr i = *this; *this = this->operator+(1); return i; } 04337 net::ipaddr& net::ipaddr::operator-- () { *this = this->operator-(1); return *this; } 04338 net::ipaddr net::ipaddr::operator-- (int foo) { net::ipaddr i = *this; *this = this->operator-(1); return i; } 04339 04340 04349 bool net::socket::udp::bind(const char* port) { 04350 struct addrinfo hints, *ai; 04351 memset(&hints, 0, sizeof(struct addrinfo)); 04352 hints.ai_family = AF_INET; 04353 hints.ai_socktype = SOCK_DGRAM; 04354 hints.ai_protocol = IPPROTO_UDP; 04355 hints.ai_flags = AI_PASSIVE; 04356 if (getaddrinfo(0, port, &hints, &ai)) return false; 04357 if (::bind(fd, ai->ai_addr, ai->ai_addrlen)) return false; 04358 freeaddrinfo(ai); 04359 return true; 04360 } 04361 04367 void net::socket::udp::unbind() { 04368 #ifdef _WIN32 04369 closesocket(fd); 04370 #else 04371 close(fd); 04372 #endif 04373 fd = ::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 04374 } 04375 04382 int net::socket::udp::post(net::dgram dg) { 04383 struct sockaddr_in sa; 04384 sa.sin_family = AF_INET; 04385 sa.sin_port = htons(dg.port); 04386 memmove(&(sa.sin_addr), &(dg.ip.addr4), sizeof(struct in_addr)); 04387 return ::sendto(fd, dg.msg.buf, dg.msg.len(), 0, (struct sockaddr*)&sa, sizeof(struct sockaddr_in)); 04388 } 04389 04397 net::dgram net::socket::udp::get() { 04398 net::dgram dg; 04399 struct sockaddr_in sa; 04400 socklen_t sl = sizeof(struct sockaddr_in); 04401 until (this->check() > -1); 04402 dg.msg.realloc(this->check() + 1); 04403 ::recvfrom(fd, dg.msg.buf, dg.msg.len(), 0, (struct sockaddr*)&sa, &sl); 04404 dg.ip = &(sa.sin_addr); 04405 dg.port = ntohs(sa.sin_port); 04406 return dg; 04407 } 04408 04416 /*int net::socket::udp::send(const char* buf, size_t len) { 04417 struct sockaddr_in sa; 04418 sa.sin_family = AF_INET; 04419 sa.sin_port = htons(port); 04420 memmove(&(sa.sin_addr), &(peer.addr4), sizeof(struct in_addr)); 04421 return ::sendto(fd, buf, len, 0, (struct sockaddr*)&sa, sizeof(struct sockaddr_in)); 04422 }*/ 04423 04431 /*int net::socket::udp::recv(char* buf, size_t len) { 04432 struct sockaddr_in sa; 04433 socklen_t sl = sizeof(struct sockaddr_in); 04434 register int i = ::recvfrom(fd, buf, len, 0, (struct sockaddr*)&sa, &sl); 04435 peer = &(sa.sin_addr); 04436 return i; 04437 }*/ 04438 04439 /*int net::socket::udp::puts(const char* s) { 04440 struct sockaddr_in sa; 04441 sa.sin_family = AF_INET; 04442 sa.sin_port = htons(port); 04443 memmove(&(sa.sin_addr), &(peer.addr4), sizeof(struct in_addr)); 04444 register int i = ::sendto(fd, s, strlen(s), 0, (struct sockaddr*)&sa, sizeof(struct sockaddr_in)); 04445 switch (i) { 04446 case 0: hurt(); return EOF; 04447 case -1: kill(); return EOF; 04448 default: heal(); return i; 04449 } 04450 }*/ 04451 04452 int net::socket::tcp::puts(const char* s) { 04453 register int i = ::send(fd, s, strlen(s), 0); 04454 switch (i) { 04455 case 0: hurt(); return EOF; 04456 case -1: kill(); return EOF; 04457 default: heal(); return i; 04458 } 04459 } 04460 04461 net::socket::udp::udp() { 04462 #ifdef _WIN32 04463 struct WSAData* wd = (struct WSAData*)malloc(sizeof(struct WSAData)); 04464 WSAStartup(MAKEWORD(2, 0), wd); 04465 free(wd); 04466 #endif 04467 fd = ::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 04468 } 04469 net::socket::udp::~udp() { 04470 #ifdef _WIN32 04471 closesocket(fd); 04472 WSACleanup(); 04473 #else 04474 close(fd); 04475 #endif 04476 } 04477 04478 bool net::socket::tcp::ready() { 04479 fd_set rfd; 04480 #ifndef _WIN32 04481 struct timeval tv = {0, 0}; 04482 #else 04483 TIMEVAL tv = {0, 0}; 04484 #endif 04485 FD_ZERO(&rfd); 04486 FD_SET(fd, &rfd); 04487 select(fd + 1, &rfd, 0, 0, &tv); 04488 return FD_ISSET(fd, &rfd); 04489 } 04490 04494 int net::socket::udp::check() { 04495 int i = -1; 04496 #ifndef _WIN32 04497 ioctl(fd, FIONREAD, &i); 04498 #else 04499 ioctlsocket(fd, FIONREAD, (unsigned long*)&i); 04500 #endif 04501 if (i == 0) { 04502 #ifndef _WIN32 04503 struct pollfd pf; 04504 pf.fd = fd; 04505 pf.events = POLLIN; 04506 pf.revents = 0; 04507 poll(&pf, 1, 0); 04508 if (pf.revents & POLLIN) return 0; 04509 else return -1; 04510 #else 04511 fd_set pf; 04512 pf.fd_count = 1; 04513 pf.fd_array[0] = fd; 04514 TIMEVAL tv = {0, 0}; 04515 select(0, &pf, 0, 0, &tv); 04516 if (FD_ISSET(fd, &pf)) return 0; 04517 else return -1; 04518 #endif 04519 } else return i; 04520 } 04521 04522 string net::socket::udp::type() { return string("net::socket::udp"); } 04523 net::socket::udp::operator string () { string s; s << fd; return s;} 04524 04526 //net::socket::udp& net::socket::udp::to(const char* ip) { peer = ip; return *this; } 04528 //net::socket::udp& net::socket::udp::on(unsigned short p) { p = htons(p); return *this; } 04529 04530 /*net::socket::udp& net::socket::udp::operator= (const char* endpoint) { 04531 string s = endpoint; 04532 if (s[0] != '*') 04533 peer = s.burn('/'); 04534 if (!s.ends('*')) port = atoi(s.slurp('/')); 04535 return *this; 04536 }*/ 04537 04538 /*int net::socket::udp::getc() { 04539 int a; 04540 char c; 04541 struct sockaddr_in sa; 04542 socklen_t sl = sizeof(struct sockaddr_in); 04543 switch (::recvfrom(fd, &c, 1, 0, (struct sockaddr*)&sa, &sl)) { 04544 case 0: drain(); a = EOF; break; 04545 #ifdef _WIN32 04546 case SOCKET_ERROR: a = EOF; break; 04547 #else 04548 case -1: kill(); a = EOF; break; 04549 #endif 04550 default: heal(); a = c; break; 04551 } 04552 peer = &(sa.sin_addr); 04553 return a; 04554 } 04555 04556 int net::socket::udp::putc(int c) { 04557 register char d = c; 04558 struct sockaddr_in sa; 04559 sa.sin_family = AF_INET; 04560 sa.sin_port = htons(port); 04561 memmove(&(sa.sin_addr), &(peer.addr4), sizeof(struct in_addr)); 04562 switch (::sendto(fd, &d, 1, 0, (struct sockaddr*)&sa, sizeof(struct sockaddr_in))) { 04563 case 0: hurt(); return EOF; 04564 case -1: kill(); return EOF; 04565 default: heal(); return c; 04566 } 04567 }*/ 04568 04569 int console::putc(int c) { 04570 register int i = fputc(c, out); 04571 if (i == EOF) { 04572 if (feof(out)) drain(); 04573 else if (ferror(out)) kill(); 04574 return EOF; 04575 } else { heal(); return i; } 04576 } 04577 04578 int console::getc() { 04579 register int i = fgetc(in); 04580 if (i == EOF) { 04581 if (feof(in)) drain(); 04582 else if (ferror(in)) kill(); 04583 return EOF; 04584 } else { heal(); return i; } 04585 } 04586 /*string console::gets(int size) { 04587 string s; 04588 int i = 32, j = 0; 04589 register int c; 04590 s.realloc(i); 04591 for (c = getc(); ; c = getc(), j++) { 04592 if (size) if (j >= size) break; 04593 if (j >= i - 4) { i *= 2; s.realloc(i); } 04594 switch (c) { 04595 case EOF: s.buf[0] = 0; return s; 04596 case '\n': s.buf[j] = '\n'; s.buf[++j] = 0; return s; 04597 default: s.buf[j] = c; 04598 } 04599 } 04600 s.buf[j] = 0; 04601 return s; 04602 }*/ 04603 04620 #ifndef _WIN32 04621 int console::getch() { 04622 int i = ::fileno(in); 04623 struct termios oldt, newt; 04624 int ch; 04625 tcgetattr(i, &oldt); 04626 newt = oldt; 04627 newt.c_lflag &= ~(ICANON | ECHO); 04628 tcsetattr(i, TCSANOW, &newt); 04629 ch = getchar(); 04630 tcsetattr(i, TCSANOW, &oldt); 04631 return ch; 04632 } 04633 int console::getche() { 04634 int i = ::fileno(in); 04635 struct termios oldt, newt; 04636 int ch; 04637 tcgetattr(i, &oldt); 04638 newt = oldt; 04639 newt.c_lflag &= ~ICANON; 04640 newt.c_lflag &= ECHO; 04641 tcsetattr(i, TCSANOW, &newt); 04642 ch = getchar(); 04643 tcsetattr(i, TCSANOW, &oldt); 04644 return ch; 04645 } 04646 bool console::kbhit() { 04647 int i = ::fileno(in); 04648 struct termios oldt, newt; 04649 struct timeval tv; 04650 fd_set fds; 04651 int ret; 04652 tcgetattr(i, &oldt); 04653 newt = oldt; 04654 newt.c_lflag &= ~(ICANON | ECHO); 04655 tcsetattr(i, TCSANOW, &newt); 04656 tv.tv_sec = 0; 04657 tv.tv_usec = 0; 04658 FD_ZERO(&fds); 04659 FD_SET(i, &fds); 04660 select(i + 1, &fds, 0, 0, &tv); 04661 ret = FD_ISSET(i, &fds); 04662 tcsetattr(i, TCSANOW, &oldt); 04663 return ret; 04664 } 04665 console& console::putcr() { fputc('\r', out); fflush(out); return *this; } 04666 console& console::putbs() { fputc('\b', out); fflush(out); return *this; } 04667 console& console::cls() { fputs("\x1B[2J", out); return *this; } 04668 console& console::bel() { fputc('\a', out); fflush(out); return *this; } 04669 console& console::setxy(int x, int y) { sprintf(s, "\x1B[%d;%df", y, x); fputs(s, out); return *this; } 04670 console& console::setx(int x) { sprintf(s, "\x1B[%dd", x); fputs(s, out); return *this; } 04671 console& console::sety(int y) { sprintf(s, "\x1B%dG", y); fputs(s, out); return *this; } 04672 console& console::up(int n) { sprintf(s, "\x1B[%dA", n); fputs(s, out); return *this; } 04673 console& console::dn(int n) { sprintf(s, "\x1B[%dB", n); fputs(s, out); return *this; } 04674 console& console::rt(int n) { sprintf(s, "\x1B[%dC", n); fputs(s, out); return *this; } 04675 console& console::lt(int n) { sprintf(s, "\x1B[%dD", n); fputs(s, out); return *this; } 04676 console& console::rmln() { fputs("\x1B[1K", out); return *this; } 04677 console& console::fglite() { fputs("\x1B[1m", out); return *this; } 04678 console& console::fgdark() { fputs("\x1B[22m", out); return *this; } 04679 console& console::fgcol(short color) { sprintf(s, "\x1B[%dm", color + 30); fputs(s, out); return *this; } 04680 console& console::bgcol(short color) { sprintf(s, "\x1B[%dm", color + 40); fputs(s, out); return *this; } 04681 #else 04682 HANDLE console::coninfo(HANDLE* h, CONSOLE_SCREEN_BUFFER_INFO* bi) { 04683 if (h != NULL) { 04684 *h = GetStdHandle(STD_OUTPUT_HANDLE); 04685 if (bi != NULL) GetConsoleScreenBufferInfo(*h, bi); 04686 return *h; 04687 } 04688 return NULL; 04689 } 04690 console& console::bel() { MessageBeep(0xffffffff); return *this; } 04691 console& console::setxy(int x, int y) { 04692 HANDLE h; 04693 COORD c; 04694 c.X = x; 04695 c.Y = y; 04696 SetConsoleCursorPosition(coninfo(&h, 0), c); 04697 return *this; 04698 } 04699 console& console::setx(int x) { 04700 HANDLE h; 04701 CONSOLE_SCREEN_BUFFER_INFO bi; 04702 coninfo(&h, &bi); 04703 bi.dwCursorPosition.X = x; 04704 SetConsoleCursorPosition(h, bi.dwCursorPosition); 04705 return *this; 04706 } 04707 console& console::sety(int y) { 04708 HANDLE h; 04709 CONSOLE_SCREEN_BUFFER_INFO bi; 04710 coninfo(&h, &bi); 04711 bi.dwCursorPosition.Y = y; 04712 SetConsoleCursorPosition(h, bi.dwCursorPosition); 04713 return *this; 04714 } 04715 console& console::up(int n) { 04716 HANDLE h; 04717 CONSOLE_SCREEN_BUFFER_INFO bi; 04718 coninfo(&h, &bi); 04719 bi.dwCursorPosition.Y -= n; 04720 SetConsoleCursorPosition(h, bi.dwCursorPosition); 04721 return *this; 04722 } 04723 console& console::dn(int n) { 04724 HANDLE h; 04725 CONSOLE_SCREEN_BUFFER_INFO bi; 04726 coninfo(&h, &bi); 04727 bi.dwCursorPosition.Y += n; 04728 SetConsoleCursorPosition(h, bi.dwCursorPosition); 04729 return *this; 04730 } 04731 console& console::lt(int n) { 04732 HANDLE h; 04733 CONSOLE_SCREEN_BUFFER_INFO bi; 04734 coninfo(&h, &bi); 04735 bi.dwCursorPosition.X -= n; 04736 SetConsoleCursorPosition(h, bi.dwCursorPosition); 04737 return *this; 04738 } 04739 console& console::rt(int n) { 04740 HANDLE h; 04741 CONSOLE_SCREEN_BUFFER_INFO bi; 04742 coninfo(&h, &bi); 04743 bi.dwCursorPosition.X += n; 04744 SetConsoleCursorPosition(h, bi.dwCursorPosition); 04745 return *this; 04746 } 04747 console& console::rmln() { 04748 HANDLE h; 04749 CONSOLE_SCREEN_BUFFER_INFO bi; 04750 COORD c; 04751 coninfo(&h, &bi); 04752 c = bi.dwCursorPosition; 04753 c.X = 0; 04754 FillConsoleOutputCharacterA(h, ' ', bi.dwCursorPosition.X, c, 0); 04755 return *this; 04756 } 04757 console& console::fglite() { 04758 HANDLE h; 04759 CONSOLE_SCREEN_BUFFER_INFO bi; 04760 coninfo(&h, &bi); 04761 bi.wAttributes |= FOREGROUND_INTENSITY; 04762 SetConsoleTextAttribute(h, bi.wAttributes); 04763 return *this; 04764 } 04765 console& console::fgdark() { 04766 HANDLE h; 04767 04768 CONSOLE_SCREEN_BUFFER_INFO bi; 04769 coninfo(&h, &bi); 04770 bi.wAttributes &= ~FOREGROUND_INTENSITY; 04771 04772 SetConsoleTextAttribute(h, bi.wAttributes); 04773 return *this; 04774 } 04775 console& console::fgcol(short color) { 04776 HANDLE h; 04777 coninfo(&h, 0); 04778 SetConsoleTextAttribute(h, color); 04779 return *this; 04780 } 04781 console& console::bgcol(short color) { 04782 HANDLE h; 04783 CONSOLE_SCREEN_BUFFER_INFO bi; 04784 coninfo(&h, &bi); 04785 switch (color) { 04786 case color::black: 04787 bi.wAttributes &= ~(BACKGROUND_BLUE | BACKGROUND_RED | BACKGROUND_GREEN); 04788 color = bi.wAttributes; 04789 break; 04790 case color::blue: color = BACKGROUND_BLUE; break; 04791 case color::green: color = BACKGROUND_GREEN; break; 04792 case color::red: color = BACKGROUND_RED; break; 04793 case color::aqua: color = BACKGROUND_BLUE | BACKGROUND_GREEN; break; 04794 case color::purple: color = BACKGROUND_BLUE | BACKGROUND_RED; break; 04795 case color::yellow: color = BACKGROUND_GREEN | BACKGROUND_RED; break; 04796 case color::white: color = BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE; break; 04797 } 04798 SetConsoleTextAttribute(h, color); 04799 return *this; 04800 } 04801 console& console::cls() { 04802 HANDLE h; 04803 coninfo(&h, 0); 04804 COORD ab, xy; 04805 xy = GetLargestConsoleWindowSize(h); 04806 ab.X = 0; 04807 ab.Y = 0; 04808 FillConsoleOutputCharacterA(h, ' ', xy.X * xy.Y, ab, 0); 04809 SetConsoleCursorPosition(h, ab); 04810 return *this; 04811 } 04812 int console::getch() { return _getch(); } 04813 int console::getche() { return _getche(); } 04814 bool console::kbhit() { return _kbhit(); } 04815 console& console::putcr() { 04816 HANDLE h; 04817 CONSOLE_SCREEN_BUFFER_INFO bi; 04818 coninfo(&h, &bi); 04819 bi.dwCursorPosition.X = 0; 04820 SetConsoleCursorPosition(h, bi.dwCursorPosition); 04821 return *this; 04822 } 04823 console& console::putbs() { 04824 HANDLE h; 04825 CONSOLE_SCREEN_BUFFER_INFO bi; 04826 coninfo(&h, &bi); 04827 bi.dwCursorPosition.X -= 1; 04828 SetConsoleCursorPosition(h, bi.dwCursorPosition); 04829 fputc(0, out); 04830 bi.dwCursorPosition.X -= 1; 04831 SetConsoleCursorPosition(h, bi.dwCursorPosition); 04832 return *this; 04833 } 04834 #endif 04835 04836 console con; 04837 04838 void die(const char* format, ...) { 04839 va_list v; 04840 va_start(v, format); 04841 vfprintf(stderr, format, v); 04842 exit(1); 04843 } 04844 04845 unsigned short cksum(const char* buf) { 04846 size_t i; 04847 unsigned short sum = 0; 04848 for (i = 0; buf[i]; i++) { 04849 sum = (sum >> 1) + ((sum & 1) << 15); 04850 sum += buf[i]; 04851 sum &= 0xffff; 04852 } 04853 return sum; 04854 } 04855 04856 int rand(int min, int max) { 04857 srand(time(NULL)); 04858 if (min == 0 && max == 0) return ::rand(); 04859 return (::rand() % (max - min)) + min; 04860 } 04861 int rands(unsigned int seed, int min, int max) { 04862 srand(seed); 04863 if (min == 0 && max == 0) return ::rand(); 04864 return (::rand() % (max - min)) + min; 04865 } 04866 04867 char* memrev(char* s, size_t size, size_t n) { 04868 char *a = s, *b = s + size * --n, *c = (char*)malloc(size); 04869 for (; a < b; a = a + size, b = b - size) { 04870 memmove(c, a, size); 04871 memmove(a, b, size); 04872 memmove(b, c, size); 04873 } 04874 free(c); 04875 return s; 04876 } 04877 04878 char* memrol(char* s, size_t size, size_t n) { 04879 size_t i = size * --n; 04880 char* a = (char*)malloc(size); 04881 memmove(a, s + i, size); 04882 memmove(s + size, s, i); 04883 memmove(s, a, size); 04884 free(a); 04885 return s; 04886 } 04887 04888 char* memror(char* s, size_t size, size_t n) { 04889 size_t i = size * --n; 04890 char* a = (char*)malloc(size); 04891 memmove(a, s, size); 04892 memmove(s, s + size, i); 04893 memmove(s + i, a, size); 04894 free(a); 04895 return s; 04896 } 04897 char* memshr(char* s, size_t size, size_t n) { 04898 memmove(s + size, s, (n - 1) * size); 04899 return s + size; 04900 } 04901 char* memshl(char* s, size_t size, size_t n) { 04902 memmove(s, s + size, (n - 1) * size); 04903 return s; 04904 } 04905 04906 string chop(const char* str) { 04907 string s(str); 04908 s = s.chop(); 04909 return s; 04910 } 04911 string chomp(const char* str, const char* eat) { 04912 string s(str); 04913 s = s.chomp(eat); 04914 return s; 04915 } 04916 string cut(const char* str) { 04917 string s(str); 04918 s = s.cut(); 04919 return s; 04920 } 04921 string munch(const char* str, const char* eat) { 04922 string s(str); 04923 s = s.munch(eat); 04924 return s; 04925 } 04926 string ltrim(const char* str) { 04927 string s(str); 04928 s = s.ltrim(); 04929 return s; 04930 } 04931 string rtrim(const char* str) { 04932 string s(str); 04933 s = s.rtrim(); 04934 return s; 04935 } 04936 string strip(const char* str) { 04937 string s(str); 04938 s = s.strip(); 04939 return s; 04940 } 04941 string substr(const char* str, size_t offset, size_t length) { 04942 string s(str); 04943 return s.substr(offset, length); 04944 } 04945 string lc(const char* str) { 04946 string s(str); 04947 return s.lc(); 04948 } 04949 string lcfirst(const char* str) { 04950 string s(str); 04951 s[0] = tolower(s[0]); 04952 return s; 04953 } 04954 string uc(const char* str) { 04955 string s(str); 04956 return s.uc(); 04957 } 04958 string ucfirst(const char* str) { 04959 string s(str); 04960 s[0] = toupper(s[0]); 04961 return s; 04962 } 04963 long rindex(const char* str, const char* find) { 04964 const char *t, *u; 04965 for (t = strstr(str, find), u = t; t; t = strstr(u, find)) 04966 if (t) u = t; 04967 return u - str; 04968 } 04969 long rindex(const char* str, int find) { 04970 char a[2]; 04971 a[0] = find; a[1] = 0; 04972 return rindex(str, a); 04973 } 04974 string q(const char* str) { 04975 string s(str); 04976 return s.q(); 04977 } 04978 string qq(const char* str) { 04979 string s(str); 04980 return s.qq(); 04981 } 04982 string qx(const char* exec) { 04983 string s(exec); 04984 return s.qx(); 04985 } 04986 string scat(const char* s1, const char* s2) { 04987 string s(s1); 04988 s = s.cat(s2); 04989 return s; 04990 } 04991 string sdup(const char* str, int x) { 04992 string s(str); 04993 return s * x; 04994 } 04995 string tok(size_t index, const char* str, const char* delim) { 04996 string s(str); 04997 return s.tok(index, delim); 04998 } 04999 string tok(size_t index, const char* str, int delim) { 05000 char a[2]; 05001 a[0] = delim; a[1] = 0; 05002 return tok(index, str, a); 05003 } 05004 long ntok(const char* str, const char* delim) { 05005 string s(str); 05006 return s.ntok(delim); 05007 } 05008 long ntok(const char* str, int delim) { 05009 char a[2]; 05010 a[0] = delim; a[1] = 0; 05011 return ntok(str, a); 05012 } 05013 long itok(size_t index, const char* str, const char* delim) { 05014 string s(str); 05015 return s.itok(index, delim); 05016 } 05017 long itok(size_t index, const char* str, int delim) { 05018 char a[2]; 05019 a[0] = delim; a[1] = 0; 05020 return itok(index, str, a); 05021 } 05022 std::deque<axcel::string> split(const char* str, const char* delim) { 05023 axcel::string s(str); 05024 return s.split(delim); 05025 } 05026 std::deque<axcel::string> split(const char* str, int delim) { 05027 char a[2]; 05028 a[0] = delim; a[1] = 0; 05029 return split(str, a); 05030 } 05031 string join(std::deque<axcel::string> v, const char* delim) { 05032 axcel::string s; 05033 while (!v.empty()) { 05034 s += v.front(); 05035 s += delim; 05036 v.pop_front(); 05037 } 05038 s = s.chomp(delim); 05039 return s; 05040 } 05041 string join(std::deque<axcel::string> v, int delim) { 05042 axcel::string s; 05043 while (!v.empty()) { 05044 s += v.front(); 05045 s += delim; 05046 v.pop_front(); 05047 } 05048 char a[2]; 05049 a[0] = delim; a[1] = 0; 05050 s = s.chomp(a); 05051 return s; 05052 } 05053 05059 string string::rep(const char* oldstr, const char* newstr) { 05060 string s(buf); 05061 if (s.str(oldstr) == -1) return s; 05062 long i = 0, k = -1, p; 05063 size_t j = strlen(oldstr), o = strlen(newstr); 05064 for (;;) { 05065 if (i > s.len()) break; 05066 p = s.shl(i).str(oldstr); 05067 if (p == -1) break; 05068 i = p + i; 05069 s = s.rm(i, j); 05070 s = s.ins(i, newstr); 05071 i += o; 05072 } 05073 return s; 05074 } 05075 05081 string string::rep(int oldc, int newc) { 05082 char a[2], b[2]; 05083 a[0] = oldc; a[1] = 0; 05084 b[0] = newc; b[1] = 0; 05085 return rep(a, b); 05086 } 05087 05092 string string::prefix(const char* str) { 05093 string s(buf); 05094 unless (s.starts(str)) s -= str; 05095 return s; 05096 } 05097 05102 string string::suffix(const char* str) { 05103 string s(buf); 05104 unless (s.ends(str)) s += str; 05105 return s; 05106 } 05107 05113 string string::untag(int opentag, int closetag) { 05114 string s; 05115 if (empty()) return s; 05116 size_t p = tell(); 05117 rewind(); 05118 int c; 05119 bool b = false; 05120 for (;;) { 05121 c = getc(); 05122 if (c == EOF) break; 05123 if (c == opentag) { b = true; continue; } 05124 else if (c == closetag) { b = false; continue; } 05125 else if (!b) s.putc(c); 05126 } 05127 seek(p, SEEK_SET); 05128 return s; 05129 } 05130 05131 05132 05133 05134 #ifdef _WIN32 05135 struct tm * localtime_r (const time_t *timer, struct tm *result) 05136 05137 05138 { 05139 struct tm *local_result; 05140 local_result = localtime (timer); 05141 05142 if (local_result == NULL || result == NULL) 05143 return NULL; 05144 05145 memmove (result, local_result, sizeof (struct tm)); 05146 return result; 05147 } 05148 05149 struct tm * gmtime_r (const time_t *timer, struct tm *result) 05150 { 05151 struct tm *local_result; 05152 local_result = gmtime (timer); 05153 05154 if (local_result == NULL || result == NULL) 05155 return NULL; 05156 05157 memmove (result, local_result, sizeof (struct tm)); 05158 return result; 05159 } 05160 #endif 05161 05162 time_t axcel_timegm(struct tm* tm) { 05163 time_t ret; 05164 string tz; 05165 tz = proc::envget("TZ"); 05166 proc::envset("TZ", ""); 05167 tzset(); 05168 ret = mktime(tm); 05169 unless (tz.empty()) 05170 proc::envset("TZ", tz); 05171 tzset(); 05172 return ret; 05173 } 05174 05175 timer::timer() { memset(&t, 0, sizeof(struct tm)); UTC = false; } 05176 timer::timer(const char* s) { UTC = false; this->operator=((const char*)s); } 05180 int timer::sec() { return t.tm_sec; } 05181 05185 int timer::min() { return t.tm_min; } 05186 05190 int timer::hour() { return t.tm_hour; } 05191 05195 int timer::mday() { return t.tm_mday; } 05196 05200 int timer::mon() { return t.tm_mon; } 05201 05205 int timer::year() { return t.tm_year; } 05206 05210 int timer::wday() { return t.tm_wday; } 05211 05215 string timer::str() { 05216 string s; 05217 s.realloc(32); 05218 string fmt; 05219 if (t.tm_wday != -1) fmt += "%a "; 05220 if (t.tm_mon != -1) fmt += "%b "; 05221 #ifndef _WIN32 05222 if (t.tm_mday != -1) fmt += "%e "; 05223 #else 05224 if (t.tm_mday != -1) fmt += "%d "; 05225 #endif 05226 if (t.tm_hour != -1) { 05227 fmt += "%H:"; 05228 if (t.tm_min != -1) fmt += "%M"; 05229 else fmt += "00"; 05230 if (t.tm_sec != -1) fmt += ":%S "; 05231 } 05232 if (t.tm_year != -1) fmt += "%Y"; 05233 strftime(s.buf, 32, fmt, &t); 05234 return s; 05235 } 05236 05267 timer& timer::operator= (const char* s) { 05268 int i; 05269 const char* c; 05270 t.tm_sec = 0; 05271 t.tm_min = 0; 05272 t.tm_hour = 0; 05273 t.tm_mday = 1; 05274 t.tm_mon = 0; 05275 t.tm_year = 0; 05276 t.tm_wday = 0; 05277 t.tm_isdst = 0; 05278 if (strstr(s, "Sun")) t.tm_wday = 0; 05279 else if (strstr(s, "Mon")) t.tm_wday = 1; 05280 else if (strstr(s, "Tue")) t.tm_wday = 2; 05281 else if (strstr(s, "Wed")) t.tm_wday = 3; 05282 else if (strstr(s, "Thu")) t.tm_wday = 4; 05283 else if (strstr(s, "Fri")) t.tm_wday = 5; 05284 else if (strstr(s, "Sat")) t.tm_wday = 6; 05285 if (strstr(s, "Jan")) t.tm_mon = 0; 05286 else if (strstr(s, "Feb")) t.tm_mon = 1; 05287 else if (strstr(s, "Mar")) t.tm_mon = 2; 05288 else if (strstr(s, "Apr")) t.tm_mon = 3; 05289 else if (strstr(s, "May")) t.tm_mon = 4; 05290 else if (strstr(s, "Jun")) t.tm_mon = 5; 05291 else if (strstr(s, "Jul")) t.tm_mon = 6; 05292 else if (strstr(s, "Aug")) t.tm_mon = 7; 05293 else if (strstr(s, "Sep")) t.tm_mon = 8; 05294 else if (strstr(s, "Oct")) t.tm_mon = 9; 05295 else if (strstr(s, "Nov")) t.tm_mon = 10; 05296 else if (strstr(s, "Dec")) t.tm_mon = 11; 05297 for (c = strpbrk(s, "0123456789"); c != NULL; c = strpbrk(c, "0123456789")) { 05298 i = atoi(c); 05299 while (isdigit(*c)) c++; 05300 if (*c == ':') { 05301 t.tm_hour = i; 05302 c++; 05303 t.tm_min = atoi(c); 05304 while (isdigit(*c)) c++; 05305 if (*c == ':') t.tm_sec = atoi(++c); 05306 while (isdigit(*c)) c++; 05307 if (*c == ' ') c++; 05308 if ( 05309 !strncmp(c, "PM", 2) || 05310 !strncmp(c, "pm", 2) || 05311 !strncmp(c, "p.m.", 4) 05312 ) { if (t.tm_hour != 12) t.tm_hour += 12; 05313 } else if ( 05314 !strncmp(c, "AM", 2) || 05315 !strncmp(c, "am", 2) || 05316 !strncmp(c, "a.m.", 4) 05317 ) { if (t.tm_hour == 12) t.tm_hour = 0; } 05318 } else { 05319 if (i > 0 && i < 32) t.tm_mday = i; 05320 else t.tm_year = i - 1900; 05321 } 05322 } 05323 return *this; 05324 } 05325 05326 05337 bool timer::operator== (const char* s) { return op<int>(::eq, s); } 05338 05339 const char* strstrs(const char* src, ...) { 05340 va_list v; 05341 va_start(v, src); 05342 const char *a, *b; 05343 for (a = va_arg(v, const char*); a != NULL; a = va_arg(v, const char*)) 05344 if ((b = strstr(src, a))) break; 05345 va_end(v); 05346 return b; 05347 } 05348 05349 int strstrc(const char* src, ...) { 05350 va_list v; 05351 va_start(v, src); 05352 int i = 0; 05353 const char* a; 05354 for (a = va_arg(v, const char*); a != NULL; a = va_arg(v, const char*), i++) 05355 if (strstr(src, a)) break; 05356 va_end(v); 05357 if (a == NULL) return -1; else return i; 05358 } 05359 05360 bool timer::operator> (const char* s) { return op<int>(::gt, s); } 05361 bool timer::operator< (const char* s) { return op<int>(::lt, s); } 05362 bool timer::operator<= (const char* s) { return op<int>(::lte, s); } 05363 bool timer::operator>= (const char* s) { return op<int>(::gte, s); } 05364 bool timer::operator!= (const char* s) { return op<int>(::neq, s); } 05365 05375 timer timer::operator+ (const char* s) { 05376 time_t tm; 05377 timer c; 05378 string p = s; 05379 char u[12]; 05380 if (UTC) tm = axcel_timegm(&t); 05381 else tm = mktime(&t); 05382 while (p.pbrk("0123456789") > -1) { 05383 p = p.shl(p.pbrk("0123456789")); 05384 strcpy(u, p.tok(1, ' ')); 05385 if (sfront(u, "second")) tm += atoi(p.tok(0, ' ')); 05386 else if (sfront(u, "minute"))tm += atoi(p.tok(0, ' ')) * 60; 05387 else if (sfront(u, "hour")) tm += atoi(p.tok(0, ' ')) * 60 * 60; 05388 else if (sfront(u, "day")) tm += atoi(p.tok(0, ' ')) * 60 * 60 * 24; 05389 else if (sfront(u, "week")) tm += atoi(p.tok(0, ' ')) * 60 * 60 * 24 * 7; 05390 else if (sfront(u, "month")) tm += atoi(p.tok(0, ' ')) * 60 * 60 * 24 * 30; 05391 else if (sfront(u, "year")) tm += atoi(p.tok(0, ' ')) * 60 * 60 * 24 * 365; 05392 p = p.slurp(' '); 05393 } 05394 if (UTC) gmtime_r(&tm, &(c.t)); 05395 else localtime_r(&tm, &(c.t)); 05396 return c; 05397 } 05398 05405 timer timer::operator- (const char* s) { 05406 time_t tm; 05407 timer c; 05408 string p = s; 05409 char u[12]; 05410 if (UTC) tm = axcel_timegm(&t); 05411 else tm = mktime(&t); 05412 while (p.pbrk("0123456789") > -1) { 05413 p = p.shl(p.pbrk("0123456789")); 05414 strcpy(u, p.tok(1, ' ')); 05415 if (sfront(u, "second")) tm -= atoi(p.tok(0, ' ')); 05416 else if (sfront(u, "minute")) tm -= atoi(p.tok(0, ' ')) * 60; 05417 else if (sfront(u, "hour")) tm -= atoi(p.tok(0, ' ')) * 60 * 60; 05418 else if (sfront(u, "day")) tm -= atoi(p.tok(0, ' ')) * 60 * 60 * 24; 05419 else if (sfront(u, "week")) tm -= atoi(p.tok(0, ' ')) * 60 * 60 * 24 * 7; 05420 else if (sfront(u, "month")) tm -= atoi(p.tok(0, ' ')) * 60 * 60 * 24 * 30; 05421 else if (sfront(u, "year")) tm -= atoi(p.tok(0, ' ')) * 60 * 60 * 24 * 365; 05422 p = p.slurp(' '); 05423 } 05424 if (UTC) gmtime_r(&tm, &(c.t)); 05425 else localtime_r(&tm, &(c.t)); 05426 return c; 05427 } 05428 05429 timer& timer::operator+= (const char* s) { *this = this->operator+(s); return *this; } 05430 timer& timer::operator-= (const char* s) { *this = this->operator-(s); return *this; } 05431 timer& timer::operator= (time_t raw) { 05432 if (UTC) gmtime_r(&raw, &t); 05433 else localtime_r(&raw, &t); 05434 return *this; 05435 } 05436 string timer::ltime() { 05437 string s; 05438 time_t foo; 05439 struct tm bar; 05440 foo = time(NULL); 05441 localtime_r(&foo, &bar); 05442 s.realloc(32); 05443 #ifndef _WIN32 05444 strftime(s.buf, 32, "%a %b %e %H:%M:%S %Y", &bar); 05445 #else 05446 strftime(s.buf, 32, "%a %b %d %H:%M:%S %Y", &bar); 05447 #endif 05448 return s; 05449 } 05450 05451 string timer::utime() { 05452 string s; 05453 time_t foo; 05454 struct tm bar; 05455 foo = time(NULL); 05456 gmtime_r(&foo, &bar); 05457 s.realloc(32); 05458 #ifndef _WIN32 05459 strftime(s.buf, 32, "%a %b %e %H:%M:%S %Y", &bar); 05460 #else 05461 strftime(s.buf, 32, "%a %b %d %H:%M:%S %Y", &bar); 05462 #endif 05463 return s; 05464 } 05465 05466 05467 timer& timer::operator= (struct tm* tm) { 05468 memmove(&t, tm, sizeof(struct tm)); 05469 return *this; 05470 } 05471 05472 namespace fs { 05473 05474 #ifndef _WIN32 05475 timer fatime(const char* fname) { 05476 timer c; 05477 struct stat buf; 05478 if (stat(fname, &buf) == -1) return c; 05479 c = buf.st_atime; 05480 return c; 05481 } 05482 timer fmtime(const char* fname) { 05483 timer c; 05484 struct stat buf; 05485 if (stat(fname, &buf) == -1) return c; 05486 c = buf.st_mtime; 05487 return c; 05488 } 05489 #else 05490 timer fatime(const char* fname) { 05491 HANDLE h; 05492 FILETIME ft; SYSTEMTIME z; SYSTEMTIME r; 05493 timer c; 05494 h = CreateFile(fname, GENERIC_READ, 0, NULL, OPEN_EXISTING, NULL, NULL); 05495 if (h == INVALID_HANDLE_VALUE) return c; 05496 if (!GetFileTime(h, NULL, &ft, NULL)) return c; 05497 FileTimeToSystemTime(&ft, &z); 05498 SystemTimeToTzSpecificLocalTime(NULL, &z, &r); 05499 struct tm t; 05500 t.tm_year = r.wYear - 1900; 05501 t.tm_mon = r.wMonth - 1; 05502 t.tm_wday = r.wDayOfWeek; 05503 t.tm_mday = r.wDay; 05504 t.tm_hour = r.wHour; 05505 t.tm_min = r.wMinute; 05506 t.tm_sec = r.wSecond; 05507 memmove(&c.t, &t, sizeof(struct tm)); 05508 return c; 05509 } 05510 05511 timer fmtime(const char* fname) { 05512 HANDLE h; 05513 FILETIME ft; SYSTEMTIME z; SYSTEMTIME r; 05514 timer c; 05515 h = CreateFile(fname, GENERIC_READ, 0, NULL, OPEN_EXISTING, NULL, NULL); 05516 if (h == INVALID_HANDLE_VALUE) return c; 05517 if (!GetFileTime(h, NULL, NULL, &ft)) return c; 05518 FileTimeToSystemTime(&ft, &z); 05519 SystemTimeToTzSpecificLocalTime(NULL, &z, &r); 05520 struct tm t; 05521 t.tm_year = r.wYear - 1900; 05522 t.tm_mon = r.wMonth - 1; 05523 t.tm_wday = r.wDayOfWeek; 05524 t.tm_mday = r.wDay; 05525 t.tm_hour = r.wHour; 05526 t.tm_min = r.wMinute; 05527 t.tm_sec = r.wSecond; 05528 memmove(&c.t, &t, sizeof(struct tm)); 05529 return c; 05530 } 05531 #endif 05532 05533 /* 05534 #ifndef _WIN32 05535 bool mkfifo(const char* fname) { return !mknod(fname, S_IFIFO | 0666, 0); } 05536 bool mkhlnk(const char* ofname, const char* lfname) { return !link(ofname, lfname); } 05537 bool mkslnk(const char* ofname, const char* lfname) { return !symlink(ofname, lfname); } 05538 string rdlnk(const char* lfname) { 05539 string s(256); 05540 ssize_t t = readlink(lfname, s, 256); 05541 if (t == -1) { s[0] = 0; return s; } 05542 else { s[t] = 0; return s; } 05543 } 05544 #endif 05545 */ 05546 05547 bool mv(const char* src, const char* dst) { return (cp(src, dst) && rm(src)); } 05548 05549 bool cp(const char* src, const char* dst) { 05550 FILE *f, *g; 05551 if (!(f = fopen(src, "rb"))) return 0; 05552 if (fisdir(dst)) { 05553 char* p = (char*)malloc(4); 05554 if (strchr(src, '/')) { 05555 p = (char*)realloc(p, strlen(dst) + strlen(strrchr(src, '/') + 1)); 05556 strcpy(p, dst); 05557 if (p[strlen(p) - 1] == '/') p[strlen(p) -1] = 0; 05558 strcat(p, strrchr(src, '/')); 05559 if (!(g = fopen(strrchr(p, '/') + 1, "wb"))){ 05560 free(p); fclose(f); return 0; 05561 } 05562 } else { 05563 p = (char*)realloc(p, strlen(dst) + strlen(src) + 2); 05564 strcpy(p, dst); 05565 if (p[strlen(p) - 1] == '/') p[strlen(p) - 1] = 0; 05566 strcat(p, "/"); 05567 strcat(p, src); 05568 if (!(g = fopen(p, "wb"))) { 05569 free(p); 05570 fclose(f); 05571 return 0; 05572 } 05573 } 05574 free(p); 05575 } else { 05576 if (!(g = fopen(dst, "wb"))) { 05577 fclose(f); 05578 return 0; 05579 } 05580 } 05581 int c; 05582 while (!feof(f)) { 05583 c = fgetc(f); 05584 if (c == EOF) break; 05585 fputc(c, g); 05586 } 05587 fclose(f); 05588 fclose(g); 05589 return 1; 05590 } 05591 05592 string gcd() { 05593 string s; 05594 size_t i; 05595 s.realloc(32); 05596 #ifndef _WIN32 05597 while (getcwd(s, s.msize()) == NULL) 05598 s.realloc(s.msize() * 2); 05599 #else 05600 i = GetCurrentDirectoryA(0, NULL); 05601 s.realloc(i); 05602 GetCurrentDirectoryA(i, s); 05603 #endif 05604 return s; 05605 } 05606 05607 string ls(const char* dir) { 05608 string s, t; 05609 s.clear(); 05610 #ifndef _WIN32 05611 DIR* d; 05612 struct dirent* f; 05613 if (!dir) d = opendir(gcd()); 05614 else d = opendir(dir); 05615 if (d == NULL) return s; 05616 while ((f = readdir(d))) { s.realloc(s.len() + strlen(f->d_name) + 2); strcat(s.buf, f->d_name); strcat(s.buf, "\n"); } 05617 closedir(d); 05618 #else 05619 WIN32_FIND_DATA f; 05620 if (!dir) t = t.cat(gcd()).cat("\\*"); 05621 HANDLE d = FindFirstFileA(t, &f); 05622 if (d == INVALID_HANDLE_VALUE) return s; 05623 do { 05624 s.realloc(s.len() + strlen(f.cFileName) + 2); 05625 strcat(s.buf, f.cFileName); 05626 strcat(s.buf, "\n"); 05627 } while (FindNextFileA(d, &f)); 05628 FindClose(d); 05629 #endif 05630 return s; 05631 } 05632 05633 size_t fread(const char* fname, char* buf, size_t size) { 05634 size_t i; 05635 FILE* f; 05636 if (!(f = fopen(fname, "rb"))) return 0; 05637 for (i = 0; !feof(f) && (i < size || !size); i++) { 05638 buf[i] = fgetc(f); 05639 if (buf[i] == -1) { buf[i] = 0; break; } 05640 } 05641 fclose(f); 05642 return i; 05643 } 05644 05645 string fread(const char* fname, size_t size) { 05646 size_t i; 05647 int j; 05648 FILE* f; 05649 string s; 05650 if (!(f = fopen(fname, "rb"))) return s; 05651 for (i = 0; !feof(f) && (i < size || !size); i++) { 05652 j = fgetc(f); 05653 if (j == EOF) break; 05654 s += (char)j; 05655 } 05656 fclose(f); 05657 return s; 05658 } 05659 05660 size_t fwrite(const char* fname, const char* buf, size_t size) { 05661 FILE* f; 05662 if (!(f = fopen(fname, "wb"))) return 0; 05663 if (!size) size = strlen(buf); 05664 size_t i = fwrite(buf, 1, size, f); 05665 fclose(f); 05666 return i; 05667 } 05668 05669 size_t fcat(const char* fname, const char* buf, size_t len) { 05670 FILE* f; 05671 if (!(f = fopen(fname, "ab"))) return 0; 05672 if (!len) len = strlen(buf); 05673 size_t i = fwrite(buf, 1, len, f); 05674 fclose(f); 05675 return i; 05676 } 05677 05678 bool fcmp(const char* src, const char* dst) { 05679 FILE *f, *g; 05680 register char a, b; 05681 if (!(f = fopen(src, "rb"))) return 0; 05682 if (!(g = fopen(dst, "rb"))) return 0; 05683 while (!feof(f) && !feof(g)) { 05684 a = fgetc(f); 05685 b = fgetc(g); 05686 if (a != b) { 05687 fclose(f); 05688 fclose(g); 05689 return 0; 05690 } 05691 } 05692 if (feof(f) && feof(g)) { 05693 fclose(f); 05694 fclose(g); 05695 return 1; 05696 } 05697 fclose(f); 05698 fclose(g); 05699 return 0; 05700 } 05701 05702 #ifndef _WIN32 05703 bool md(const char* path) { if (::mkdir(path, 00744) == -1) return 0; else return 1; } 05704 bool cd(const char* path) { if (::chdir(path) == -1) return 0; else return 1; } 05705 bool creat(const char* fname) { 05706 int f = ::open(fname, O_CREAT | O_TRUNC | O_RDWR, 00644); 05707 if (f == -1) return 0; 05708 ::close(f); 05709 return 1; 05710 } 05711 bool trunc(const char* fname, unsigned long len) { 05712 if (truncate(fname, len) == -1) return 0; 05713 else return 1; 05714 } 05715 bool rm(const char* fname) { if (remove(fname) == -1) return 0; else return 1; } 05716 05717 bool rd(const char* dir, bool rmsub) { 05718 if (!rmsub) 05719 return !rmdir(dir); 05720 bool ret = true; 05721 unsigned long i = 0; 05722 string s = ls(dir), t; 05723 for (;;) { 05724 t = s.tok(i++, "\n"); 05725 if (t.empty()) break; 05726 if (t == ".." || t == ".") continue; 05727 if (!sback(dir, "/")) t = t.prep('/'); 05728 t = t.prep(dir); 05729 if (fisdir(t)) rd(t); 05730 rm(t); 05731 } 05732 if (rmdir(dir)) ret = false; 05733 return ret; 05734 } 05735 05736 size_t fsize(const char* fname) { 05737 struct stat buf; 05738 if (stat(fname, &buf) == -1) return 0; 05739 return buf.st_size; 05740 } 05741 bool fexist(const char* fname) { 05742 int i; 05743 struct stat buf; 05744 i = stat(fname, &buf); 05745 if (i == -1) return 0; 05746 return 1; 05747 } 05748 bool fisdir(const char* fname) { 05749 struct stat buf; 05750 if (stat(fname, &buf) == -1) return 0; 05751 return S_ISDIR(buf.st_mode); 05752 } 05753 bool fisreg(const char* fname) { 05754 struct stat buf; 05755 if (stat(fname, &buf) == -1) return 0; 05756 return S_ISREG(buf.st_mode); 05757 } 05758 #else 05759 bool rd(const char* dir, bool rmsub) { 05760 if (!rmsub) 05761 return (bool)RemoveDirectory(dir); 05762 bool ret = true; 05763 unsigned long i = 0; 05764 string s = ls(dir), t; 05765 for (;;) { 05766 t = s.tok(i++, "\n"); 05767 if (t.empty()) break; 05768 if (t == ".." || t == ".") continue; 05769 if (!sback(dir, "/")) t = t.prep('/'); 05770 t = t.prep(dir); 05771 if (fisdir(t)) rd(t); 05772 rm(t); 05773 } 05774 if (!RemoveDirectory(dir)) ret = false; 05775 return ret; 05776 } 05777 05778 bool fisdir(const char* fname) { 05779 DWORD i = GetFileAttributesA(fname); 05780 if (i == INVALID_FILE_ATTRIBUTES) return 0; 05781 else if (i & FILE_ATTRIBUTE_DIRECTORY) return 1; 05782 else return 0; 05783 } 05784 bool fisreg(const char* fname) { 05785 DWORD i = GetFileAttributesA(fname); 05786 if (i == INVALID_FILE_ATTRIBUTES) return 0; 05787 else if (!(i & FILE_ATTRIBUTE_DIRECTORY)) return 1; 05788 else return 0; 05789 } 05790 bool fexist(const char* fname) { 05791 if (GetFileAttributesA(fname) == INVALID_FILE_ATTRIBUTES) return 0; 05792 return 1; 05793 } 05794 bool creat(const char* fname) { 05795 HANDLE f = CreateFileA(fname, 0, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); 05796 if (f == INVALID_HANDLE_VALUE) return 0; 05797 CloseHandle(f); 05798 return 1; 05799 } 05800 bool trunc(const char* fname, unsigned long len) { 05801 HANDLE f = CreateFileA(fname, 0, 0, 0, OPEN_EXISTING, 0, 0); 05802 if (f == INVALID_HANDLE_VALUE) return 0; 05803 if (SetFilePointer(f, len, 0, FILE_BEGIN) == INVALID_SET_FILE_POINTER) return 0; 05804 if (!SetEndOfFile(f)) return 0; 05805 CloseHandle(f); 05806 return 1; 05807 } 05808 size_t fsize(const char* fname) { 05809 HANDLE f = CreateFileA(fname, 0, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); 05810 if (f == INVALID_HANDLE_VALUE) return -1; 05811 long int i = GetFileSize(f, 0); 05812 CloseHandle(f); 05813 return i; 05814 } 05815 #endif 05816 05817 }; 05818 05819 proc::thread::thread() { tid = 0; sub = 0; stack = 0; } 05820 proc::thread::thread(void* (*tfunc)(void*)) { tid = 0; sub = tfunc; stack = 0; } 05821 proc::thread& proc::thread::operator= (void* (*tfunc)(void*)) { sub = tfunc; return *this; } 05822 proc::thread& proc::thread::operator= (proc::thread t) { sub = t.sub; tid = t.tid; return *this; } 05823 bool proc::thread::operator== (proc::thread t) { return (sub == t.sub && tid == t.tid); } 05824 bool proc::thread::operator== (void* (*tfunc)(void*)) { return sub == tfunc; } 05825 bool proc::thread::operator!= (proc::thread t) { return !(sub == t.sub && tid == t.tid); } 05826 bool proc::thread::operator!= (void* (*tfunc)(void*)) { return sub != tfunc; } 05827 05828 #ifdef _WIN32 05829 proc::thread::~thread() { CloseHandle(fd); } 05830 bool proc::thread::start(void* param) { 05831 if (!sub) return false; 05832 DWORD t; 05833 HANDLE tmp = CreateThread(0, stack, (LPTHREAD_START_ROUTINE)sub, param, 0, &t); 05834 if (!tmp) return false; 05835 else { fd = tmp; tid = t; return true; } 05836 } 05837 bool proc::thread::stop() { return TerminateThread(fd, 0); } 05838 bool proc::thread::join(void ** ret) { 05839 WaitForSingleObject(fd, INFINITE); 05840 return getret(ret); 05841 } 05842 bool proc::thread::tjoin(size_t ms, void ** ret) { 05843 WaitForSingleObject(fd, ms); 05844 return getret(ret); 05845 } 05846 bool proc::thread::getret(void ** retval) { 05847 void* r; 05848 if (GetExitCodeThread(fd, (LPDWORD)&r)) { 05849 memmove(*retval, r, sizeof(void*)); 05850 return true; 05851 } else return false; 05852 } 05853 05854 void proc::thread::exit(void* retval) { ExitThread((DWORD)retval); } 05855 proc::thread proc::thread::self() { proc::thread t; t.tid = GetCurrentThreadId(); return t; } 05856 #else 05857 proc::thread::~thread() { pthread_attr_destroy(&attr); } 05858 bool proc::thread::start(void* param) { 05859 register int err; 05860 if (err = pthread_attr_init(&attr)) { errnum = err; return false; } 05861 if (stack) 05862 if (err = pthread_attr_setstacksize(&attr, stack)) { 05863 errnum = err; return false; 05864 } 05865 if (err = pthread_create(&tid, &attr, sub, param)) { 05866 errnum = err; return false; 05867 } 05868 05869 return true; 05870 } 05871 bool proc::thread::stop() { 05872 register int err; 05873 if (err = pthread_cancel(tid)) { 05874 errnum = err; return false; 05875 } 05876 05877 return true; 05878 } 05879 bool proc::thread::join(void ** ret) { 05880 void* r; 05881 register int err; 05882 if (ret) { 05883 if (err = pthread_join(tid, ret)) { 05884 errnum = err; 05885 return false; 05886 } 05887 } else { 05888 if (err = pthread_join(tid, &r)) { 05889 errnum = err; 05890 return false; 05891 } 05892 } 05893 05894 return true; 05895 } 05896 bool proc::thread::tjoin(size_t ms, void ** ret) { 05897 void* r; 05898 struct timespec t; 05899 register int err; 05900 t.tv_sec = ms / 1000; 05901 t.tv_nsec = (ms % 1000) * (1000 * 1000); 05902 if (ret) { 05903 if (err = pthread_timedjoin_np(tid, ret, &t)) { errnum = err; return false; } 05904 } else { 05905 if (err = pthread_timedjoin_np(tid, &r, &t)) { 05906 errnum = err; return false; 05907 } 05908 } 05909 05910 return true; 05911 } 05912 bool proc::thread::getret(void ** retval) { 05913 void* r; 05914 register int err; 05915 if (retval == 0) err = pthread_tryjoin_np(tid, &r); 05916 else err = pthread_tryjoin_np(tid, retval); 05917 if (!err) { return true; } 05918 errnum = err; 05919 return false; 05920 } 05921 void proc::thread::exit(void* retval) { pthread_exit(retval); } 05922 proc::thread proc::thread::self() { proc::thread t; t.tid = pthread_self(); return t; } 05923 #endif 05924 05925 string proc::environment::type() { return string("proc::environ"); } 05926 proc::environment::operator string () { 05927 string s; 05928 std::deque<p>::iterator it; 05929 for (it = e.begin(); it != e.end(); it++) 05930 if (it->v.empty()) { 05931 e.erase(it--); 05932 continue; 05933 } else 05934 s << it->k << '=' << it->v << '\n'; 05935 return s; 05936 } 05937 string proc::environment::vars() { 05938 string v; 05939 std::deque<p>::iterator it; 05940 for (it = e.begin(); it != e.end(); it++) 05941 if (it->v.empty()) { 05942 e.erase(it--); 05943 continue; 05944 } else 05945 v << it->k << '\n'; 05946 return v; 05947 } 05948 string& proc::environment::operator[] (const char* s) { 05949 std::deque<p>::iterator it; 05950 struct p pair; 05951 for (it = e.begin(); it != e.end(); it++) 05952 if (it->k == s) break; 05953 if (it == e.end()) { pair.k = s; e.push_back(pair); } 05954 return it->v; 05955 } 05956 string& proc::environment::at(size_t i) { 05957 return e[i].v; 05958 } 05959 size_t proc::environment::len() { 05960 std::deque<p>::iterator it; 05961 for (it = e.begin(); it != e.end(); it++) 05962 if (it->v.empty()) { 05963 e.erase(it--); 05964 continue; 05965 } 05966 return e.size(); 05967 } 05968 proc::environment& proc::environment::clear() { 05969 e.clear(); 05970 return *this; 05971 } 05972 bool proc::environment::empty() { 05973 return e.empty(); 05974 } 05975 05976 data proc::environment::bake() { 05977 data d; 05978 size_t i = 0, j = 0, k = 0; 05979 char *c, **b; 05980 std::deque<p>::iterator it; 05981 for (it = e.begin(); it != e.end(); it++) { 05982 if (it->v.empty()) { 05983 e.erase(it--); 05984 continue; 05985 } 05986 i++; 05987 j += it->k.len() + it->v.len() + 2; 05988 } 05989 i++; 05990 d.realloc(sizeof(char*) * i + j); 05991 c = d.buf + sizeof(char*) * i; 05992 b = (char**)d.buf; 05993 for (it = e.begin(); it != e.end(); it++, k++) { 05994 strcpy(c, it->k); 05995 strcat(c, "="); 05996 strcat(c, it->v); 05997 b[k] = c; 05998 c += strlen(c) + 1; 05999 } 06000 b[k] = (char*)0; 06001 return d; 06002 } 06003 06004 namespace proc { 06005 06006 #ifndef _WIN32 06007 06008 string lsproc() { 06009 string s, t, u; 06010 fs::file f; 06011 size_t pid; 06012 std::deque<string> d = fs::ls("/proc").split('\n'); 06013 std::deque<string>::iterator it; 06014 for (it = d.begin(); it < d.end(); it++) { 06015 if ((*it)[0] == '.') continue; 06016 if (!it->isdigit()) continue; 06017 f.open(it->prep("/proc/").cat("/status"), "rb"); 06018 if (f.dead()) continue; 06019 until (f.eof()) { 06020 t = f.gets(); 06021 if (t.starts("Name:")) u = t.slurp(':').ltrim(); 06022 else if (t.starts("Pid:")) 06023 pid = stoi<size_t>(t.slurp(':').ltrim()); 06024 } 06025 f.close(); 06026 s << pid << ':' << u; 06027 } 06028 return s; 06029 } 06030 06031 pid_t run(const char* program, const char* argv, void* envp) { 06032 if (!fs::fexist(program)) return false; 06033 pid_t p; 06034 string gay = program; 06035 if (argv) gay = gay.cat(' ').cat(argv); 06036 wordexp_t we; 06037 char** w; 06038 wordexp(gay, &we, WRDE_NOCMD); 06039 w = we.we_wordv; 06040 char *const e[] = {NULL,NULL}; 06041 p = fork(); 06042 if (!p) { 06043 setsid(); 06044 if (!envp) execve(program, w, e); 06045 else execve(program, w, (char* *const)envp); 06046 wordfree(&we); 06047 } else { 06048 wordfree(&we); 06049 } 06050 return p; 06051 } 06052 06053 bool killp(size_t pid) { 06054 if (kill(pid, SIGKILL) == -1) return false; 06055 else return true; 06056 } 06057 bool killp(const char* name) { 06058 pid_t p; 06059 size_t i; 06060 char* s = (char*)malloc(264); 06061 char buf[128]; 06062 FILE* st; 06063 DIR* d = opendir("/proc"); 06064 if (d == NULL) { free(s); return false; } 06065 struct dirent* f; 06066 while ((f = readdir(d)) != NULL) { 06067 if (f->d_name[0] == '.') continue; 06068 for (i = 0; isdigit(f->d_name[i]); i++); 06069 if (i < strlen(f->d_name)) continue; 06070 strcpy(s, "/proc/"); 06071 strcat(s, f->d_name); 06072 strcat(s, "/status"); 06073 st = fopen(s, "r"); 06074 if (st == NULL) { closedir(d); free(s); return false; } 06075 do { 06076 if (fgets(buf, 128, st) == NULL) { fclose(st); closedir(d); free(s); return false; } 06077 } while (strncmp(buf, "Name:", 5)); 06078 fclose(st); 06079 for (i = 5; isspace(buf[i]); i++); 06080 *strchr(buf, '\n') = 0; 06081 if (!strcmp(&(buf[i]), name)) { 06082 sscanf(&(s[6]), "%d", &p); 06083 kill(p, SIGKILL); 06084 } 06085 } 06086 closedir(d); 06087 free(s); 06088 return true; 06089 } 06090 bool freeze(size_t pid) { if (kill(pid, SIGSTOP) == -1) return false; else return true; } 06091 bool freeze(const char* name) { 06092 pid_t p; 06093 size_t i; 06094 char* s = (char*)malloc(264); 06095 char buf[128]; 06096 FILE* st; 06097 DIR* d = opendir("/proc"); 06098 if (d == NULL) { free(s); return false; } 06099 struct dirent* f; 06100 while ((f = readdir(d)) != NULL) { 06101 if (f->d_name[0] == '.') continue; 06102 for (i = 0; isdigit(f->d_name[i]); i++); 06103 if (i < strlen(f->d_name)) continue; 06104 strcpy(s, "/proc/"); 06105 strcat(s, f->d_name); 06106 strcat(s, "/status"); 06107 st = fopen(s, "r"); 06108 if (st == NULL) { closedir(d); free(s); return false; } 06109 do { 06110 if (fgets(buf, 128, st) == NULL) { fclose(st); closedir(d); free(s); return false; } 06111 } while (strncmp(buf, "Name:", 5)); 06112 fclose(st); 06113 for (i = 5; isspace(buf[i]); i++); 06114 *strchr(buf, '\n') = 0; 06115 if (!strcmp(&(buf[i]), name)) { 06116 sscanf(&(s[6]), "%d", &p); 06117 kill(p, SIGSTOP); 06118 } 06119 } 06120 closedir(d); 06121 free(s); 06122 return true; 06123 } 06124 bool cont(size_t pid) { if (kill(pid, SIGCONT) == -1) return false; else return true; } 06125 bool cont(const char* name) { 06126 pid_t p; 06127 size_t i; 06128 char* s = (char*)malloc(264); 06129 char buf[128]; 06130 FILE* st; 06131 DIR* d = opendir("/proc"); 06132 if (d == NULL) { free(s); return false; } 06133 struct dirent* f; 06134 while ((f = readdir(d)) != NULL) { 06135 if (f->d_name[0] == '.') continue; 06136 for (i = 0; isdigit(f->d_name[i]); i++); 06137 if (i < strlen(f->d_name)) continue; 06138 strcpy(s, "/proc/"); 06139 strcat(s, f->d_name); 06140 strcat(s, "/status"); 06141 st = fopen(s, "r"); 06142 if (st == NULL) { closedir(d); free(s); return false; } 06143 do { 06144 if (fgets(buf, 128, st) == NULL) { fclose(st); closedir(d); free(s); return false; } 06145 } while (strncmp(buf, "Name:", 5)); 06146 fclose(st); 06147 for (i = 5; isspace(buf[i]); i++); 06148 *strchr(buf, '\n') = 0; 06149 if (!strcmp(&(buf[i]), name)) { 06150 sscanf(&(s[6]), "%d", &p); 06151 kill(p, SIGCONT); 06152 } 06153 } 06154 closedir(d); 06155 free(s); 06156 return true; 06157 } 06158 void delay(size_t ms) { 06159 struct timespec t; 06160 t.tv_sec = ms / 1000; 06161 t.tv_nsec = (ms % 1000) * (1000 * 1000); 06162 nanosleep(&t, 0); 06163 } 06164 bool envset(const char* name, const char* value) { 06165 if (value) return !setenv(name, value, 1); 06166 else return !unsetenv(name); 06167 } 06168 string envget(const char* name) { 06169 string s; 06170 char* t = getenv(name); 06171 if (t == NULL) { 06172 s.clear(); 06173 return s; 06174 } 06175 s = t; 06176 return s; 06177 } 06178 #else 06179 06180 string lsproc() { 06181 string s; 06182 PROCESSENTRY32 proc; 06183 HANDLE images = CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0); 06184 Process32First(images, &proc); 06185 while (GetLastError() != ERROR_NO_MORE_FILES) { 06186 s << proc.th32ProcessID << ':' << proc.szExeFile << '\n'; 06187 Process32Next(images, &proc); 06188 } 06189 CloseHandle(images); 06190 return s; 06191 } 06192 06193 DWORD run(const char* program, const char* argv, void* envp) { 06194 if (!fs::fexist(program)) return false; 06195 string pname = program; 06196 string args = program; 06197 fs::file f; 06198 string s; 06199 PROCESS_INFORMATION pi; 06200 STARTUPINFO si; 06201 memset(&si, 0, sizeof(STARTUPINFO)); 06202 si.cb = sizeof(STARTUPINFO); 06203 f.open(program, "rb"); 06204 if (f.getc() == '#') 06205 if (f.getc() == '!') { 06206 s = f.gets().strip(); 06207 pname = s; 06208 if (pname.chr(' ') != -1) { 06209 pname = pname.burn(' '); 06210 args = pname; 06211 args += ' '; 06212 args += s.slurp(' '); 06213 args += ' '; 06214 args += program; 06215 } 06216 } 06217 f.close(); 06218 if (argv) args = args.cat(' ').cat(argv); 06219 if (!CreateProcessA(pname, args, NULL, NULL, false, NORMAL_PRIORITY_CLASS, envp, NULL, &si, &pi)) return false; 06220 return pi.dwProcessId; 06221 } 06222 06223 bool killp(size_t pid) { return TerminateProcess(OpenProcess(PROCESS_TERMINATE, false, pid), 1); } 06224 bool killp(const char* name) { 06225 PROCESSENTRY32 p; 06226 HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); 06227 if (!Process32First(snap, &p)) { CloseHandle(snap); return false; } 06228 do { 06229 if (!strcmp(name, p.szExeFile)) 06230 if (!killp(p.th32ProcessID)) { 06231 CloseHandle(snap); 06232 return false; 06233 } 06234 } while (Process32Next(snap, &p)); 06235 CloseHandle(snap); 06236 return true; 06237 } 06238 bool freeze(size_t pid) { 06239 HANDLE snap; 06240 THREADENTRY32 t; 06241 HANDLE th; 06242 DWORD i; 06243 snap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); 06244 if (!Thread32First(snap, &t)) { CloseHandle(snap); return false; } 06245 do { 06246 06247 if (t.th32OwnerProcessID != pid) continue; 06248 th = OpenThread(THREAD_SUSPEND_RESUME, false, t.th32ThreadID); 06249 if (th == NULL) continue; 06250 i = SuspendThread(th); 06251 CloseHandle(th); 06252 if (i == -1) { CloseHandle(snap); return false; } 06253 } while (Thread32Next(snap, &t)); 06254 CloseHandle(snap); 06255 return true; 06256 } 06257 bool freeze(const char* name) { 06258 PROCESSENTRY32 p; 06259 HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); 06260 if (!Process32First(snap, &p)) { CloseHandle(snap); return false; } 06261 do { 06262 if (!strcmp(name, p.szExeFile)) 06263 if (!freeze(p.th32ProcessID)) { 06264 CloseHandle(snap); 06265 return false; 06266 } 06267 } while (Process32Next(snap, &p)); 06268 CloseHandle(snap); 06269 return true; 06270 } 06271 06272 bool cont(size_t pid) { 06273 HANDLE snap; 06274 THREADENTRY32 t; 06275 HANDLE th; 06276 DWORD i; 06277 snap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); 06278 if (!Thread32First(snap, &t)) { CloseHandle(snap); return false; } 06279 do { 06280 if (t.th32OwnerProcessID != pid) continue; 06281 th = OpenThread(THREAD_SUSPEND_RESUME, false, t.th32ThreadID); 06282 if (th == NULL) continue; 06283 i = ResumeThread(th); 06284 CloseHandle(th); 06285 if (i == -1) { CloseHandle(snap); return false; } 06286 } while (Thread32Next(snap, &t)); 06287 CloseHandle(snap); 06288 return true; 06289 } 06290 06291 bool cont(const char* name) { 06292 PROCESSENTRY32 p; 06293 HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); 06294 if (!Process32First(snap, &p)) { CloseHandle(snap); return false; } 06295 do { 06296 if (!strcmp(name, p.szExeFile)) 06297 if (!cont(p.th32ProcessID)) { 06298 CloseHandle(snap); 06299 return false; 06300 } 06301 } while (Process32Next(snap, &p)); 06302 CloseHandle(snap); 06303 return true; 06304 } 06305 06306 bool envset(const char* name, const char* value) { return SetEnvironmentVariableA(name, value); } 06307 string envget(const char* name) { 06308 DWORD i; 06309 string s; 06310 s.realloc(128); 06311 i = GetEnvironmentVariableA(name, s, 128); 06312 if (i > 128) { 06313 s = (char*)realloc(s, i); 06314 if (!GetEnvironmentVariableA(name, s, i)) { 06315 s.clear(); 06316 return s; 06317 } 06318 } else if (!i) { 06319 s.clear(); 06320 return s; 06321 } 06322 return s; 06323 } 06324 #endif 06325 06326 }; 06327 06328 proc::library::~library() { 06329 if (fd) 06330 #ifdef _WIN32 06331 FreeLibrary(fd); 06332 #else 06333 dlclose(fd); 06334 #endif 06335 } 06336 06337 proc::library& proc::library::operator =(const char* libname) { 06338 libraryname = libname; 06339 #ifdef _WIN32 06340 fd = LoadLibraryA(libname); 06341 #else 06342 fd = dlopen(libname, RTLD_LAZY); 06343 #endif 06344 return *this; 06345 } 06346 06347 proc::library& proc::library::operator= (library s) { 06348 if (fd) 06349 #ifdef _WIN32 06350 FreeLibrary(fd); 06351 #else 06352 dlclose(fd); 06353 #endif 06354 fd = s.fd; 06355 return *this; 06356 } 06357 bool proc::library::operator== (library s) { return fd == s.fd; } 06358 bool proc::library::operator!= (library s) { return fd != s.fd; } 06359 void* proc::library::operator[] (const char* name) { 06360 #ifdef _WIN32 06361 return (void*)GetProcAddress(fd, name); 06362 #else 06363 return dlsym(fd, name); 06364 #endif 06365 } 06366 namespace net { 06367 namespace irc { 06368 06369 msg::msg(const char* line) { buf = line; } 06370 msg& msg::operator= (const char* line) { buf = line; return *this; } 06371 bool msg::operator== (const char* line) { return buf == line; } 06372 bool msg::operator!= (const char* line) { return buf != line; } 06373 string msg::server() { 06374 if (buf.chr(' ') == -1) return string(); 06375 return buf.munch(':').burn(' '); 06376 } 06377 string msg::nick() { 06378 if (buf.chr('!') == -1 || buf.chr(' ') == -1) 06379 return string(); 06380 if (buf.chr('!') > buf.chr(' ')) 06381 return string(); 06382 return buf.munch(':').burn('!'); 06383 } 06384 string msg::user() { 06385 if (nick().empty()) return string(); 06386 return buf.slurp('!').burn('@'); 06387 } 06388 string msg::host() { 06389 if (nick().empty()) return string(); 06390 return buf.slurp('@').burn(' '); 06391 } 06392 string msg::cmd() { 06393 if (buf.chr(' ') == -1) return string(); 06394 return buf.tok(1, ' '); 06395 } 06396 string msg::param(int index) { 06397 if (buf.nchr(' ') < 2) return string(); 06398 return buf.shl(buf.itok(2, ' ')).tok(index, ' '); 06399 } 06400 string msg::data() { 06401 if (buf.munch(':').chr(':') == -1 || buf.chr(' ') == -1) return string(); 06402 return buf.munch(':').slurp(':'); 06403 }/* 06404 :nick!user@host cmd param1 param2 :data 06405 :server cmd param param :data 06406 msg::msg(const char* line) { 06407 if (line) this->operator=(line); 06408 else this->operator=("Expecto_patronum"); 06409 } 06410 06411 msg& msg::operator= (const msg& s) { 06412 memcpy(buf, s.buf, 536); 06413 server = 0; 06414 nick = 0; 06415 user = 0; 06416 host = 0; 06417 cmd = 0; 06418 data = 0; 06419 if (s.server) { 06420 server = buf; 06421 cmd = s.cmd - s.server + buf; 06422 data = s.data - s.server + buf; 06423 } else if (s.nick) { 06424 nick = buf; 06425 user = s.user - s.nick + buf; 06426 host = s.host - s.nick + buf; 06427 cmd = s.cmd - s.nick + buf; 06428 data = s.data - s.nick + buf; 06429 } 06430 return *this; 06431 } 06432 06433 bool msg::operator== (const char* line) { 06434 msg im(line); 06435 return *this == im; 06436 } 06437 bool msg::operator!= (const char* line) { 06438 msg im(line); 06439 return !(*this == im); 06440 } 06441 bool msg::operator== (msg im) { 06442 if (server == NULL) { if (im.server != NULL) return false; } 06443 else if (strcmp(server, im.server)) return false; 06444 if (nick == NULL) { if (im.nick != NULL) return false; } 06445 else if (strcmp(nick, im.nick)) return false; 06446 if (user == NULL) { if (im.user != NULL) return false; } 06447 else if (strcmp(user, im.user)) return false; 06448 if (host == NULL) { if (im.host != NULL) return false; } 06449 else if (strcmp(host, im.host)) return false; 06450 if (cmd == NULL) { if (im.cmd != NULL) return false; } 06451 else if (strcmp(cmd, im.cmd)) return false; 06452 if (data == NULL) { if (im.data != NULL) return false; } 06453 else if (strcmp(data, im.data)) return false; 06454 int i; 06455 const char* c = (const char*)1; 06456 for (i = 0, c = param(0); c; c = param(++i)) 06457 if (strcmp(c, im.param(i))) return false; 06458 return true; 06459 } 06460 bool msg::operator!= (msg im) { return !(this->operator==(im)); } 06461 06462 const char* msg::param(int index) { 06463 const char* a = cmd + strlen(cmd) + 1; 06464 for (; index > 0; index--) { 06465 a += strlen(a) + 1; 06466 if (a[0] == 0) return 0; 06467 } 06468 return a; 06469 } 06470 06471 msg& msg::operator= (const char* line) { 06472 int i = 0; 06473 const char *a, *b; 06474 server = 0; 06475 nick = 0; 06476 user = 0; 06477 host = 0; 06478 cmd = 0; 06479 data = 0; 06480 if (line[0] == ':') line++; 06481 a = strchr(line, '!'); 06482 b = strchr(line, ' '); 06483 if (b == NULL) return *this; 06484 if (a != NULL && a < b) { 06485 strncpy((char*)buf, line, a - line); 06486 buf[a - line] = 0; 06487 nick = buf; 06488 line += strlen(buf) + 1; 06489 06490 a = strchr(line, '@'); 06491 user = buf + strlen(buf) + 1; 06492 strncpy((char*)user, line, a - line); 06493 ((char*)user)[a - line] = 0; 06494 line += strlen(user) + 1; 06495 06496 a = strchr(line, ' '); 06497 host = user + strlen(user) + 1; 06498 strncpy((char*)host, line, a - line); 06499 ((char*)host)[a - line] = 0; 06500 line += strlen(host) + 1; 06501 06502 a = strchr(line, ' '); 06503 cmd = host + strlen(host) + 1; 06504 strncpy((char*)cmd, line, a - line); 06505 ((char*)cmd)[a - line] = 0; 06506 line += strlen(cmd) + 1; 06507 06508 } else if (a == NULL || a > b) { 06509 strncpy(buf, line, b - line); 06510 buf[b - line] = 0; 06511 server = buf; 06512 line += strlen(server) + 1; 06513 06514 a = strchr(line, ' '); 06515 cmd = server + strlen(server) + 1; 06516 strncpy((char*)cmd, line, a - line); 06517 ((char*)cmd)[a - line] = 0; 06518 line += strlen(cmd) + 1; 06519 } 06520 06521 a = cmd + strlen(cmd) + 1; 06522 for (b = strchr(line, ' '); line[0] != ':' && (*line - 1 != '\r' && *line != '\n') && line[0]; b = strpbrk(line, " \r\n")) { 06523 if (b == NULL) b = line + strlen(line); 06524 strncpy((char*)a, line, b - line); 06525 ((char*)a)[b - line] = 0; 06526 line += strlen(a) + 1; 06527 a += strlen(a) + 1; 06528 } 06529 ((char*)a)[0] = 0; 06530 a++; 06531 data = a; 06532 if (*line == '\r' || !(*line)) 06533 ((char*)data)[0] = 0; 06534 else strcpy((char*)data, ++line); 06535 ((char*)data)[strlen(data) + 1] = 0; 06536 char* x = strstr((char*)data, "\r\n"); 06537 if (x) *x = 0; 06538 return *this; 06539 }*/ 06540 06541 }; 06542 }; 06543 06544 #ifdef _WIN32 06545 06546 proc::mutex::mutex() { InitializeCriticalSection(&id); } 06547 proc::mutex::~mutex() { DeleteCriticalSection(&id); } 06548 void proc::mutex::lock() { EnterCriticalSection(&id); } 06549 bool proc::mutex::trylock() { return TryEnterCriticalSection(&id); } 06550 void proc::mutex::unlock() { LeaveCriticalSection(&id); } 06551 06552 #else 06553 proc::mutex::mutex() { pthread_mutex_init(&id, NULL); } 06554 proc::mutex::~mutex() { pthread_mutex_destroy(&id); } 06555 void proc::mutex::lock() { pthread_mutex_lock(&id); } 06556 bool proc::mutex::trylock() { return !pthread_mutex_trylock(&id); } 06557 void proc::mutex::unlock() { pthread_mutex_unlock(&id); } 06558 06559 #endif 06560 06561 #ifdef _WIN32 06562 06563 proc::semaphore::semaphore(size_t count) { init(count); } 06564 proc::semaphore::semaphore(const char* name) { open(name); } 06565 proc::semaphore::~semaphore() { if (id) CloseHandle(id); } 06566 bool proc::semaphore::init(size_t count) { 06567 named = false; 06568 if ((id = CreateSemaphore(NULL, count, UINT_MAX, NULL)) == NULL) 06569 return false; 06570 else return true; 06571 } 06572 bool proc::semaphore::die() { return !CloseHandle(id); } 06573 bool proc::semaphore::close() { return !CloseHandle(id); } 06574 bool proc::semaphore::open(const char* name) { 06575 named = true; 06576 string s = name; 06577 s -= "Global\\"; 06578 if ((id = OpenSemaphore(SEMAPHORE_MODIFY_STATE, false, s)) == NULL) 06579 return false; 06580 else return true; 06581 } 06582 bool proc::semaphore::get(size_t ms) { 06583 if (WaitForSingleObject(id, (ms ? ms : INFINITE)) == WAIT_FAILED) 06584 return true; 06585 else return false; 06586 } 06587 bool proc::semaphore::tryget() { return !WaitForSingleObject(id, 0); } 06588 bool proc::semaphore::ret() { return ReleaseSemaphore(id, 1, 0); } 06589 06590 HANDLE mksem(const char* name, size_t count) { string s = name; s -= "Global\\"; return CreateSemaphore(NULL, count, UINT_MAX, s); } 06591 06592 #else 06593 06594 06595 proc::semaphore::semaphore(size_t count) { init(count); } 06596 proc::semaphore::semaphore(const char* name) { open(name); } 06597 proc::semaphore::~semaphore() { if (id) if (named) { sem_close(id); } else { sem_destroy(id); } } 06598 bool proc::semaphore::init(size_t count) { named = false; id = &s; return !sem_init(id, 0, count); } 06599 bool proc::semaphore::die() { return !sem_destroy(id); } 06600 bool proc::semaphore::close() { return !sem_close(id); } 06601 bool proc::semaphore::open(const char* name) { 06602 named = true; 06603 char* n = (char*)malloc(strlen(name) + 2); 06604 n[0] = '/'; 06605 n[1] = 0; 06606 strcat(n, name); 06607 if ((id = sem_open(n, 0)) == SEM_FAILED) id = 0; 06608 free(n); 06609 if (!id) return false; 06610 else return true; 06611 } 06612 bool proc::semaphore::get(size_t ms) { 06613 struct timespec t; 06614 if (!ms) return !sem_wait(id); 06615 else { 06616 t.tv_sec = ms / 1000; 06617 t.tv_nsec = (ms % 1000) * (1000 * 1000); 06618 return !sem_timedwait(id, &t); 06619 } 06620 } 06621 bool proc::semaphore::tryget() { return !sem_trywait(id); } 06622 bool proc::semaphore::ret() { return !sem_post(id); } 06623 06624 sem_t* proc::mksem(const char* name, size_t count) { 06625 sem_t* s; 06626 char* n = (char*)malloc(strlen(name) + 2); 06627 n[0] = '/'; 06628 n[1] = 0; 06629 strcat(n, name); 06630 if ((s = sem_open(n, O_CREAT, O_EXCL, 0666, count)) == SEM_FAILED) { 06631 free(n); 06632 return NULL; 06633 } else { free(n); return s; } 06634 } 06635 bool proc::rmsem(const char* name) { return !sem_unlink(name); } 06636 #endif 06637 06641 string io::input::drink(const char* eol) { 06642 string s; 06643 if (!eol) eol = "\0"; 06644 if (!strlen(eol)) { 06645 register int i; 06646 for (i = getc(); ok(); i = getc()) { if (!i) break; s += (char)i; } 06647 return s; 06648 } 06649 until (s.ends(eol)) s += getc(); 06650 return s; 06651 } 06652 06656 data io::input::suck(const char* eol, size_t len) { 06657 if (!len) len = strlen(eol); 06658 data d; 06659 size_t i; 06660 for (i = 0; i < len; i++) d << getc(); 06661 return d; 06662 } 06663 06664 bool fs::file::operator! () { 06665 if (!fd) return true; 06666 if (eof() | dead()) return true; 06667 if (feof(fd)) { drain(); return true; } 06668 if (ferror(fd)) { kill(); return true; } 06669 return false; 06670 } 06674 data io::input::dump() { 06675 data d; 06676 int i; 06677 if (eof()) return d; 06678 size_t a; 06679 for (a = 0;; a++) { 06680 i = getc(); 06681 if (!ok()) break; 06682 d.putc(i); 06683 } 06684 return d; 06685 } 06686 06691 size_t io::output::write(data d) { return write(d.buf, 1, d.len()); } 06692 06693 //string proc::environment::type() { return string("proc::environ"); } 06694 06695 bool proc::pstream::open(const char* program, const char* argv, environment envp) { 06696 data d = envp.bake(); 06697 return open(program, argv, (void*)d.buf); 06698 } 06699 bool proc::pstream::open(const char* program, const char* argv, data d) { 06700 return open(program, argv, (void*)d.buf); 06701 } 06702 #ifndef _WIN32 06703 bool proc::pstream::open(const char* program, const char* argv, void* envp) { 06704 if (!fs::fexist(program)) { kill(); return false; } 06705 string gay = program; 06706 if (argv) gay = gay.cat(' ').cat(argv); 06707 wordexp_t we; 06708 char **w; 06709 wordexp(gay, &we, WRDE_NOCMD); 06710 w = we.we_wordv; 06711 char *const e[] = {NULL}; 06712 pname = program; 06713 pipe(rpipe); 06714 pipe(wpipe); 06715 p = fork(); 06716 if (!p) { 06717 ::close(rpipe[0]); 06718 ::close(wpipe[1]); 06719 dup2(wpipe[0], 0); ::close(wpipe[0]); 06720 dup2(rpipe[1], 1); ::close(rpipe[1]); 06721 if (!envp) execve(program, w, e); 06722 else execve(program, w, (char* *const)envp); 06723 wordfree(&we); 06724 } else { 06725 wordfree(&we); 06726 ::close(wpipe[0]); 06727 ::close(rpipe[1]); 06728 return true; 06729 } 06730 } 06731 #else 06732 bool proc::pstream::open(const char* program, const char* argv, void* envp) { 06733 if (!fs::fexist(program)) { kill(); return false; } 06734 pname = program; 06735 string args = program; 06736 fs::file f; 06737 string s; 06738 f.open(program, "rb"); 06739 if (f.getc() == '#') 06740 if (f.getc() == '!') { 06741 s = f.gets().strip(); 06742 pname = s; 06743 if (pname.chr(' ') != -1) { 06744 pname = pname.burn(' '); 06745 args = pname; 06746 args += ' '; 06747 args += s.slurp(' '); 06748 args += ' '; 06749 args += program; 06750 } 06751 } 06752 f.close(); 06753 if (argv) args = args.cat(' ').cat(argv); 06754 con << pname << ' ' << args << '\n'; 06755 CreatePipe(&rin, &win, NULL, 0); 06756 CreatePipe(&rout, &wout, NULL, 0); 06757 CreatePipe(&rerr, &werr, NULL, 0); 06758 SetHandleInformation(rin, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT); 06759 SetHandleInformation(wout, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT); 06760 SetHandleInformation(werr, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT); 06761 STARTUPINFOA si; 06762 PROCESS_INFORMATION pi; 06763 memset(&si, 0, sizeof(STARTUPINFOA)); 06764 si.cb = sizeof(STARTUPINFOA); 06765 si.dwFlags = STARTF_USESTDHANDLES; 06766 si.hStdInput = rin; 06767 si.hStdOutput = wout; 06768 si.hStdError = werr; 06769 if (!CreateProcessA(pname, args, NULL, NULL, true, NORMAL_PRIORITY_CLASS, envp, NULL, &si, &pi)) return false; 06770 p = pi.dwProcessId; 06771 ph = pi.hProcess; 06772 Sleep(200); 06773 return true; 06774 } 06775 #endif 06776 06777 string proc::pstream::name() { return pname; } 06778 06782 data io::input::read(size_t size, size_t nmemb) { 06783 data d; 06784 d.realloc(size * nmemb); 06785 read(d.buf, size, nmemb); 06786 return d; 06787 } 06788 06789 data net::socket::tcp::dump() { 06790 data d; 06791 char c; 06792 if (eof()) return d; 06793 for (;;) { 06794 if (ready()) { 06795 switch (::recv(fd, &c, 1, 0)) { 06796 case 0: drain(); return d; 06797 case -1: kill(); return d; 06798 case 1: d << c; 06799 } 06800 } else return d; 06801 } 06802 } 06803 06804 void proc::pstream::close() { 06805 pname.clear(); 06806 #ifndef _WIN32 06807 ::close(wpipe[0]); ::close(wpipe[1]); 06808 ::close(rpipe[0]); ::close(rpipe[1]); 06809 ::waitpid(p, NULL, 0); 06810 #else 06811 CloseHandle(rin); CloseHandle(rout); 06812 CloseHandle(win); CloseHandle(wout); 06813 DWORD d; 06814 GetExitCodeProcess(ph, &d); 06815 #endif 06816 } 06817 size_t proc::pstream::pid() { return p; } 06818 int proc::pstream::getc() { 06819 register int i; 06820 char c; 06821 #ifndef _WIN32 06822 struct pollfd pf; 06823 #else 06824 DWORD avail = 0, bleft, bread; 06825 #endif 06826 #ifndef _WIN32 06827 pf.fd = rpipe[0]; 06828 pf.events = POLLIN; 06829 poll(&pf, 1, 0); 06830 if (pf.revents & POLLIN == 0) { 06831 if (lsproc().str(this->operator string()) == -1) { kill(); return EOF; } 06832 if (!blocking) { drain(); return EOF; } 06833 } 06834 #else 06835 PeekNamedPipe(rout, &c, 1, &bread, &avail, &bleft); 06836 if (avail <= 0) { 06837 if (lsproc().str(this->operator string()) == -1) { kill(); return EOF; } 06838 if (!blocking) { drain(); return EOF; } 06839 } 06840 #endif 06841 #ifndef _WIN32 06842 switch (::read(rpipe[0], &c, 1)) { 06843 case 0: drain(); return EOF; 06844 case -1: kill(); return EOF; 06845 default: heal(); i = c; return i; 06846 } 06847 #else 06848 if (ReadFile(rout, &c, 1, &bread, 0) != 0) { 06849 if (bread == 0) { drain(); return EOF; } heal(); i = c; return i; 06850 } else { kill(); return EOF; } 06851 #endif 06852 } 06853 06854 proc::pstream::pstream() { blocking = true; } 06855 06856 int proc::pstream::putc(int c) { 06857 register char i = c; 06858 #ifndef _WIN32 06859 switch (::write(wpipe[1], &i, 1)) { 06860 case 0: drain(); return EOF; 06861 case -1: kill(); return EOF; 06862 case 1: heal(); fsync(wpipe[1]); return i; 06863 } 06864 #else 06865 DWORD bwrite; 06866 if (WriteFile(win, &i, 1, &bwrite, 0) != 0) { 06867 if (bwrite == 0) { drain(); return EOF; } heal(); FlushFileBuffers(win); return i; 06868 } else { kill(); return EOF; } 06869 #endif 06870 } 06871 06872 string proc::pstream::type() { return string("proc::pstream"); } 06873 proc::pstream::operator string () { string s; s << p; s << ':'; s << pname; return s; } 06874 06875 namespace net { 06876 namespace http { 06877 06878 field::field(const char* s) { this->operator=(s); } 06879 string field::type() { return string("net::http::field"); } 06880 field::operator string () { 06881 string s = name; 06882 s += ": "; 06883 std::deque<svarpair>::iterator it; 06884 for (it = svars.begin(); it < svars.end(); it++) { 06885 if (it->v.empty()) { svars.erase(it); it--; continue; } 06886 if (it->n.len()) { 06887 s += it->n; 06888 s += '='; 06889 } 06890 s += it->v; 06891 s += "; "; 06892 } 06893 s = s.chomp("; "); 06894 return s; 06895 } 06896 06897 string& field::var(const char* s) { 06898 if (s == 0 && svars.size()) return svars[0].v; 06899 std::deque<svarpair>::iterator it; 06900 svarpair svp; 06901 for (it = svars.begin(); it < svars.end(); it++) 06902 if (it->n == s) return it->v; 06903 if (it == svars.end()) { 06904 if (s) svp.n = string(s); 06905 else svp.n = string(); 06906 svp.v = string(); 06907 svars.push_back(svp); 06908 return svars.back().v; 06909 } 06910 } 06911 06912 string& field::operator[] (const char* v) { 06913 if (v == 0) return var(); 06914 return var(v); 06915 } 06916 06917 string field::vars() { 06918 string s; 06919 std::deque<svarpair>::iterator it; 06920 for (it = svars.begin() + 1; it < svars.end(); it++) { 06921 s += it->n; 06922 s += '\n'; 06923 } 06924 return s; 06925 } 06926 06927 field& field::operator= (const char* s) { 06928 if (strstr(s, ": ") != 0) { 06929 name = s; 06930 name = name.burn(": "); 06931 s = strstr(s, ": ") + 2; 06932 } 06933 svars.clear(); 06934 svarpair svp; 06935 if (strstr(s, "; ") == 0) { 06936 svp.v = s; 06937 svars.push_back(svp); 06938 return *this; 06939 } 06940 std::deque<string> t = string(s).split(' '); 06941 std::deque<string>::iterator it; 06942 for (it = t.begin(); it < t.end(); it++) 06943 if (it->chr('=') == -1) { 06944 svp.v = it->burn(';').rtrim(); 06945 svars.push_back(svp); 06946 } else { 06947 svp.n = it->burn('='); 06948 svp.v = it->slurp('=').burn(';').rtrim(); 06949 svars.push_back(svp); 06950 } 06951 return *this; 06952 } 06953 06954 string query::type() { return string("net::http::query"); } 06955 query::operator string() { 06956 string s; 06957 std::deque<svarpair>::iterator it; 06958 for (it = svars.begin(); it < svars.end(); it++) { 06959 if (it->v.empty()) { svars.erase(it); it--; continue; } 06960 s += it->n; 06961 s += '='; 06962 s += it->v; 06963 s += '&'; 06964 } 06965 s = s.chomp('&'); 06966 return s; 06967 } 06968 string query::vars() { 06969 string s; 06970 std::deque<svarpair>::iterator it; 06971 for (it = svars.begin(); it < svars.end(); it++) { 06972 s += it->n; 06973 s += '\n'; 06974 } 06975 return s; 06976 } 06977 string& query::var(const char* v) { 06978 svarpair svp; 06979 std::deque<svarpair>::iterator it; 06980 for (it = svars.begin(); it < svars.end(); it++) 06981 if (it->n == v) return it->v; 06982 svp.n = v; 06983 svp.v = string(); 06984 svars.push_back(svp); 06985 return svars.back().v; 06986 } 06987 string& query::operator[] (const char* s) { return var(s); } 06988 query& query::operator= (const char* s) { 06989 svars.clear(); 06990 svarpair svp; 06991 std::deque<string> t = string(s).split('&'); 06992 std::deque<string>::iterator it; 06993 for (it = t.begin(); it < t.end(); it++) { 06994 svp.n = it->tok(0, '='); 06995 svp.v = it->tok(1, '='); 06996 svars.push_back(svp); 06997 } 06998 return *this; 06999 } 07000 query::query(const char* s) { this->operator=(s); } 07001 07002 request& request::operator= (const char* s) { 07003 string t = s; 07004 t = t.chomp(); 07005 method = t.tok(0, ' ').uc(); 07006 file = t.tok(1, ' ').burn('?'); 07007 if (t.tok(1, ' ').chr('?') == -1) qstr.clear(); 07008 else qstr = t.tok(1, ' ').slurp('?'); 07009 ver = atof(t.tok(2, ' ').slurp('/')); 07010 return *this; 07011 } 07012 07013 string request::type() { return string("net::http::request"); } 07014 request::operator string () { 07015 string s; 07016 s << method << ' ' << file; 07017 if (qstr.len()) s << '?' << qstr; 07018 s << " HTTP/" << ver; 07019 return s; 07020 } 07021 07022 string response::type() { return string("net::http::response"); } 07023 response::operator string () { 07024 string s; 07025 s << "HTTP/" << ver << ' ' << code << ' ' << status << "\r\n"; 07026 return s; 07027 } 07028 response& response::operator= (const char* s) { 07029 string t = s; 07030 ver = atof(t.slurp('/')); 07031 code = atoi(t.tok(1, ' ')); 07032 status = t.shl(t.itok(2, ' ')).rtrim(); 07033 return *this; 07034 } 07035 07036 string header::type() { return string("net::http::header"); } 07037 field& header::at(size_t i) { 07038 return f[i]; 07039 } 07040 header::operator string () { 07041 string s; 07042 std::deque<field>::iterator it; 07043 for (it = f.begin(); it < f.end(); it++) { 07044 if (it->var().empty()) { f.erase(it); it--; continue; } 07045 if (it->name.empty()) { f.erase(it); it--; continue; } 07046 s = s.cat(it->operator string()).cat("\r\n"); 07047 } 07048 s += "\r\n"; 07049 return s; 07050 } 07051 string field::data() { return (this->operator string()).slurp(": ").rtrim(); } 07052 field& header::var(const char* s) { 07053 std::deque<field>::iterator it; 07054 for (it = f.begin(); it < f.end(); it++) 07055 if (it->name == s) return *it; 07056 field t; 07057 t.name = s; 07058 f.push_back(t); 07059 return f.back(); 07060 } 07061 size_t header::len() { return f.size(); } 07062 string header::vars() { 07063 string s; 07064 std::deque<field>::iterator it; 07065 for (it = f.begin(); it < f.end(); it++) { 07066 if (it->name.empty()) { f.erase(it); it--; continue; } 07067 s += it->name; 07068 s += '\n'; 07069 } 07070 return s; 07071 } 07072 field& header::operator[] (const char* s) { return var(s); } 07073 header::header(const char* s) { this->operator=(s); } 07074 header& header::clear() { 07075 f.clear(); 07076 return *this; 07077 } 07078 header& header::operator= (const char* s) { 07079 f.clear(); 07080 std::deque<string> t = string(s).rtrim().split('\n'); 07081 std::deque<string>::iterator it; 07082 for (it = t.begin(); it < t.end(); it++) { 07083 if (it->chr(':') != -1) 07084 f.push_back(field(it->rtrim().buf)); 07085 } 07086 return *this; 07087 } 07088 //header::operator const char* () { i = this->operator string (); return i.buf; } 07089 bool header::operator== (const char* s) { return this->operator string().operator==(s); } 07090 bool header::operator== (header h) { return this->operator string().operator==(h.operator string ()); } 07091 bool header::operator!= (const char* s) { return !this->operator==(s); } 07092 bool header::operator!= (header h) { return !this->operator==(h); } 07093 bool response::operator== (const char* s) { return this->operator string().operator==(s); } 07094 bool response::operator== (response h) { return this->operator string().operator==(h.operator string ()); } 07095 bool response::operator!= (const char* s) { return !this->operator==(s); } 07096 bool response::operator!= (response h) { return !this->operator==(h); } 07097 bool request::operator== (const char* s) { return this->operator string().operator==(s); } 07098 bool request::operator== (request h) { return this->operator string().operator==(h.operator string ()); } 07099 bool request::operator!= (const char* s) { return !this->operator==(s); } 07100 bool request::operator!= (request h) { return !this->operator==(h); } 07101 bool field::operator== (const char* s) { return this->operator string().operator==(s); } 07102 bool field::operator== (field h) { return this->operator string().operator==(h.operator string ()); } 07103 bool field::operator!= (const char* s) { return !this->operator==(s); } 07104 bool field::operator!= (field h) { return !this->operator==(h); } 07105 bool query::operator== (const char* s) { return this->operator string().operator==(s); } 07106 bool query::operator== (query h) { return this->operator string().operator==(h.operator string ()); } 07107 bool query::operator!= (const char* s) { return !this->operator==(s); } 07108 bool query::operator!= (query h) { return !this->operator==(h); } 07109 07110 }; 07111 }; 07112 07113 #ifdef _WIN32 07114 int net::socket::tcp::wsatoerr(int i) { 07115 switch (i) { 07116 case WSA_INVALID_HANDLE: return EINVAL; 07117 case WSA_NOT_ENOUGH_MEMORY: return ENOMEM; 07118 case WSA_INVALID_PARAMETER: return EINVAL; 07119 case WSA_OPERATION_ABORTED: return EINTR; 07120 case WSA_IO_INCOMPLETE: return EBUSY; 07121 case WSA_IO_PENDING: return EBUSY; 07122 case WSAEINTR: return EINTR; 07123 case WSAEBADF: return EBADF; 07124 case WSAEACCES: return EACCES; 07125 case WSAEFAULT: return EFAULT; 07126 case WSAEINVAL: return EINVAL; 07127 case WSAEMFILE: return EMFILE; 07128 case WSAEWOULDBLOCK: return EAGAIN; 07129 case WSAEINPROGRESS: return EINPROGRESS; 07130 case WSAEALREADY: return EALREADY; 07131 case WSAENOTSOCK: return ENOTSOCK; 07132 case WSAEDESTADDRREQ: return EDESTADDRREQ; 07133 case WSAEMSGSIZE: return EMSGSIZE; 07134 case WSAEPROTOTYPE: return EPROTOTYPE; 07135 case WSAENOPROTOOPT: return ENOPROTOOPT; 07136 case WSAEPROTONOSUPPORT: return EPROTONOSUPPORT; 07137 case WSAESOCKTNOSUPPORT: return ENOTSUP; 07138 case WSAEOPNOTSUPP: return ENOTSUP; 07139 case WSAEPFNOSUPPORT: return EAFNOSUPPORT; 07140 case WSAEAFNOSUPPORT: return EAFNOSUPPORT; 07141 case WSAEADDRINUSE: return EADDRINUSE; 07142 case WSAEADDRNOTAVAIL: return EADDRNOTAVAIL; 07143 case WSAENETDOWN: return ENETDOWN; 07144 case WSAENETUNREACH: return ENETUNREACH; 07145 case WSAENETRESET: return ENETRESET; 07146 case WSAECONNABORTED: return ECONNABORTED; 07147 case WSAECONNREFUSED: return ECONNREFUSED; 07148 case WSAENOBUFS: return ENOBUFS; 07149 case WSAENOTCONN: return ENOTCONN; 07150 case WSAESHUTDOWN: return EIO; 07151 case WSAETOOMANYREFS: return EMLINK; 07152 case WSAETIMEDOUT: return ETIMEDOUT; 07153 case WSAELOOP: return ELOOP; 07154 case WSAENAMETOOLONG: return ENAMETOOLONG; 07155 case WSAEHOSTUNREACH: return EHOSTUNREACH; 07156 case WSAENOTEMPTY: return ENOTEMPTY; 07157 case WSAEPROCLIM: return EMFILE; 07158 case WSAEUSERS: return ENOMEM; 07159 case WSAEDQUOT: return ENOMEM; 07160 case WSAESTALE: return EBADF; 07161 case WSAEREMOTE: return ENOENT; 07162 case WSASYSNOTREADY: return EBUSY; 07163 case WSAVERNOTSUPPORTED: return ENOTSUP; 07164 case WSANOTINITIALISED: return EPERM; 07165 case WSAEDISCON: return ECANCELED; 07166 case WSAENOMORE: return ENOENT; 07167 case WSAECANCELLED: return ECANCELED; 07168 case WSAEINVALIDPROCTABLE: return EINVAL; 07169 case WSAEINVALIDPROVIDER: return EINVAL; 07170 case WSAEPROVIDERFAILEDINIT: return EINTR; 07171 case WSASYSCALLFAILURE: return EINTR; 07172 case WSASERVICE_NOT_FOUND: return ENOENT; 07173 case WSATYPE_NOT_FOUND: return ENOENT; 07174 case WSA_E_NO_MORE: return ENOENT; 07175 case WSA_E_CANCELLED: return ECANCELED; 07176 case WSAEREFUSED: return ECONNREFUSED; 07177 case WSAHOST_NOT_FOUND: return EHOSTUNREACH; 07178 case WSATRY_AGAIN: return EAGAIN; 07179 case WSANO_RECOVERY: return ENOTRECOVERABLE; 07180 case WSANO_DATA: return ENODATA; 07181 default: return 0; 07182 } 07183 } 07184 #endif 07185 07186 string object::tostr() { return this->operator string(); } 07187 07188 };