Skip to content

Commit 109c33c

Browse files
committed
aio: add support for gets ?-eol <eolstr>? ?-keep 0|1?
This can make it easier to read non-newline based protocols with gets, especially in conjunction with timeout. Signed-off-by: Steve Bennett <steveb@workware.net.au>
1 parent 5575c55 commit 109c33c

File tree

2 files changed

+106
-5
lines changed

2 files changed

+106
-5
lines changed

jim-aio.c

Lines changed: 51 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1127,15 +1127,61 @@ static int aio_cmd_copy(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
11271127
return JIM_OK;
11281128
}
11291129

1130+
/* Like strstr() but optimised in the case the the needle is of length 1 */
1131+
static const char *jim_strstr(const char *haystack, int haylen, const char *needle, int needlen)
1132+
{
1133+
if (needlen == 1) {
1134+
return (const char *)memchr(haystack, needle[0], strlen(haystack));
1135+
}
1136+
return strstr(haystack, needle);
1137+
}
1138+
11301139
static int aio_cmd_gets(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
11311140
{
11321141
AioFile *af = Jim_CmdPrivData(interp);
11331142
Jim_Obj *objPtr = NULL;
11341143
int len;
11351144
int nb;
11361145
unsigned flags = AIO_ONEREAD;
1137-
char *nl = NULL;
1146+
const char *nl = NULL;
11381147
int offset = 0;
1148+
long keepnl = 0;
1149+
const char *nlstr = "\n";
1150+
int nlstrlen = 1;
1151+
1152+
while (argc >= 2) {
1153+
enum {OPT_EOL, OPT_KEEP};
1154+
static const char * const options[] = {
1155+
"-eol",
1156+
"-keep",
1157+
NULL
1158+
};
1159+
int opt;
1160+
1161+
if (Jim_GetEnum(interp, argv[0], options, &opt, NULL, JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) {
1162+
return JIM_ERR;
1163+
}
1164+
1165+
switch (opt) {
1166+
case OPT_EOL:
1167+
nlstr = Jim_GetString(argv[1], &nlstrlen);
1168+
break;
1169+
1170+
case OPT_KEEP:
1171+
if (Jim_GetLong(interp, argv[1], &keepnl) != JIM_OK) {
1172+
return JIM_ERR;
1173+
}
1174+
break;
1175+
default:
1176+
return JIM_ERR;
1177+
}
1178+
argc -= 2;
1179+
argv += 2;
1180+
}
1181+
1182+
if (argc > 1) {
1183+
return JIM_USAGE;
1184+
}
11391185

11401186
errno = 0;
11411187

@@ -1148,10 +1194,10 @@ static int aio_cmd_gets(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
11481194
while (!aio_eof(af)) {
11491195
if (af->readbuf) {
11501196
const char *pt = Jim_GetString(af->readbuf, &len);
1151-
nl = memchr(pt + offset, '\n', len - offset);
1197+
nl = jim_strstr(pt + offset, len - offset, nlstr, nlstrlen);
11521198
if (nl) {
11531199
/* got a line */
1154-
objPtr = Jim_NewStringObj(interp, pt, nl - pt);
1200+
objPtr = Jim_NewStringObj(interp, pt, nl - pt + (keepnl ? nlstrlen : 0));
11551201
/* And consume it plus the newline */
11561202
aio_consume(af->readbuf, nl - pt + 1);
11571203
break;
@@ -2169,10 +2215,10 @@ static const jim_subcmd_type aio_command_table[] = {
21692215
/* Description: Internal command to return the taint of the channel. */
21702216
},
21712217
{ "gets",
2172-
"?var?",
2218+
"?-eol <str>? ?-keep 0|1? ?var?",
21732219
aio_cmd_gets,
21742220
0,
2175-
1,
2221+
-1,
21762222
/* Description: Read one line and return it or store it in the var */
21772223
},
21782224
{ "puts",

tests/aio.test

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,61 @@ test aio-4.1 {gets invalid var} -body {
9898
$f gets badvar(abc)
9999
} -returnCodes error -result {can't set "badvar(abc)": variable isn't array}
100100

101+
test aio-4.2 {gets -eol} -body {
102+
set ff [open copy.in]
103+
set rc [$ff gets -eol 2 buf]
104+
$ff close
105+
list $rc $buf
106+
} -result {10 {line1
107+
line}}
108+
109+
test aio-4.3 {gets -keep} -body {
110+
set ff [open copy.in]
111+
set rc [$ff gets -keep 1 buf]
112+
$ff close
113+
list $rc $buf
114+
} -result {6 {line1
115+
}}
116+
117+
test aio-4.4 {gets -eol -keep} -body {
118+
set ff [open copy.in]
119+
set rc [$ff gets -keep 1 -eol 2 buf]
120+
$ff close
121+
list $rc $buf
122+
} -result {11 {line1
123+
line2}}
124+
125+
test aio-4.5 {gets -eol -keep chars} -body {
126+
set ff [open copy.in]
127+
set rc [$ff gets -eol ne2 -keep 1 buf]
128+
$ff close
129+
list $rc $buf
130+
} -result {11 {line1
131+
line2}}
132+
133+
test aio-4.6 {gets -eol no var} -body {
134+
set ff [open copy.in]
135+
set buf [$ff gets -eol ne2 -keep 1]
136+
$ff close
137+
set buf
138+
} -result {line1
139+
line2}
140+
141+
test aio-4.7 {gets -keep 0 count} -body {
142+
set ff [open copy.in]
143+
set count [$ff gets -keep 0 buf]
144+
$ff close
145+
list $count $buf
146+
} -result {5 line1}
147+
148+
test aio-4.8 {gets -keep 1 count} -body {
149+
set ff [open copy.in]
150+
set count [$ff gets -keep 1 buf]
151+
$ff close
152+
list $count $buf
153+
} -result {6 {line1
154+
}}
155+
101156
test aio-5.1 {puts usage} -body {
102157
stdout puts -badopt abc
103158
} -returnCodes error -result {wrong # args: should be "stdout puts ?-nonewline? str"}

0 commit comments

Comments
 (0)