Skip to content

Commit 70b29d7

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 70b29d7

File tree

2 files changed

+128
-18
lines changed

2 files changed

+128
-18
lines changed

jim-aio.c

Lines changed: 53 additions & 7 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], 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+
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,12 +1194,12 @@ 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);
1155-
/* And consume it plus the newline */
1156-
aio_consume(af->readbuf, nl - pt + 1);
1200+
objPtr = Jim_NewStringObj(interp, pt, nl - pt + (keepnl ? nlstrlen : 0));
1201+
/* And consume it plus the eol */
1202+
aio_consume(af->readbuf, nl - pt + nlstrlen);
11571203
break;
11581204
}
11591205
offset = len;
@@ -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: 75 additions & 11 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]
@@ -98,6 +98,70 @@ 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 y\n buf]
104+
$ff close
105+
list $rc $buf
106+
} -result {6 line1x}
107+
108+
test aio-4.3 {gets -eol} -body {
109+
set ff [open copy.in]
110+
set rc [$ff gets -eol 2xy\n buf]
111+
$ff close
112+
list $rc $buf
113+
} -result {12 {line1xy
114+
line}}
115+
116+
test aio-4.4 {gets -keep} -body {
117+
set ff [open copy.in]
118+
set rc [$ff gets -keep 1 buf]
119+
$ff close
120+
list $rc $buf
121+
} -result {8 {line1xy
122+
}}
123+
124+
test aio-4.5 {gets -eol -keep} -body {
125+
set ff [open copy.in]
126+
set rc [$ff gets -keep 1 -eol 2xy\n buf]
127+
$ff close
128+
list $rc $buf
129+
} -result {16 {line1xy
130+
line2xy
131+
}}
132+
133+
test aio-4.6 {gets -eol no var} -body {
134+
set ff [open copy.in]
135+
set buf [$ff gets -eol xy -keep 1]
136+
$ff close
137+
set buf
138+
} -result line1xy
139+
140+
test aio-4.7 {gets -keep 0 count} -body {
141+
set ff [open copy.in]
142+
set count [$ff gets -keep 0 buf]
143+
$ff close
144+
list $count $buf
145+
} -result {7 line1xy}
146+
147+
test aio-4.8 {gets -keep 1 count} -body {
148+
set ff [open copy.in]
149+
set count [$ff gets -keep 1 buf]
150+
$ff close
151+
list $count $buf
152+
} -result {8 {line1xy
153+
}}
154+
155+
test aio-4.9 {gets -eol multiple calls} -body {
156+
set ff [open copy.in]
157+
set lines {}
158+
lappend lines [$ff gets -eol xy\n]
159+
lappend lines [$ff gets -eol xy\n]
160+
lappend lines [$ff gets -eol xy\n]
161+
$ff close
162+
set lines
163+
} -result {line1 line2 line3}
164+
101165
test aio-5.1 {puts usage} -body {
102166
stdout puts -badopt abc
103167
} -returnCodes error -result {wrong # args: should be "stdout puts ?-nonewline? str"}
@@ -188,19 +252,19 @@ test copyto-1.1 {basic copyto} {
188252
set result [list [$ff gets] [$ff gets] [$ff gets]]
189253
$ff close
190254
set result
191-
} {line1 line2 line3}
255+
} {line1xy line2xy line3xy}
192256

193257
test copyto-1.2 {copyto with limit} {
194258
set in [open copy.in]
195259
set out [open copy.out w]
196-
$in copyto $out 8
260+
$in copyto $out 10
197261
$in close
198262
$out close
199263
set ff [open copy.out]
200264
set result [list [$ff gets] [$ff gets] [$ff gets]]
201265
$ff close
202266
set result
203-
} {line1 li {}}
267+
} {line1xy li {}}
204268

205269
test copyto-1.3 {copyto after gets} {
206270
set in [open copy.in]
@@ -213,7 +277,7 @@ test copyto-1.3 {copyto after gets} {
213277
set result [list [$ff gets] [$ff gets] [$ff gets]]
214278
$ff close
215279
set result
216-
} {line2 line3 {}}
280+
} {line2xy line3xy {}}
217281

218282
test copyto-1.4 {copyto after read} {
219283
set in [open copy.in]
@@ -226,7 +290,7 @@ test copyto-1.4 {copyto after read} {
226290
set result [list [$ff gets] [$ff gets] [$ff gets]]
227291
$ff close
228292
set result
229-
} {e1 line2 line3}
293+
} {e1xy line2xy line3xy}
230294

231295
test copyto-1.5 {copyto after gets, seek} {
232296
set in [open copy.in]
@@ -240,7 +304,7 @@ test copyto-1.5 {copyto after gets, seek} {
240304
set result [list [$ff gets] [$ff gets] [$ff gets]]
241305
$ff close
242306
set result
243-
} {ne1 line2 line3}
307+
} {ne1xy line2xy line3xy}
244308

245309
test copyto-1.6 {copyto from pipe} {
246310
set in [open "|cat copy.in"]
@@ -252,7 +316,7 @@ test copyto-1.6 {copyto from pipe} {
252316
set result [list [$ff gets] [$ff gets] [$ff gets]]
253317
$ff close
254318
set result
255-
} {line1 line2 line3}
319+
} {line1xy line2xy line3xy}
256320

257321
test copyto-1.6 {copyto to pipe} {
258322
set out [open "|cat >copy.out" w]
@@ -264,7 +328,7 @@ test copyto-1.6 {copyto to pipe} {
264328
set result [list [$ff gets] [$ff gets] [$ff gets]]
265329
$ff close
266330
set result
267-
} {line1 line2 line3}
331+
} {line1xy line2xy line3xy}
268332

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

0 commit comments

Comments
 (0)