#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "pth.h"
#include "test_common.h"
#define READLINE_MAXLEN 1024
static pth_key_t readline_key;
static pth_once_t readline_once_ctrl = PTH_ONCE_INIT;
typedef struct {
int rl_cnt;
char *rl_bufptr;
char rl_buf[READLINE_MAXLEN];
} readline_buf;
static void readline_buf_destroy(void *vp)
{
free(vp);
return;
}
static void readline_init(void *vp)
{
pth_key_create(&readline_key, readline_buf_destroy);
return;
}
ssize_t pth_readline(int fd, void *buf, size_t buflen)
{
return pth_readline_ev(fd, buf, buflen, NULL);
}
ssize_t pth_readline_ev(int fd, void *buf, size_t buflen, pth_event_t ev_extra)
{
size_t n;
ssize_t rc;
char c = '\0', *cp;
readline_buf *rl;
pth_once(&readline_once_ctrl, readline_init, NULL);
if ((rl = (readline_buf *)pth_key_getdata(readline_key)) == NULL) {
rl = (readline_buf *)malloc(sizeof(readline_buf));
rl->rl_cnt = 0;
rl->rl_bufptr = NULL;
pth_key_setdata(readline_key, rl);
}
cp = (char *)buf;
for (n = 1; n < buflen; n++) {
rc = 1;
if (rl->rl_cnt <= 0) {
if ((rl->rl_cnt = pth_read_ev(fd, rl->rl_buf, READLINE_MAXLEN, ev_extra)) < 0)
rc = -1;
else if (rl->rl_cnt == 0)
rc = 0;
else
rl->rl_bufptr = rl->rl_buf;
}
if (rc == 1) {
rl->rl_cnt--;
c = *rl->rl_bufptr++;
}
if (rc == 1) {
if (c == '\r') {
n--;
continue;
}
*cp++ = c;
if (c == '\n')
break;
}
else if (rc == 0) {
if (n == 1)
return 0;
else
break;
}
else
return -1;
}
*cp = NUL;
return n;
}