diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/file.c | 95 | ||||
-rw-r--r-- | tools/file.h | 100 | ||||
-rw-r--r-- | tools/select.c | 52 | ||||
-rw-r--r-- | tools/select.h | 75 | ||||
-rw-r--r-- | tools/shared.c | 90 | ||||
-rw-r--r-- | tools/shared.h | 65 | ||||
-rw-r--r-- | tools/socket.c | 135 | ||||
-rw-r--r-- | tools/socket.h | 108 | ||||
-rw-r--r-- | tools/source.c | 195 | ||||
-rw-r--r-- | tools/source.h | 107 | ||||
-rw-r--r-- | tools/string.c | 454 | ||||
-rw-r--r-- | tools/string.h | 353 | ||||
-rw-r--r-- | tools/tools.c | 12 | ||||
-rw-r--r-- | tools/tools.h | 67 |
14 files changed, 1908 insertions, 0 deletions
diff --git a/tools/file.c b/tools/file.c new file mode 100644 index 0000000..2283500 --- /dev/null +++ b/tools/file.c @@ -0,0 +1,95 @@ +#include "tools/file.h" + +#include <sys/stat.h> +#include <string.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> + +cTBFile::cTBFile(void) { +} + +cTBFile::~cTBFile() { + Close(); +} + +bool cTBFile::Open(const cTBString &Filename, int Mode, mode_t Attribs) { + int filed; + + if (IsOpen()) Close(); + + if ((filed = ::open(Filename, Mode, Attribs)) == -1) + return false; + + if (!cTBSource::Open(filed)) + return false; + + m_Filename = Filename; + m_Anonymous = false; + return true; +} + +bool cTBFile::Open(uint Fileno) { + if (IsOpen()) Close(); + + if (!cTBSource::Open(Fileno)) + return false; + + m_Filename.Format("<&%d>", Fileno); + m_Anonymous = true; + return true; +} + +bool cTBFile::Close(void) { + bool ret = true; + + if (!IsOpen()) + ERRNUL(EBADF); + + if (::close(*this) == -1) + ret = false; + + if (!cTBSource::Close()) + ret = false; + + m_Filename.Clear(); + return ret; +} + +bool cTBFile::Unlink(void) const { + if (m_Filename.IsNull()) + ERRNUL(ENOENT); + + if (!IsOpen()) + ERRNUL(EBADF); + + if (m_Anonymous) + ERRNUL(EINVAL); + + return cTBFile::Unlink(m_Filename); +} + +bool cTBFile::Unlink(const cTBString &Filename) { + return (::unlink(Filename) != -1); +} + +ssize_t cTBFile::Size(void) const { + struct stat buf; + + if (!IsOpen()) + ERRSYS(EBADF); + + if (fstat(*this, &buf) == -1) + return -1; + + return buf.st_size; +} + +ssize_t cTBFile::Size(const cTBString &Filename) { + struct stat buf; + + if (stat(Filename, &buf) == -1) + return -1; + + return buf.st_size; +} diff --git a/tools/file.h b/tools/file.h new file mode 100644 index 0000000..de63e74 --- /dev/null +++ b/tools/file.h @@ -0,0 +1,100 @@ +#ifndef TOOLBOX_FILE_H +#define TOOLBOX_FILE_H + +#include "tools/tools.h" +#include "tools/source.h" +#include "tools/string.h" + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> + +/* cTBFile provides a cTBSource-derived interface for input and output on UNIX + files. */ + +class cTBFile: public cTBSource { +private: + bool m_Anonymous; + cTBString m_Filename; + + /* Unhide and forbid baseclass method */ + virtual bool Open(int Fd, bool IsUnixFd = false) { return false; } + +public: + cTBFile(void); + virtual ~cTBFile(); + + /* enum eFileType represents the modes a file can be opened with. The full + open mode is one of the first three, maybe or'ed with one of the others. + */ + enum eFileType { + ReadOnly = O_RDONLY, + WriteOnly = O_WRONLY, + ReadWrite = O_RDWR, + + Create = O_CREAT, + Exclude = O_EXCL, + Truncate = O_TRUNC, + Append = O_APPEND + }; + + /* See cTBSource::SysRead() + Reimplemented for UNIX files. */ + virtual ssize_t SysRead(void *Buffer, size_t Length) const; + + /* See cTBSource::SysWrite() + Reimplemented for UNIX files. */ + virtual ssize_t SysWrite(const void *Buffer, size_t Length) const; + + /* Open() opens the file referred to by Filename according to the given + Mode. If the file is created, it receives the attributes given by + Attribs, defaulting to rw-------. Returns true on success and false on + error, setting errno appropriately. */ + virtual bool Open(const cTBString &Filename, int Mode, + mode_t Attribs = S_IRUSR + S_IWUSR); + + /* Open() associates this file object with Fileno. Fileno must refer to a + previously opened file descriptor, which will be set non-blocking by + this call. If successful, true is returned, false otherwise and errno + is set appropriately. */ + virtual bool Open(uint Fileno); + + /* Close() closes the associated file descriptor and releases all + structures. Returns true on success and false otherwise, setting errno + appropriately. The object is in the closed state afterwards, even if + an error occured. */ + virtual bool Close(void); + + /* Unlink() unlinks (deletes) the associated file from the underlying + filesystem. Returns true on success and false otherwise, setting errno + appropriately. The file must be opened by filename to use this. */ + virtual bool Unlink(void) const; + + /* Unlink() unlinks (deletes) the file referred to by Filename from the + underlying filesystem. Returns true on success and false otherwise, + setting errno appropriately. */ + static bool Unlink(const cTBString &Filename); + + /* Size() returns the current size of the associated file. Returns the + exact size of the file in bytes. Returns -1 on error, setting errno to + an appropriate value. */ + virtual ssize_t Size(void) const; + + /* Size() returns the current size of the file referred to by Filename. + Symbolic links are followed (the size of the link-target is returned). + Returns the exact size of the file in bytes. Returns -1 on error, + setting errno to an appropriate value. */ + static ssize_t Size(const cTBString &Filename); +}; + +inline ssize_t cTBFile::SysRead(void *Buffer, size_t Length) const { + return ::read(*this, Buffer, Length); +} + +inline ssize_t cTBFile::SysWrite(const void *Buffer, size_t Length) const { + return ::write(*this, Buffer, Length); +} + + +#endif // TOOLBOX_FILE_H diff --git a/tools/select.c b/tools/select.c new file mode 100644 index 0000000..77229c8 --- /dev/null +++ b/tools/select.c @@ -0,0 +1,52 @@ +#include "tools/select.h" + +#include <vdr/tools.h> +#include <sys/time.h> +#include <sys/types.h> +#include <time.h> +#include <unistd.h> +#include <errno.h> + +cTBSelect::cTBSelect(void) { + Clear(); +} + +cTBSelect::~cTBSelect() { +} + +int cTBSelect::Select(uint TimeoutMs) { + struct timeval tv; + time_t st, et; + ssize_t res; + int ms; + + tv.tv_usec = (TimeoutMs % 1000) * 1000; + tv.tv_sec = TimeoutMs / 1000; + + if (TimeoutMs == 0) + return ::select(m_MaxFiled + 1, &m_Rfds, &m_Wfds, NULL, &tv); + + st = time_ms(); + ms = TimeoutMs; + while (ms > 0 && (res = ::select(m_MaxFiled + 1, &m_Rfds, &m_Wfds, NULL, + &tv)) == -1 && errno == EINTR) { + et = time_ms(); + ms -= et - st; + tv.tv_usec = (ms % 1000) * 1000; + tv.tv_sec = ms / 1000; + st = et; + } + if (ms <= 0) { + errno = ETIMEDOUT; + return -1; + } + return res; +} + +int cTBSelect::Select(void) { + ssize_t res; + while ((res = ::select(m_MaxFiled + 1, &m_Rfds, &m_Wfds, NULL, NULL)) == -1 + && errno == EINTR) + ; + return res; +} diff --git a/tools/select.h b/tools/select.h new file mode 100644 index 0000000..7e873e2 --- /dev/null +++ b/tools/select.h @@ -0,0 +1,75 @@ +#ifndef TOOLBOX_SELECT_H +#define TOOLBOX_SELECT_H + +#include "tools/tools.h" + +#include <sys/types.h> + +/* cTBSelect provides an interface for polling UNIX-like file descriptors. */ + +class cTBSelect { +private: + int m_MaxFiled; + + fd_set m_Rfds; + fd_set m_Wfds; + +public: + cTBSelect(void); + virtual ~cTBSelect(); + + /* Clear() resets the object for use in a new Select() call. All file + descriptors and their previous states are invalidated. */ + virtual void Clear(void); + + /* Add() adds a file descriptor to be polled in the next Select() call. + That call polls if the file is readable if Output is set to false, + writeable otherwise. */ + virtual bool Add(int Filed, bool Output = false); + + /* Select() polls all descriptors added by Add() and returns as soon as + one of those changes state (gets readable/writeable), or after + TimeoutMs milliseconds, whichever happens first. It returns the number + of filedescriptors that have changed state. On error, -1 is returned + and errno is set appropriately. */ + virtual int Select(uint TimeoutMs); + + /* Select() polls all descriptors added by Add() and returns as soon as + one of those changes state (gets readable/writeable). It returns the + number of filedescriptors that have changed state. On error, -1 is + returned and errno is set appropriately. */ + virtual int Select(void); + + /* CanRead() returns true if the descriptor has changed to readable during + the last Select() call. Otherwise false is returned. */ + virtual bool CanRead(int FileNo) const; + + /* CanWrite() returns true if the descriptor has changed to writeable + during the last Select() call. Otherwise false is returned. */ + virtual bool CanWrite(int FileNo) const; +}; + +inline void cTBSelect::Clear(void) { + FD_ZERO(&m_Rfds); + FD_ZERO(&m_Wfds); + m_MaxFiled = -1; +} + +inline bool cTBSelect::Add(int Filed, bool Output /* = false */) { + if (Filed < 0) return false; + FD_SET(Filed, Output ? &m_Wfds : &m_Rfds); + if (Filed > m_MaxFiled) m_MaxFiled = Filed; + return true; +} + +inline bool cTBSelect::CanRead(int FileNo) const { + if (FileNo < 0) return false; + return FD_ISSET(FileNo, &m_Rfds); +} + +inline bool cTBSelect::CanWrite(int FileNo) const { + if (FileNo < 0) return false; + return FD_ISSET(FileNo, &m_Wfds); +} + +#endif // TOOLBOX_SELECT_H diff --git a/tools/shared.c b/tools/shared.c new file mode 100644 index 0000000..ef20969 --- /dev/null +++ b/tools/shared.c @@ -0,0 +1,90 @@ +#include "tools/shared.h" + +#include <errno.h> +#include <stddef.h> +#include <string.h> + +cSharedData *cSharedData::Construct (size_t Length) { + size_t reallength = sizeof(cSharedData) + Length; + cSharedData *ret = (cSharedData*)new char[reallength]; + + ret->m_Length = Length; + ret->m_NumRefs = 0; + return ret; +} + +cTBShared::cTBShared(void) { + m_Buffer = NULL; +} + +cTBShared::cTBShared (const cTBShared &src) { + m_Buffer = src.m_Buffer; + if (m_Buffer) + ++*m_Buffer; +} + +cTBShared::~cTBShared () { + if (m_Buffer) + Release(); +} + +void cTBShared::Clear () { + if (m_Buffer) + Release(); + m_Buffer = 0; +} + +void cTBShared::Set (const cTBShared &src) { + if (m_Buffer) + Release(); + + m_Buffer = src.m_Buffer; + if (m_Buffer) + ++*m_Buffer; +} + +void cTBShared::Release () { + CHECK_PTR(m_Buffer); + + if (--*m_Buffer == 0) + delete[] (char*)m_Buffer; + + m_Buffer = 0; +} + +void cTBShared::Release(uint newsize) { + CHECK_PTR(m_Buffer); + + Allocate(newsize, true); +} + +void cTBShared::Exclusive () { + CHECK_PTR(m_Buffer); + + if (m_Buffer->Refs() == 1) + return; + + cSharedData *copy = cSharedData::Construct(m_Buffer->Size()); + memcpy(*copy, *m_Buffer, m_Buffer->Size()); + + Release(); + + m_Buffer = copy; + ++*m_Buffer; +} + +void cTBShared::Allocate (size_t len, bool keep /* = false */) { + if (m_Buffer && (m_Buffer->Refs() == 1) && (m_Buffer->Size() == len)) + return; + + cSharedData *newBuffer = cSharedData::Construct(len); + if (m_Buffer) { + if (keep) + memcpy(*newBuffer, *m_Buffer, len < m_Buffer->Size() ? len : m_Buffer->Size()); + + Release(); + } + m_Buffer = newBuffer; + ++*m_Buffer; +} + diff --git a/tools/shared.h b/tools/shared.h new file mode 100644 index 0000000..bacb708 --- /dev/null +++ b/tools/shared.h @@ -0,0 +1,65 @@ +#ifndef TOOLBOX_SHARED_H +#define TOOLBOX_SHARED_H + +#include "tools/tools.h" + +struct cSharedData { +private: + uint m_Length; + uint m_NumRefs; + +public: + static cSharedData *Construct (size_t Length); + + operator char * () { return this ? (char*)(this+1) : 0; } + + uint operator++ () { return ++m_NumRefs; } + uint operator-- () { return --m_NumRefs; } + + size_t Size() const { return m_Length; } + + uint Refs () const { return m_NumRefs; } +}; + +class cTBShared { +private: + cSharedData *m_Buffer; + +protected: + void Release(); + void Exclusive(); + void Allocate(size_t len, bool keep = false); + + char *Buffer() const { return m_Buffer ? (char*)*m_Buffer : (char*)0; } + +public: + cTBShared (void); + cTBShared (const cTBShared &src); + virtual ~cTBShared (); + + virtual void Clear (); + virtual void Set (const cTBShared &src); + + virtual char *Buffer (uint size); + virtual void Release (uint newsize); + + cTBShared &operator= (const cTBShared &src) { Set(src); return *this; } + + operator const void * () const { return m_Buffer ? (const void*)*m_Buffer : (const void*)0; } + operator void * () const { return m_Buffer ? (void*)*m_Buffer : (void*)0; } + + operator const char * () const { return m_Buffer ? (const char*)*m_Buffer : (const char*)0; } + + size_t Size() const { return m_Buffer ? m_Buffer->Size() : 0; } + size_t Length() const { return m_Buffer ? m_Buffer->Size() : 0; } + + // friend cSource &operator>> (cSource &dest, cTBShared &str); +}; + +inline char *cTBShared::Buffer(uint size) { + if ((!m_Buffer) || (m_Buffer->Refs() > 1) || (size > m_Buffer->Size())) + Allocate(size, true); + return Buffer(); +} + +#endif // TOOLBOX_SHARED_H diff --git a/tools/socket.c b/tools/socket.c new file mode 100644 index 0000000..46d7b9a --- /dev/null +++ b/tools/socket.c @@ -0,0 +1,135 @@ +#include "tools/socket.h" + +#include <string.h> +#include <arpa/inet.h> +#include <unistd.h> +#include <errno.h> +#include <fcntl.h> + +cTBSocket::cTBSocket(int Type) { + memset(&m_LocalAddr, 0, sizeof(m_LocalAddr)); + memset(&m_RemoteAddr, 0, sizeof(m_RemoteAddr)); + m_Type = Type; +} + +cTBSocket::~cTBSocket() { + if (IsOpen()) Close(); +} + +bool cTBSocket::Connect(const cTBString &Host, unsigned int Port) { + socklen_t len; + int socket; + + if (IsOpen()) Close(); + + if ((socket = ::socket(PF_INET, m_Type, IPPROTO_IP)) == -1) + return false; + + m_LocalAddr.sin_family = AF_INET; + m_LocalAddr.sin_port = 0; + m_LocalAddr.sin_addr.s_addr = INADDR_ANY; + if (::bind(socket, (struct sockaddr*)&m_LocalAddr, sizeof(m_LocalAddr)) + == -1) + return false; + + m_RemoteAddr.sin_family = AF_INET; + m_RemoteAddr.sin_port = htons(Port); + m_RemoteAddr.sin_addr.s_addr = inet_addr(Host); + if (::connect(socket, (struct sockaddr*)&m_RemoteAddr, + sizeof(m_RemoteAddr)) == -1) + return false; + + len = sizeof(struct sockaddr_in); + if (::getpeername(socket, (struct sockaddr*)&m_RemoteAddr, &len) == -1) + return false; + + len = sizeof(struct sockaddr_in); + if (::getsockname(socket, (struct sockaddr*)&m_LocalAddr, &len) == -1) + return false; + + return cTBSource::Open(socket); +} + +bool cTBSocket::Listen(const char *Ip, unsigned int Port, int BackLog) { + int val; + socklen_t len; + int socket; + + if (IsOpen()) Close(); + + if ((socket = ::socket(PF_INET, m_Type, IPPROTO_IP)) == -1) + return false; + + val = 1; + if (::setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) == -1) + return false; + + m_LocalAddr.sin_family = AF_INET; + m_LocalAddr.sin_port = htons(Port); + m_LocalAddr.sin_addr.s_addr = inet_addr(Ip); + if (::bind(socket, (struct sockaddr*)&m_LocalAddr, sizeof(m_LocalAddr)) + == -1) + return false; + + len = sizeof(struct sockaddr_in); + if (::getsockname(socket, (struct sockaddr*)&m_LocalAddr, &len) == -1) + return false; + + if (m_Type == SOCK_STREAM && ::listen(socket, BackLog) == -1) + return false; + + if (!cTBSource::Open(socket)) + return false; + + return true; +} + +bool cTBSocket::Accept(const cTBSocket &Listener) { + socklen_t addrlen; + int socket; + + if (IsOpen()) Close(); + + addrlen = sizeof(struct sockaddr_in); + if ((socket = ::accept(Listener, (struct sockaddr*)&m_RemoteAddr, + &addrlen)) == -1) + return false; + + addrlen = sizeof(struct sockaddr_in); + if (::getsockname(socket, (struct sockaddr*)&m_LocalAddr, &addrlen) == -1) + return false; + + if (!cTBSource::Open(socket)) + return false; + + return true; +} + +RETURNS(cTBSocket, cTBSocket::Accept(void) const, ret) + ret.Accept(*this); +RETURN(ret) + +bool cTBSocket::Close(void) { + bool ret = true; + + if (!IsOpen()) + ERRNUL(EBADF); + + if (::close(*this) == -1) + ret = false; + + if (!cTBSource::Close()) + ret = false; + + memset(&m_LocalAddr, 0, sizeof(m_LocalAddr)); + memset(&m_RemoteAddr, 0, sizeof(m_RemoteAddr)); + + return ret; +} + +bool cTBSocket::Shutdown(int how) { + if (!IsOpen()) + ERRNUL(EBADF); + + return ::shutdown(*this, how) != -1; +} diff --git a/tools/socket.h b/tools/socket.h new file mode 100644 index 0000000..a4b06ab --- /dev/null +++ b/tools/socket.h @@ -0,0 +1,108 @@ +#ifndef TOOLBOX_SOCKET_H +#define TOOLBOX_SOCKET_H + +#include "tools/tools.h" +#include "tools/source.h" +#include "tools/string.h" + +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +/* cTBSocket provides a cTBSource-derived interface for input and output on + TCP/IPv4-sockets. */ + +class cTBSocket: public cTBSource { +private: + struct sockaddr_in m_LocalAddr; + struct sockaddr_in m_RemoteAddr; + + int m_Type; + +public: + cTBSocket(int Type = SOCK_STREAM); + virtual ~cTBSocket(); + + /* See cTBSource::SysRead() + Reimplemented for TCP/IPv4 sockets. */ + virtual ssize_t SysRead(void *Buffer, size_t Length) const; + + /* See cTBSource::SysWrite() + Reimplemented for TCP/IPv4 sockets. */ + virtual ssize_t SysWrite(const void *Buffer, size_t Length) const; + + /* Connect() tries to connect an available local socket to the port given + by Port of the target host given by Host in numbers-and-dots notation + (i.e. "212.43.45.21"). Returns true if the connection attempt was + successful and false otherwise, setting errno appropriately. */ + virtual bool Connect(const cTBString &Host, uint Port); + + /* Shutdown() shuts down one or both ends of a socket. If called with How + set to SHUT_RD, further reads on this socket will be denied. If called + with SHUT_WR, all writes are denied. Called with SHUT_RDWR, all firther + action on this socket will be denied. Returns true on success and false + otherwise, setting errno appropriately. */ + virtual bool Shutdown(int How); + + /* Close() closes the associated socket and releases all structures. + Returns true on success and false otherwise, setting errno + appropriately. The object is in the closed state afterwards, regardless + of any errors. */ + virtual bool Close(void); + + /* Listen() listens on the local port Port for incoming connections. The + BackLog parameter defines the maximum length the queue of pending + connections may grow to. Returns true if the object is listening on + the specified port and false otherwise, setting errno appropriately. */ + virtual bool Listen(const char *Ip, uint Port, int BackLog); + + /* Accept() returns a newly created cTBSocket, which is connected to the + first connection request on the queue of pending connections of a + listening socket. If no connection request was pending, or if any other + error occured, the resulting cTBSocket is closed. */ + virtual cTBSocket Accept(void) const; + + /* Accept() extracts the first connection request on the queue of pending + connections of the listening socket Listener and connects it to this + object. Returns true on success and false otherwise, setting errno to + an appropriate value. */ + virtual bool Accept(const cTBSocket &Listener); + + /* LocalPort() returns the port number this socket is connected to locally. + The result is undefined for a non-open socket. */ + int LocalPort(void) const { return ntohs(m_LocalAddr.sin_port); } + + /* RemotePort() returns the port number this socket is connected to on the + remote side. The result is undefined for a non-open socket. */ + int RemotePort(void) const { return ntohs(m_RemoteAddr.sin_port); } + + /* LocalIp() returns the internet address in numbers-and-dots notation of + the interface this socket is connected to locally. This can be + "0.0.0.0" for a listening socket listening to all interfaces. If the + socket is in its closed state, the result is undefined. */ + cTBString LocalIp(void) const { return inet_ntoa(m_LocalAddr.sin_addr); } + + /* RemoteIp() returns the internet address in numbers-and-dots notation of + the interface this socket is connected to on the remote side. If the + socket is in its closed state, the result is undefined. */ + cTBString RemoteIp(void) const { return inet_ntoa(m_RemoteAddr.sin_addr); } + + in_addr_t LocalIpAddr(void) const { return m_LocalAddr.sin_addr.s_addr; } + in_addr_t RemoteIpAddr(void) const { return m_RemoteAddr.sin_addr.s_addr; } + + int Type(void) const { return m_Type; } +}; + +inline ssize_t cTBSocket::SysRead(void *Buffer, size_t Length) const { + if (m_Type == SOCK_DGRAM) { + socklen_t len = sizeof(m_RemoteAddr); + return ::recvfrom(*this, Buffer, Length, 0, (sockaddr*)&m_RemoteAddr, &len); + } else + return ::recv(*this, Buffer, Length, 0); +} + +inline ssize_t cTBSocket::SysWrite(const void *Buffer, size_t Length) const { + return ::send(*this, Buffer, Length, 0); +} + +#endif // TOOLBOX_SOCKET_H diff --git a/tools/source.c b/tools/source.c new file mode 100644 index 0000000..91c36c8 --- /dev/null +++ b/tools/source.c @@ -0,0 +1,195 @@ +#include "tools/source.h" +#include "tools/select.h" +#include "common.h" + +#include <vdr/tools.h> +#include <string.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> + +cTBSource::cTBSource(void) { + m_BytesRead = 0; + m_BytesWritten = 0; + m_Filed = -1; +} + +bool cTBSource::Open(int Filed, bool IsUnixFd) { + if (IsOpen()) + Close(); + + m_Filed = Filed; + if (IsUnixFd && ::fcntl(m_Filed, F_SETFL, O_NONBLOCK) == -1) + return false; + + return true; +} + +cTBSource::~cTBSource() { +} + +bool cTBSource::Close(void) { + if (!IsOpen()) { + errno = EBADF; + return false; + } + + m_Filed = -1; + return true; +} + +ssize_t cTBSource::Read(void *Buffer, size_t Length) { + ssize_t res; + while ((res = SysRead(Buffer, Length)) < 0 && errno == EINTR) + errno = 0; + if (res > 0) m_BytesRead += res; + return res; +} + +ssize_t cTBSource::Write(const void *Buffer, size_t Length) { + ssize_t res; + while ((res = SysWrite(Buffer, Length)) < 0 && errno == EINTR) + errno = 0; + if (res > 0) m_BytesWritten += res; + return res; +} + +bool cTBSource::TimedWrite(const void *Buffer, size_t Length, uint TimeoutMs) { + cTBSelect sel; + time_t st; + int ms, offs; + + st = time_ms(); + ms = TimeoutMs; + offs = 0; + while (Length > 0) { + int b; + + sel.Clear(); + sel.Add(m_Filed, true); + if (sel.Select(ms) == -1) + return false; + + if (sel.CanWrite(m_Filed)) { + if ((b = Write((char*)Buffer + offs, Length)) == -1) + return false; + offs += b; + Length -= b; + } + + ms -= time_ms() - st; + if (ms <= 0) { + errno = ETIMEDOUT; + return false; + } + } + return true; +} + +ssize_t cTBSource::ReadUntil(void *Buffer, size_t Length, const char *Seq, + uint TimeoutMs) { + char *offs; + time_t st; + int seqlen, ms; + size_t olen; + cTBSelect sel; + + seqlen = strlen(Seq); + if ((offs = (char*)memmem(m_LineBuffer, m_LineBuffer.Length(), Seq, seqlen))){ + olen = offs - m_LineBuffer; + if (olen >= Length) { + errno = ENOBUFS; + return -1; + } + memcpy(Buffer, m_LineBuffer, olen); + m_LineBuffer = m_LineBuffer.Mid(olen + seqlen); + Dprintf("ReadUntil: Served from Linebuffer: %d, |%.*s|\n", olen, olen - 1, + (char*)Buffer); + return olen; + } + + st = time_ms(); + ms = TimeoutMs; + while (m_LineBuffer.Length() < BUFSIZ) { + int b; + + sel.Clear(); + sel.Add(m_Filed, false); + + if (sel.Select(ms) == -1) + return -1; + + if (sel.CanRead(m_Filed)) { + offs = m_LineBuffer.Buffer(BUFSIZ); + if ((b = Read(offs + m_LineBuffer.Length(), BUFSIZ + - m_LineBuffer.Length())) == -1) + return -1; + + m_LineBuffer.Release(m_LineBuffer.Length() + b); + if ((offs = (char*)memmem(m_LineBuffer, m_LineBuffer.Length(), Seq, + seqlen))) { + olen = offs - m_LineBuffer; + if (olen >= Length) { + errno = ENOBUFS; + return -1; + } + memcpy(Buffer, m_LineBuffer, olen); + m_LineBuffer = m_LineBuffer.Mid(olen + seqlen, m_LineBuffer.Length() + - olen - seqlen); + Dprintf("ReadUntil: Served after Read: %d, |%.*s|\n", olen, olen-1, + (char*)Buffer); + return olen; + } + } + + ms -= time_ms() - st; + if (ms <= 0) { + errno = ETIMEDOUT; + return -1; + } + } + errno = ENOBUFS; + return -1; + + + +/* + cTBSelect sel; + time_t st, et; + int ms, seqlen, offs; + + seqlen = strlen(Seq); + st = time_ms(); + ms = TimeoutMs; + offs = 0; + while (Length > 0) { + int b; + + sel.Clear(); + sel.Add(m_Filed, false); + if (sel.Select(ms) == -1) + return -1; + + if (sel.CanRead(m_Filed)) { + if ((b = Read((char*)Buffer + offs, Length)) == -1) + return -1; + + offs += b; + Length -= b; + + if (memmem(Buffer, offs, Seq, seqlen) != NULL) + return offs; + } + + et = time_ms(); + ms -= et - st; + if (ms <= 0) { + errno = ETIMEDOUT; + return -1; + } + } + errno = ENOBUFS; + return -1; +*/ +} + diff --git a/tools/source.h b/tools/source.h new file mode 100644 index 0000000..09536bc --- /dev/null +++ b/tools/source.h @@ -0,0 +1,107 @@ +#ifndef TOOLBOX_SOURCE_H +#define TOOLBOX_SOURCE_H + +#include "tools/tools.h" +#include "tools/string.h" + +#include <sys/types.h> + +/* cTBSource provides an abstract interface for input and output. It can + be used to have common access to different types of UNIX-files. */ + +class cTBSource { +private: + int m_Filed; + + size_t m_BytesRead; + size_t m_BytesWritten; + + cTBString m_LineBuffer; + +public: + cTBSource(void); + virtual ~cTBSource(); + + /* SysRead() implements the low-level read on the source. It will store + data into the area pointed to by Buffer, which is at least Length + bytes in size. It will return the exact number of bytes read (which + can be fewer than requested). On error, -1 is returned, and errno + is set to an appropriate value. */ + virtual ssize_t SysRead(void *Buffer, size_t Length) const = 0; + + /* SysWrite() implements the low-level write on the source. It will write + at most Length bytes of the data pointed to by Buffer. It will return + the exact number of bytes written (which can be fewer than requested). + On error, -1 is returned, and errno is set to an appropriate value. */ + virtual ssize_t SysWrite(const void *Buffer, size_t Length) const = 0; + + /* IsOpen() returns true, if this source refers to a valid descriptor. + It is not checked whether this source is really open, so only if + opened by the appropriate Methods this function will return the + correct value */ + virtual bool IsOpen(void) const { return m_Filed != -1; } + + /* Open() associates this source with the descriptor Filed, setting it + to non-blocking mode if IsUnixFd in true. Returns true on success, + and false on error, setting errno to appropriately. + If you want to implement sources that can't be represented by UNIX + filedescriptors, you can use Filed to store any useful information + about the source. + This must be called by any derivations in an appropriate Method (like + open for files, connect for sockets). */ + virtual bool Open(int Filed, bool IsUnixFd = true); + + /* Close() resets the source to the uninitialized state (IsOpen() == false) + and must be called by any derivations after really closing the source. + Returns true on success and false on error, setting errno appropriately. + The object is in closed state afterwards, even if an error occured. */ + virtual bool Close(void); + + /* Read() reads at most Length bytes into the storage pointed to by Buffer, + which must be at least Length bytes in size, using the SysRead()- + Interface. It retries if an EINTR occurs (i.e. the low-level call was + interrupted). It returns the exact number of bytes read (which can be + fewer than requested). On error, -1 is returned, and errno is set + appropriately. */ + ssize_t Read(void *Buffer, size_t Length); + + /* Write() writes at most Length bytes from the storage pointed to by + Buffer, using the SysWrite()-Interface. It retries if EINTR occurs + (i.e. the low-level call was interrupted). It returns the exact number + of bytes written (which can be fewer than requested). On error, -1 is + returned and errno is set appropriately. */ + ssize_t Write(const void *Buffer, size_t Length); + + /* TimedWrite() tries to write Length bytes from the storage pointed to by + Buffer within the time specified by TimeoutMs, using the Write()- + Interface. On success, true is returned. On error, false is returned + and errno is set appropriately. TimedRead only works on UNIX file + descriptor sources. */ + bool TimedWrite(const void *Buffer, size_t Length, uint TimeoutMs); + + /* ReadUntil() tries to read at most Length bytes into the storage pointed + to by Buffer, which must be at least Length bytes in size, within the + time specified by TimeoutMs, using the Read()-Interface. Reading stops + after the character sequence Seq has been read and on end-of-file. + Returns the number of bytes read (if that is equal to Length, you have + to check if the buffer ends with Seq), or -1 on error, in which case + errno is set appropriately. */ + ssize_t ReadUntil(void *Buffer, size_t Length, const char *Seq, + uint TimeoutMs); + + /* BytesRead() returns the exact number of bytes read through the Read() + method since Close() has been called on this source (or since its + creation). */ + size_t BytesRead(void) const { return m_BytesRead; } + + /* BytesWritten() returns the exact number of bytes written through the + Write() method since Close() has been called on this source (or since + its creation). */ + size_t BytesWritten(void) const { return m_BytesWritten; } + + /* operator int() returns the descriptor (or informative number) associated + with this source. */ + operator int() const { return m_Filed; } +}; + +#endif // TOOLBOX_SOURCE_H diff --git a/tools/string.c b/tools/string.c new file mode 100644 index 0000000..0897ece --- /dev/null +++ b/tools/string.c @@ -0,0 +1,454 @@ +#include "tools/string.h" +#ifdef TOOLBOX_REGEX +# include "tools/regex.h" +#endif + +#include <string.h> +#include <stdarg.h> +#include <stdlib.h> +#include <stdio.h> +#include <ctype.h> +#include <limits.h> +#include <math.h> +#include <errno.h> + +const cTBString cTBString::Null; + +cTBString::cTBString(): + cTBShared(), + m_StringLen(0) { +} + +cTBString::cTBString(const cTBString &src): + cTBShared(src), + m_StringLen(src.m_StringLen) { +} + +cTBString::cTBString(const char *src) { + Set(src); +} + +cTBString::cTBString(const uchar *src) { + Set(src); +} + +cTBString::cTBString(char src) { + Set(src); +} + +cTBString::~cTBString () { +} + +void cTBString::Release(uint newsize) { + m_StringLen = newsize; + cTBShared::Release(m_StringLen + 1); + Buffer()[m_StringLen] = 0; +} + +void cTBString::Clear() { + cTBShared::Clear(); + m_StringLen = 0; +} + +void cTBString::Set(const cTBString &String) { + cTBShared::Set(String); + m_StringLen = String.m_StringLen; +} + +void cTBString::Set (const char *String) { + m_StringLen = strlen(String); + Allocate(m_StringLen + 1); + + memcpy(Buffer(), String, m_StringLen); + Buffer()[m_StringLen] = 0; +} + +void cTBString::Set (const uchar *String) { + Set((const char*)String); +} + +void cTBString::Set (char Character) { + m_StringLen = 1; + Allocate(m_StringLen + 1); + + Buffer()[0] = Character; + Buffer()[1] = 0; +} + +void cTBString::Fill(char Character, int Length) { + if (Length != -1) { + m_StringLen = Length; + Allocate(m_StringLen + 1); + } + memset(Buffer(), Character, m_StringLen); + Buffer()[m_StringLen] = 0; +} + +void cTBString::Append(const cTBString &src) { + Allocate(m_StringLen + src.m_StringLen + 1, true); + + memcpy(Buffer() + m_StringLen, src.Buffer(), src.m_StringLen); + m_StringLen += src.m_StringLen; + Buffer()[m_StringLen] = 0; +} + +void cTBString::Append(const char *src) { + uint len = strlen(src); + Allocate(m_StringLen + len + 1, true); + + memcpy(Buffer() + m_StringLen, src, len); + m_StringLen += len; + Buffer()[m_StringLen] = 0; +} + +void cTBString::Append(char src) { + Allocate(m_StringLen + 2, true); + + Buffer()[m_StringLen] = src; + ++m_StringLen; + Buffer()[m_StringLen] = 0; +} + +void cTBString::Prepend(const cTBString &src) { + Allocate(m_StringLen + src.m_StringLen + 1, true); + + memmove(Buffer() + src.m_StringLen, Buffer(), m_StringLen); + memcpy(Buffer(), src.Buffer(), src.m_StringLen); + m_StringLen += src.m_StringLen; + Buffer()[m_StringLen] = 0; +} + +void cTBString::Prepend(const char *src) { + uint len = strlen(src); + Allocate(m_StringLen + len + 1, true); + + memmove(Buffer() + len, Buffer(), m_StringLen); + memcpy(Buffer(), src, len); + m_StringLen += len; + Buffer()[m_StringLen] = 0; +} + +void cTBString::Prepend(char src) { + Allocate(m_StringLen + 2, true); + + memmove(Buffer() + 1, Buffer(), m_StringLen); + Buffer()[0] = src; + Buffer()[++m_StringLen] = 0; +} + +void cTBString::Insert(uint Index, const cTBString &String) { + Allocate(m_StringLen + String.m_StringLen + 1, true); + + memmove(Buffer() + Index + String.m_StringLen, Buffer() + Index, m_StringLen - Index); + memcpy(Buffer() + Index, String.Buffer(), String.m_StringLen); + m_StringLen += String.m_StringLen; + Buffer()[m_StringLen] = 0; +} + +void cTBString::Insert(uint Index, const char *String) { + uint len = strlen(String); + Allocate(m_StringLen + len + 1, true); + + memmove(Buffer() + Index + len, Buffer() + Index, m_StringLen - Index); + memcpy(Buffer() + Index, String, len); + m_StringLen += len; + Buffer()[m_StringLen] = 0; +} + +void cTBString::Insert(uint Index, char Character) { + Allocate(m_StringLen + 2, true); + + memmove(Buffer() + Index + 1, Buffer() + Index, m_StringLen - Index); + Buffer()[Index] = Character; + Buffer()[++m_StringLen] = 0; +} + +RETURNS(cTBString, cTBString::Left(uint count) const, ret) + if (count > m_StringLen) + count = m_StringLen; + + ret.Allocate(count + 1); + memcpy(ret.Buffer(), Buffer(), count); + ret.Buffer()[count] = 0; + ret.m_StringLen = count; +RETURN(ret) + +RETURNS(cTBString, cTBString::Right(uint count) const, ret) + if (count > m_StringLen) + count = m_StringLen; + + ret.Allocate(count + 1); + memcpy(ret.Buffer(), Buffer() + m_StringLen - count, count); + ret.Buffer()[count] = 0; + ret.m_StringLen = count; +RETURN(ret) + +RETURNS(cTBString, cTBString::Mid(int idx, int count) const, ret) + if (idx < 0) + idx = m_StringLen + idx; + + if ((count < 0) || (count > (int)m_StringLen - idx)) + count = m_StringLen - idx; + + ret.Allocate(count + 1); + memcpy(ret.Buffer(), Buffer() + idx, count); + ret.Buffer()[count] = 0; + ret.m_StringLen = count; +RETURN(ret) + +int cTBString::Find (const cTBString &String, uint Offset) const { + if (Offset >= m_StringLen) + return -1; + + char *pos = strstr(Buffer() + Offset, String.Buffer()); + if (pos) return (pos - Buffer()); + else return -1; +} + +int cTBString::Find (const char *String, uint Offset) const { + if (Offset >= m_StringLen) + return -1; + + char *pos = strstr(Buffer() + Offset, String); + if (pos) return (pos - Buffer()); + else return -1; +} + +int cTBString::Find (char Character, uint Offset) const { + if (Offset >= m_StringLen) + return -1; + + char *pos = strchr(Buffer() + Offset, Character); + if (pos) return (pos - Buffer()); + else return -1; +} + +#ifdef TOOLBOX_REGEX +bool cTBString::Find (cTBRegEx &Regex, uint Offset) const { + return Regex.Match(Buffer(), Offset); +} +#endif + +void cTBString::Format (const char *fmt, ...) { + int n, size = 128; + va_list ap; + + char *buf = Buffer(size); + + while (1) { + va_start(ap, fmt); + n = vsnprintf(buf, size, fmt, ap); + va_end(ap); + + if ((n > -1) && (n < size)) + break; + + if (n > -1) + size = n + 1; + else + size *= 2; + + buf = Buffer(size); + } + Release(n); +} + +void cTBString::Format(const cTBString &fmt, ...) { + int n, size = 128; + va_list ap; + + char *buf = Buffer(size); + + while (1) { + va_start(ap, &fmt); + n = vsnprintf(buf, size, fmt, ap); + va_end(ap); + + if ((n > -1) && (n < size)) + break; + + if (n > -1) + size = n + 1; + else + size *= 2; + + buf = Buffer(size); + } + Release(n); +} + +template<cTBString::TOFUNC F> +cTBString cTBString::ToAnything(void) const { + const char *src; + char *dest; + cTBString ret; + + src = Buffer(); + dest = ret.Buffer(m_StringLen + 1); + + for (; src < Buffer() + m_StringLen; ++src, ++dest) + *dest = F(*src); + + *dest = '\0'; + + ret.Release(m_StringLen); + return ret; +} + +template<cTBString::ISFUNC F> +bool cTBString::IsAnything(void) const { + const char *ptr = Buffer(); + + for (; ptr < Buffer() + m_StringLen; ++ptr) + if (!F(*ptr)) return false; + + return true; +} + +short cTBString::ToShort(bool *Ok) const { + long ret; + char *endptr; + bool res = false; + + ret = strtol(Buffer(), &endptr, 0); + + if (!IsEmpty() && *endptr == '\0' && ret >= SHRT_MIN && ret <= SHRT_MAX) + res = true; + + if (Ok) *Ok = res; + return (short)ret; +} + +ushort cTBString::ToUShort(bool *Ok) const { + ulong ret; + char *endptr; + bool res = false; + + ret = strtoul(Buffer(), &endptr, 0); + + if (!IsEmpty() && *endptr == '\0' && ret <= USHRT_MAX) + res = true; + + if (Ok) *Ok = res; + return (ushort)ret; +} + +int cTBString::ToInt(bool *Ok) const { + long ret; + char *endptr; + bool res = false; + + ret = strtol(Buffer(), &endptr, 0); + + if (!IsEmpty() && *endptr == '\0' && ret >= INT_MIN && ret <= INT_MAX) + res = true; + + if (Ok) *Ok = res; + return (int)ret; +} + +uint cTBString::ToUInt(bool *Ok) const { + ulong ret; + char *endptr; + bool res = false; + + ret = strtoul(Buffer(), &endptr, 0); + + if (!IsEmpty() && *endptr == '\0' && ret <= UINT_MAX) + res = true; + + if (Ok) *Ok = res; + return (uint)ret; +} + +long cTBString::ToLong(bool *Ok) const { + long ret; + char *endptr; + bool res = false; + + errno = 0; + ret = strtol(Buffer(), &endptr, 0); + + if (!IsEmpty() && *endptr == '\0' && errno != ERANGE) + res = true; + + if (Ok) *Ok = res; + return (long)ret; +} + +ulong cTBString::ToULong(bool *Ok) const { + ulong ret; + char *endptr; + bool res = false; + + errno = 0; + ret = strtoul(Buffer(), &endptr, 0); + + if (!IsEmpty() && *endptr == '\0' && errno != ERANGE) + res = true; + + if (Ok) *Ok = res; + return (ulong)ret; +} + +float cTBString::ToFloat(bool *Ok) const { + double ret; + char *endptr; + bool res = false; + + ret = strtod(Buffer(), &endptr); + + if (!IsEmpty() && *endptr == '\0' && errno != ERANGE) + res = true; + + if (Ok) *Ok = res; + return (float)ret; +} + +double cTBString::ToDouble(bool *Ok) const { + double ret; + char *endptr; + bool res = false; + + errno = 0; + ret = strtol(Buffer(), &endptr, 0); + + if (!IsEmpty() && *endptr == '\0' && errno != ERANGE) + res = true; + + if (Ok) *Ok = res; + return (double)ret; +} + +RETURNS(cTBString, cTBString::Number(short Num), ret) + ret.Format("%hd", Num); +RETURN(ret) + +RETURNS(cTBString, cTBString::Number(ushort Num), ret) + ret.Format("%hu", Num); +RETURN(ret) + +RETURNS(cTBString, cTBString::Number(int Num), ret) + ret.Format("%d", Num); +RETURN(ret) + +RETURNS(cTBString, cTBString::Number(uint Num), ret) + ret.Format("%u", Num); +RETURN(ret) + +RETURNS(cTBString, cTBString::Number(long Num), ret) + ret.Format("%ld", Num); +RETURN(ret) + +RETURNS(cTBString, cTBString::Number(ulong Num), ret) + ret.Format("%lu", Num); +RETURN(ret) + +RETURNS(cTBString, cTBString::Number(float Num), ret) + ret.Format("%f", Num); +RETURN(ret) + +RETURNS(cTBString, cTBString::Number(double Num), ret) + ret.Format("%f", Num); +RETURN(ret) + diff --git a/tools/string.h b/tools/string.h new file mode 100644 index 0000000..2e81929 --- /dev/null +++ b/tools/string.h @@ -0,0 +1,353 @@ +#ifndef TOOLBOX_STRING_H +#define TOOLBOX_STRING_H + +#include "tools/tools.h" +#include "tools/shared.h" +//#include "tools/source.h" + +#include <ctype.h> +#include <stddef.h> +#include <string.h> + +#ifdef TOOLBOX_REGEX +class cTBRegEx; +#endif + +class cTBString: public cTBShared { +private: + uint m_StringLen; + + /* Unhide and forbid baseclass method */ + virtual void Set (const cTBShared &src) {} + +public: + cTBString (); + cTBString (const cTBString &src); + cTBString (const uchar *src); + cTBString (const char *src); + cTBString (char src); + virtual ~cTBString (); + + static const cTBString Null; + + void Clear (); + void Set (const cTBString &String); + void Set (const uchar *String); + void Set (const char *String); + void Set (char Character); + + void Fill (char Character, int Length = -1); + + void Release (uint newsize); + + cTBString &operator= (const cTBString &src) { Set(src); return *this; } + cTBString &operator= (const char *src) { Set(src); return *this; } + cTBString &operator= (char src) { Set(src); return *this; } + + void Append (const cTBString &src); + void Append (const char *src); + void Append (char src); + + friend cTBString operator+ (const cTBString &a, const cTBString &b); + friend cTBString operator+ (const cTBString &a, const char *b); + friend cTBString operator+ (const char *a, const cTBString &b); + friend cTBString operator+ (const cTBString &a, char b); + friend cTBString operator+ (char a, const cTBString &b); + + friend cTBString &operator+= (cTBString &a, const cTBString &b); + friend cTBString &operator+= (cTBString &a, const char *b); + friend cTBString &operator+= (cTBString &a, char b); + + void Prepend (const cTBString &src); + void Prepend (const char *src); + void Prepend (char src); + + void Insert (uint Index, const cTBString &src); + void Insert (uint Index, const char *src); + void Insert (uint Index, char src); + + char At (uint i) const; + char operator[] (int i) const { return At((uint)i); } + + char &At (uint i); + char &operator[] (int i) { return At(i); } + + cTBString Left (uint Count) const; + cTBString Right (uint Count) const; + cTBString Mid (int idx, int Count = -1) const; + + int Find (const cTBString &String, uint Offset = 0) const; + int Find (const char *String, uint Offset = 0) const; + int Find (char Character, uint Offset = 0) const; +#ifdef TOOLBOX_REGEX + bool Find (cTBRegEx &Regex, uint Offset = 0) const; +#endif + + void Format (const char *fmt, ...) +#if defined(__GNUC__) + __attribute__ ((format (printf, 2, 3))) +#endif + ; + void Format (const cTBString &fmt, ...); + + typedef int(*TOFUNC)(int); + template<TOFUNC F> cTBString ToAnything(void) const; + + cTBString ToUpper (void) const { return ToAnything<toupper>(); } + cTBString ToLower (void) const { return ToAnything<tolower>(); } + + typedef int(*ISFUNC)(int); + template<ISFUNC F> bool IsAnything(void) const; + + bool IsAlnum(void) const { return IsAnything<isalnum>(); } + bool IsAlpha(void) const { return IsAnything<isalpha>(); } + bool IsAscii(void) const { return IsAnything<isascii>(); } + bool IsCntrl(void) const { return IsAnything<iscntrl>(); } + bool IsDigit(void) const { return IsAnything<isdigit>(); } + bool IsGraph(void) const { return IsAnything<isgraph>(); } + bool IsLower(void) const { return IsAnything<islower>(); } + bool IsPrint(void) const { return IsAnything<isprint>(); } + bool IsPunct(void) const { return IsAnything<ispunct>(); } + bool IsSpace(void) const { return IsAnything<isspace>(); } + bool IsUpper(void) const { return IsAnything<isupper>(); } + bool IsXdigit(void) const { return IsAnything<isxdigit>(); } + +#if defined(_GNU_SOURCE) + bool IsBlank(void) const { return IsAnything<isblank>(); } +#endif + + uint Length (void) const { return m_StringLen; } + bool IsEmpty (void) const { return m_StringLen == 0; } + bool IsNull (void) const { return Buffer() == 0; } + + short ToShort(bool *Ok = NULL) const; + ushort ToUShort(bool *Ok = NULL) const; + int ToInt(bool *Ok = NULL) const; + uint ToUInt(bool *Ok = NULL) const; + long ToLong(bool *Ok = NULL) const; + ulong ToULong(bool *Ok = NULL) const; + float ToFloat(bool *Ok = NULL) const; + double ToDouble(bool *Ok = NULL) const; + + static cTBString Number(short Num); + static cTBString Number(ushort Num); + static cTBString Number(int Num); + static cTBString Number(uint Num); + static cTBString Number(long Num); + static cTBString Number(ulong Num); + static cTBString Number(float Num); + static cTBString Number(double Num); + + friend bool operator== (const cTBString &str1, const cTBString &str2); + friend bool operator== (const cTBString &str1, const char *str2); + friend bool operator== (const char *str1, const cTBString &str2); + + friend bool operator!= (const cTBString &str1, const cTBString &str2); + friend bool operator!= (const cTBString &str1, const char *str2); + friend bool operator!= (const char *str1, const cTBString &str2); + + friend bool operator< (const cTBString &str1, const cTBString &str2); + friend bool operator< (const cTBString &str1, const char *str2); + friend bool operator< (const char *str1, const cTBString &str2); + + friend bool operator> (const cTBString &str1, const cTBString &str2); + friend bool operator> (const cTBString &str1, const char *str2); + friend bool operator> (const char *str1, const cTBString &str2); + + friend bool operator<= (const cTBString &str1, const cTBString &str2); + friend bool operator<= (const cTBString &str1, const char *str2); + friend bool operator<= (const char *str1, const cTBString &str2); + + friend bool operator>= (const cTBString &str1, const cTBString &str2); + friend bool operator>= (const cTBString &str1, const char *str2); + friend bool operator>= (const char *str1, const cTBString &str2); +}; + +inline char cTBString::At(uint idx) const { + ASSERT(idx >= m_StringLen); + return Buffer() ? Buffer()[idx] : 0; +} + +inline char &cTBString::At(uint idx) { + static char null = 0; + ASSERT(idx >= m_StringLen); + if (Buffer()) { + Exclusive(); + return Buffer()[idx]; + } else + return (null = 0); +} + +inline +RETURNS(cTBString, operator+(const cTBString &a, const cTBString &b), ret(a)) + ret.Append(b); +RETURN(ret) + +inline +RETURNS(cTBString, operator+ (const cTBString &a, const char *b), ret(a)) + ret.Append(b); +RETURN(ret) + +inline +RETURNS(cTBString, operator+ (const char *a, const cTBString &b), ret(a)) + ret.Append(b); +RETURN(ret) + +inline +RETURNS(cTBString, operator+ (const cTBString &a, char b), ret(a)) + ret.Append(b); +RETURN(ret) + +inline +RETURNS(cTBString, operator+ (char a, const cTBString &b), ret(a)) + ret.Append(b); +RETURN(ret) + +inline cTBString &operator+= (cTBString &a, const cTBString &b) { + a.Append(b); + return a; +} + +inline cTBString &operator+= (cTBString &a, const char *b) { + a.Append(b); + return a; +} + +inline cTBString &operator+= (cTBString &a, char b) { + a.Append(b); + return a; +} + +inline bool operator== (const cTBString &str1, const cTBString &str2) { + if (str1.Length() != str2.Length()) + return false; + return memcmp(str1.Buffer(), str2.Buffer(), str1.Length()) == 0; +} + +inline bool operator== (const cTBString &str1, const char *str2) { + uint len = strlen(str2); + if (str1.Length() != len) + return false; + return memcmp(str1.Buffer(), str2, len) == 0; +} + +inline bool operator== (const char *str1, const cTBString &str2) { + uint len = strlen(str1); + if (len != str2.Length()) + return false; + return memcmp(str1, str2.Buffer(), len) == 0; +} + +inline bool operator!= (const cTBString &str1, const cTBString &str2) { + if (str1.Length() != str2.Length()) + return true; + return memcmp(str1.Buffer(), str2.Buffer(), str1.Length()) != 0; +} + +inline bool operator!= (const cTBString &str1, const char *str2) { + uint len = strlen(str2); + if (str1.Length() != len) + return true; + return memcmp(str1.Buffer(), str2, len) != 0; +} + +inline bool operator!= (const char *str1, const cTBString &str2) { + uint len = strlen(str1); + if (len != str2.Length()) + return true; + return memcmp(str1, str2.Buffer(), len) != 0; +} + +inline bool operator< (const cTBString &str1, const cTBString &str2) { + int ret = memcmp(str1.Buffer(), str2.Buffer(), str1.Length() < str2.Length() ? str1.Length() : str2.Length()); + if ((ret < 0) || ((ret == 0) && (str1.Length() < str2.Length()))) + return true; + return false; +} + +inline bool operator< (const cTBString &str1, const char *str2) { + uint len = strlen(str2); + int ret = memcmp(str1.Buffer(), str2, str1.Length() < len ? str1.Length() : len); + if ((ret < 0) || ((ret == 0) && (str1.Length() < len))) + return true; + return false; +} + +inline bool operator< (const char *str1, const cTBString &str2) { + uint len = strlen(str1); + int ret = memcmp(str1, str2.Buffer(), len < str2.Length() ? len : str2.Length()); + if ((ret < 0) || ((ret == 0) && (len < str2.Length()))) + return true; + return false; +} + +inline bool operator> (const cTBString &str1, const cTBString &str2) { + int ret = memcmp(str1.Buffer(), str2.Buffer(), str1.Length() < str2.Length() ? str1.Length() : str2.Length()); + if ((ret > 0) || ((ret == 0) && (str1.Length() < str2.Length()))) + return true; + return false; +} + +inline bool operator> (const cTBString &str1, const char *str2) { + uint len = strlen(str2); + int ret = memcmp(str1.Buffer(), str2, str1.Length() < len ? str1.Length() : len); + if ((ret > 0) || ((ret == 0) && (str1.Length() < len))) + return true; + return false; +} + +inline bool operator> (const char *str1, const cTBString &str2) { + uint len = strlen(str1); + int ret = memcmp(str1, str2.Buffer(), len < str2.Length() ? len : str2.Length()); + if ((ret > 0) || ((ret == 0) && (len < str2.Length()))) + return true; + return false; +} + +inline bool operator<= (const cTBString &str1, const cTBString &str2) { + int ret = memcmp(str1.Buffer(), str2.Buffer(), str1.Length() < str2.Length() ? str1.Length() : str2.Length()); + if ((ret < 0) || ((ret == 0) && (str1.Length() <= str2.Length()))) + return true; + return false; +} + +inline bool operator<= (const cTBString &str1, const char *str2) { + uint len = strlen(str2); + int ret = memcmp(str1.Buffer(), str2, str1.Length() < len ? str1.Length() : len); + if ((ret < 0) || ((ret == 0) && (str1.Length() <= len))) + return true; + return false; +} + +inline bool operator<= (const char *str1, const cTBString &str2) { + uint len = strlen(str1); + int ret = memcmp(str1, str2.Buffer(), len < str2.Length() ? len : str2.Length()); + if ((ret < 0) || ((ret == 0) && (len <= str2.Length()))) + return true; + return false; +} + +inline bool operator>= (const cTBString &str1, const cTBString &str2) { + int ret = memcmp(str1.Buffer(), str2.Buffer(), str1.Length() < str2.Length() ? str1.Length() : str2.Length()); + if ((ret > 0) || ((ret == 0) && (str1.Length() >= str2.Length()))) + return true; + return false; +} + +inline bool operator>= (const cTBString &str1, const char *str2) { + uint len = strlen(str2); + int ret = memcmp(str1.Buffer(), str2, str1.Length() < len ? str1.Length() : len); + if ((ret > 0) || ((ret == 0) && (str1.Length() >= len))) + return true; + return false; +} + +inline bool operator>= (const char *str1, const cTBString &str2) { + uint len = strlen(str1); + int ret = memcmp(str1, str2.Buffer(), len < str2.Length() ? len : str2.Length()); + if ((ret > 0) || ((ret == 0) && (len >= str2.Length()))) + return true; + return false; +} + +#endif // TOOLBOX_STRING_H diff --git a/tools/tools.c b/tools/tools.c new file mode 100644 index 0000000..fa813fa --- /dev/null +++ b/tools/tools.c @@ -0,0 +1,12 @@ +#include "tools/tools.h" + +#include <sys/time.h> +#include <time.h> +#include <sys/types.h> +#include <unistd.h> +#include <stdarg.h> + +void *operator new(size_t nSize, void *p) throw () { + return p; +} + diff --git a/tools/tools.h b/tools/tools.h new file mode 100644 index 0000000..ab00c60 --- /dev/null +++ b/tools/tools.h @@ -0,0 +1,67 @@ +#ifndef TOOLBOX_TOOLS_H +#define TOOLBOX_TOOLS_H + +//#include <stdio.h> +//#include <iostream> +#include <sys/types.h> + +//#define KILOBYTE(x) ((x)*1024) +//#define MEGABYTE(x) (KILOBYTE(x)*1024) + +//typedef unsigned int uint; +//typedef unsigned long ulong; +typedef unsigned char uchar; +//typedef unsigned short ushort; + +// Special constructor for CreateElements +void *operator new(size_t, void*) throw (); + +#ifdef TOOLBOX_DEBUG +# define ASSERT(x) if ((x)) cerr << "Warning: ASSERT failed At " << __FILE__ << ":" << __LINE__ << " ["#x"]" << endl +# define CHECK_PTR(x) if (!(x)) cerr << "Warning: Pointer is NULL At " << __FILE__ << ":" << __LINE__ << endl; +# define CHECK_NEXT_ALLOC() _checkNextAlloc() +# define DPRINT(x...) LOGi(x) +#else +# define ASSERT(x) +# define CHECK_PTR(x) +# define CHECK_NEXT_ALLOC() +# define DPRINT(x...) +#endif + +#define ERRNUL(e) {errno=e;return 0;} +#define ERRSYS(e) {errno=e;return -1;} + +/* RETURNS() and RETURN() are macros that can be used if a class object is + being returned. They make use of the GNU C-Compiler's named return value + feature, if available. In this case, the class object isn't returned and + copied, but the result itself is filled. + + RETURNS(ReturnType, FunctionDeclaration, Result) + ... function-body working on Result ... + RETURN(Result) + + A function like this (cXYZ is a class type): + + cXYZ myfunction(int a, char *b) { + cXYZ result; + ... something happens with result ... + return result; + } + + can be written like this: + + RETURNS(cXYZ, myfunction(int a, char *b), result) + ... something happens with result ... + RETURN(result) + + DISABLED SINCE GCC 3.x +*/ +//#ifdef __GNUC__ +//# define RETURNS(t,x,r) t x return r { +//# define RETURN(x) } +//#else +# define RETURNS(t,x,r) t x { t r; +# define RETURN(x) return x; } +//#endif + +#endif // TOOLBOX_TOOLS_H |