Skip to content

Commit f22b8c4

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 <[email protected]>
1 parent 5575c55 commit f22b8c4

File tree

2 files changed

+136
-19
lines changed

2 files changed

+136
-19
lines changed

jim-aio.c

Lines changed: 52 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1127,15 +1127,60 @@ 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], haylen);
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+
/* Expect an option here */
1162+
if (*Jim_String(argv[0]) != '-') {
1163+
return JIM_USAGE;
1164+
}
1165+
1166+
if (Jim_GetEnum(interp, argv[0], options, &opt, NULL, JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) {
1167+
return JIM_ERR;
1168+
}
1169+
1170+
switch (opt) {
1171+
case OPT_EOL:
1172+
nlstr = Jim_GetString(argv[1], &nlstrlen);
1173+
break;
1174+
1175+
case OPT_KEEP:
1176+
if (Jim_GetLong(interp, argv[1], &keepnl) != JIM_OK) {
1177+
return JIM_ERR;
1178+
}
1179+
break;
1180+
}
1181+
argc -= 2;
1182+
argv += 2;
1183+
}
11391184

11401185
errno = 0;
11411186

@@ -1148,12 +1193,12 @@ static int aio_cmd_gets(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
11481193
while (!aio_eof(af)) {
11491194
if (af->readbuf) {
11501195
const char *pt = Jim_GetString(af->readbuf, &len);
1151-
nl = memchr(pt + offset, '\n', len - offset);
1196+
nl = jim_strstr(pt + offset, len - offset, nlstr, nlstrlen);
11521197
if (nl) {
11531198
/* got a line */
1154-
objPtr = Jim_NewStringObj(interp, pt, nl - pt);
1155-
/* And consume it plus the newline */
1156-
aio_consume(af->readbuf, nl - pt + 1);
1199+
objPtr = Jim_NewStringObj(interp, pt, nl - pt + (keepnl ? nlstrlen : 0));
1200+
/* And consume it plus the eol */
1201+
aio_consume(af->readbuf, nl - pt + nlstrlen);
11571202
break;
11581203
}
11591204
offset = len;
@@ -2169,10 +2214,10 @@ static const jim_subcmd_type aio_command_table[] = {
21692214
/* Description: Internal command to return the taint of the channel. */
21702215
},
21712216
{ "gets",
2172-
"?var?",
2217+
"?-eol <str>? ?-keep 0|1? ?var?",
21732218
aio_cmd_gets,
21742219
0,
2175-
1,
2220+
-1,
21762221
/* Description: Read one line and return it or store it in the var */
21772222
},
21782223
{ "puts",

tests/aio.test

Lines changed: 84 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ $f puts test-data
1111
$f close
1212
# create a test file file with several lines
1313
set f [open copy.in wb]
14-
$f puts line1
15-
$f puts line2
16-
$f puts line3
14+
$f puts line1xy
15+
$f puts line2xy
16+
$f puts line3xy
1717
$f close
1818

1919
set f [open testdata.in rb]
@@ -94,10 +94,82 @@ test aio-3.2 {copy bad length} -body {
9494

9595
set badvar a
9696

97-
test aio-4.1 {gets invalid var} -body {
97+
test aio-4.1 {gets usage} -body {
98+
$f gets abc def
99+
} -returnCodes error -match glob -result {wrong # args: should be "* gets ?-eol <str>? ?-keep 0|1? ?var?"}
100+
101+
test aio-4.2 {gets invalid option} -body {
102+
$f gets -xyz 3 def
103+
} -returnCodes error -result {bad option "-xyz": must be -eol, or -keep}
104+
105+
test aio-4.3 {gets invalid var} -body {
98106
$f gets badvar(abc)
99107
} -returnCodes error -result {can't set "badvar(abc)": variable isn't array}
100108

109+
test aio-4.4 {gets -eol} -body {
110+
set ff [open copy.in]
111+
set rc [$ff gets -eol y\n buf]
112+
$ff close
113+
list $rc $buf
114+
} -result {6 line1x}
115+
116+
test aio-4.5 {gets -eol} -body {
117+
set ff [open copy.in]
118+
set rc [$ff gets -eol 2xy\n buf]
119+
$ff close
120+
list $rc $buf
121+
} -result {12 {line1xy
122+
line}}
123+
124+
test aio-4.6 {gets -keep} -body {
125+
set ff [open copy.in]
126+
set rc [$ff gets -keep 1 buf]
127+
$ff close
128+
list $rc $buf
129+
} -result {8 {line1xy
130+
}}
131+
132+
test aio-4.7 {gets -eol -keep} -body {
133+
set ff [open copy.in]
134+
set rc [$ff gets -keep 1 -eol 2xy\n buf]
135+
$ff close
136+
list $rc $buf
137+
} -result {16 {line1xy
138+
line2xy
139+
}}
140+
141+
test aio-4.8 {gets -eol no var} -body {
142+
set ff [open copy.in]
143+
set buf [$ff gets -eol xy -keep 1]
144+
$ff close
145+
set buf
146+
} -result line1xy
147+
148+
test aio-4.9 {gets -keep 0 count} -body {
149+
set ff [open copy.in]
150+
set count [$ff gets -keep 0 buf]
151+
$ff close
152+
list $count $buf
153+
} -result {7 line1xy}
154+
155+
test aio-4.10 {gets -keep 1 count} -body {
156+
set ff [open copy.in]
157+
set count [$ff gets -keep 1 buf]
158+
$ff close
159+
list $count $buf
160+
} -result {8 {line1xy
161+
}}
162+
163+
test aio-4.11 {gets -eol multiple calls} -body {
164+
set ff [open copy.in]
165+
set lines {}
166+
lappend lines [$ff gets -eol xy\n]
167+
lappend lines [$ff gets -eol xy\n]
168+
lappend lines [$ff gets -eol xy\n]
169+
$ff close
170+
set lines
171+
} -result {line1 line2 line3}
172+
101173
test aio-5.1 {puts usage} -body {
102174
stdout puts -badopt abc
103175
} -returnCodes error -result {wrong # args: should be "stdout puts ?-nonewline? str"}
@@ -188,19 +260,19 @@ test copyto-1.1 {basic copyto} {
188260
set result [list [$ff gets] [$ff gets] [$ff gets]]
189261
$ff close
190262
set result
191-
} {line1 line2 line3}
263+
} {line1xy line2xy line3xy}
192264

193265
test copyto-1.2 {copyto with limit} {
194266
set in [open copy.in]
195267
set out [open copy.out w]
196-
$in copyto $out 8
268+
$in copyto $out 10
197269
$in close
198270
$out close
199271
set ff [open copy.out]
200272
set result [list [$ff gets] [$ff gets] [$ff gets]]
201273
$ff close
202274
set result
203-
} {line1 li {}}
275+
} {line1xy li {}}
204276

205277
test copyto-1.3 {copyto after gets} {
206278
set in [open copy.in]
@@ -213,7 +285,7 @@ test copyto-1.3 {copyto after gets} {
213285
set result [list [$ff gets] [$ff gets] [$ff gets]]
214286
$ff close
215287
set result
216-
} {line2 line3 {}}
288+
} {line2xy line3xy {}}
217289

218290
test copyto-1.4 {copyto after read} {
219291
set in [open copy.in]
@@ -226,7 +298,7 @@ test copyto-1.4 {copyto after read} {
226298
set result [list [$ff gets] [$ff gets] [$ff gets]]
227299
$ff close
228300
set result
229-
} {e1 line2 line3}
301+
} {e1xy line2xy line3xy}
230302

231303
test copyto-1.5 {copyto after gets, seek} {
232304
set in [open copy.in]
@@ -240,7 +312,7 @@ test copyto-1.5 {copyto after gets, seek} {
240312
set result [list [$ff gets] [$ff gets] [$ff gets]]
241313
$ff close
242314
set result
243-
} {ne1 line2 line3}
315+
} {ne1xy line2xy line3xy}
244316

245317
test copyto-1.6 {copyto from pipe} {
246318
set in [open "|cat copy.in"]
@@ -252,7 +324,7 @@ test copyto-1.6 {copyto from pipe} {
252324
set result [list [$ff gets] [$ff gets] [$ff gets]]
253325
$ff close
254326
set result
255-
} {line1 line2 line3}
327+
} {line1xy line2xy line3xy}
256328

257329
test copyto-1.6 {copyto to pipe} {
258330
set out [open "|cat >copy.out" w]
@@ -264,7 +336,7 @@ test copyto-1.6 {copyto to pipe} {
264336
set result [list [$ff gets] [$ff gets] [$ff gets]]
265337
$ff close
266338
set result
267-
} {line1 line2 line3}
339+
} {line1xy line2xy line3xy}
268340

269341
# Creates a child process and returns {pid writehandle}
270342
# The child expects to read $numlines lines of input and exits with a return

0 commit comments

Comments
 (0)