int selectresolution,
const char **Error);
-
int StrBufSipLine(StrBuf *LineBuf, StrBuf *Buf, const char **Ptr);
-
-typedef enum _eReadState {
- eReadFail,
- eReadSuccess,
- eMustReadMore,
- eBufferNotEmpty
-} eReadState;
-
-typedef struct _file_buffer {
- StrBuf *Buf;
- const char *ReadWritePointer;
- int fd;
- int LineCompleted;
- int nBlobBytesWanted;
-} IOBuffer;
-
-long StrBuf_read_one_chunk_callback (int fd, short event, IOBuffer *FB);
-int StrBuf_write_one_chunk_callback(int fd, short event, IOBuffer *FB);
-
-eReadState StrBufChunkSipLine(StrBuf *LineBuf, IOBuffer *FB);
-eReadState StrBufCheckBuffer(IOBuffer *FB);
-
-
int StrBufReplaceToken(StrBuf *Buf, long where, long HowLong, const char *Repl, long ReplLen);
int StrBufExtract_token(StrBuf *dest, const StrBuf *Source, int parmnum, char separator);
int StrBufSub(StrBuf *dest, const StrBuf *Source, unsigned long Offset, size_t nChars);
return 0;
}
-/*******************************************************************************
- * File I/O; Callbacks to libevent *
- *******************************************************************************/
-
-long StrBuf_read_one_chunk_callback (int fd, short event, IOBuffer *FB)
-{
- long bufremain = 0;
- int n;
-
- /*
- * check whether the read pointer is somewhere in a range
- * where a cut left is inexpensive
- */
- if (FB->ReadWritePointer != NULL)
- {
- long already_read = FB->ReadWritePointer - FB->Buf->buf;
- bufremain = FB->Buf->BufSize - FB->Buf->BufUsed;
-
- if (already_read != 0) {
- long unread = FB->Buf->BufUsed - already_read;
- /* else nothing to compact... */
- if (unread == 0) {
- FB->ReadWritePointer = FB->Buf->buf;
- bufremain = FB->Buf->BufSize;
- }
- else if ((unread < 64) ||
- (bufremain < already_read))
- {
- /*
- * if its just a tiny bit remaining, or we run out of space...
- * lets tidy up.
- */
- FB->Buf->BufUsed = unread;
- if (unread < already_read)
- memcpy(FB->Buf->buf, FB->ReadWritePointer, unread);
- else
- memmove(FB->Buf->buf, FB->ReadWritePointer, unread);
- FB->ReadWritePointer = FB->Buf->buf;
- bufremain = FB->Buf->BufSize - unread;
- }
- else if (bufremain < (FB->Buf->BufSize / 10)) {
- /* get a bigger buffer */ ///TODO: special increase function that won't copy the already read!
- IncreaseBuf(FB->Buf, 0, -1);
- FB->ReadWritePointer = FB->Buf->buf + unread;
- bufremain = FB->Buf->BufSize - unread;
- }
- }
-
- }
- else {
- FB->ReadWritePointer = FB->Buf->buf;
- bufremain = FB->Buf->BufSize;
- }
- n = read(fd, FB->Buf->buf + FB->Buf->BufUsed, bufremain - 1);
-
- if (n > 0) {
- FB->Buf->BufUsed += n;
- FB->Buf->buf[FB->Buf->BufUsed] = '\0';
- }
- return n;
-}
-
-int StrBuf_write_one_chunk_callback(int fd, short event, IOBuffer *FB)
-{
- long WriteRemain;
- int n;
-
- if (FB->ReadWritePointer != NULL)
- {
- WriteRemain = FB->Buf->BufUsed -
- (FB->ReadWritePointer -
- FB->Buf->buf);
- }
- else {
- FB->ReadWritePointer = FB->Buf->buf;
- WriteRemain = FB->Buf->BufUsed;
- }
-
- n = write(fd, FB->ReadWritePointer, WriteRemain);
- if (n > 0) {
- FB->ReadWritePointer += n;
-
- if (FB->ReadWritePointer ==
- FB->Buf->buf + FB->Buf->BufUsed)
- {
- FlushStrBuf(FB->Buf);
- FB->ReadWritePointer = NULL;
- return 0;
- }
- // check whether we've got something to write
- // get the maximum chunk plus the pointer we can send
- // write whats there
- // if not all was sent, remember the send pointer for the next time
- return FB->ReadWritePointer - FB->Buf->buf + FB->Buf->BufUsed;
- }
- return n;
-}
-
-/**
- * @ingroup StrBuf_IO
- * @brief extract a "next line" from Buf; Ptr to persist across several iterations
- * @param LineBuf your line will be copied here.
- * @param FB BLOB with lines of text...
- * @param Ptr moved arround to keep the next-line across several iterations
- * has to be &NULL on start; will be &NotNULL on end of buffer
- * @returns size of copied buffer
- */
-eReadState StrBufChunkSipLine(StrBuf *LineBuf, IOBuffer *FB)
-{
- const char *aptr, *ptr, *eptr;
- char *optr, *xptr;
-
- if ((FB->Buf == NULL) || (FB->ReadWritePointer == StrBufNOTNULL)) {
- FB->ReadWritePointer = StrBufNOTNULL;
- return eReadFail;
- }
-
- FlushStrBuf(LineBuf);
- if (FB->ReadWritePointer == NULL)
- ptr = aptr = FB->Buf->buf;
- else
- ptr = aptr = FB->ReadWritePointer;
-
- optr = LineBuf->buf;
- eptr = FB->Buf->buf + FB->Buf->BufUsed;
- xptr = LineBuf->buf + LineBuf->BufSize - 1;
-
- while ((ptr <= eptr) &&
- (*ptr != '\n') &&
- (*ptr != '\r') )
- {
- *optr = *ptr;
- optr++; ptr++;
- if (optr == xptr) {
- LineBuf->BufUsed = optr - LineBuf->buf;
- IncreaseBuf(LineBuf, 1, LineBuf->BufUsed + 1);
- optr = LineBuf->buf + LineBuf->BufUsed;
- xptr = LineBuf->buf + LineBuf->BufSize - 1;
- }
- }
- if (ptr >= eptr) {
- if (optr > LineBuf->buf)
- optr --;
- if ((*(ptr - 1) != '\r') && (*(ptr - 1) != '\n')) {
- LineBuf->BufUsed = optr - LineBuf->buf;
- *optr = '\0';
- return eMustReadMore;
- }
- }
- LineBuf->BufUsed = optr - LineBuf->buf;
- *optr = '\0';
- if ((ptr <= eptr) && (*ptr == '\r'))
- ptr ++;
- if ((ptr <= eptr) && (*ptr == '\n'))
- ptr ++;
-
- if (ptr < eptr) {
- FB->ReadWritePointer = ptr;
- }
- else {
- FlushStrBuf(FB->Buf);
- FB->ReadWritePointer = NULL;
- }
-
- return eReadSuccess;
-}
-
-/**
- * @ingroup StrBuf_CHUNKED_IO
- * @brief check whether the chunk-buffer has more data waiting or not.
- * @param FB Chunk-Buffer to inspect
- */
-eReadState StrBufCheckBuffer(IOBuffer *FB)
-{
- if (FB == NULL)
- return eReadFail;
- if (FB->Buf->BufUsed == 0)
- return eReadSuccess;
- if (FB->ReadWritePointer == NULL)
- return eBufferNotEmpty;
- if (FB->Buf->buf + FB->Buf->BufUsed > FB->ReadWritePointer)
- return eBufferNotEmpty;
- return eReadSuccess;
-}
/*******************************************************************************
* File I/O; Prefer buffered read since its faster! *