5 * Implements the bio command for binary I/O
7 * bio read ?-hex? fd var length
9 * Reads 'length' bytes of binary data from 'fd' and stores an encoded string
10 * in 'var' so that the string contains no internal null characters.
12 * Returns the number of (original) chars read, which may be short if EOF is reached.
14 * bio write ?-hex? fd encoded
16 * Writes the binary-encoded string 'encoded' to 'fd'
18 * Returns the number of chars written (if no error)
20 * Note that by default no encoding is actually done since Jim supports strings containing nulls!
22 * Alternatively, if -hex is specified, the data is read and written as ascii hex
32 #include <jim-subcmd.h>
34 static int hex2char(const char *hex
)
38 value
= (hex
[0] >= 'A' ? ((hex
[0] & 0xdf) - 'A') + 10 : (hex
[0] - '0'));
40 value
+= (hex
[1] >= 'A' ? ((hex
[1] & 0xdf) - 'A') + 10 : (hex
[1] - '0'));
44 static void char2hex(int c
, char hex
[2])
46 hex
[1] = (c
& 0x0F) >= 0x0A ? (c
& 0x0F) + 'A' - 10 : (c
& 0x0F) + '0';
48 hex
[0] = (c
& 0x0F) >= 0x0A ? (c
& 0x0F) + 'A' - 10 : (c
& 0x0F) + '0';
52 * Modelled on Jim_ReadCmd
55 static int bio_cmd_read(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *argv
)
65 if (Jim_CompareStringImmediate(interp
, argv
[0], "-hex")) {
74 fh
= Jim_AioFilehandle(interp
, argv
[0]);
80 if (Jim_GetLong(interp
, argv
[2], &len
) != JIM_OK
) {
84 result
= Jim_NewStringObj(interp
, "", 0);
86 /* Read one char at a time */
96 char2hex(ch
, buf
+ count
);
103 if (count
>= sizeof(buf
)) {
104 /* Buffer is full, so append it */
105 Jim_AppendString(interp
, result
, buf
, count
);
112 Jim_SetResultString(interp
, "error during read", -1);
117 /* Add anything still pending */
118 Jim_AppendString(interp
, result
, buf
, count
);
120 if (Jim_SetVariable(interp
, argv
[1], result
) != JIM_OK
) {
124 Jim_SetResultInt(interp
, total
);
129 static int bio_cmd_copy(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *argv
)
132 long maxlen
= LONG_MAX
;
134 FILE *infh
= Jim_AioFilehandle(interp
, argv
[0]);
135 FILE *outfh
= Jim_AioFilehandle(interp
, argv
[1]);
137 if (infh
== NULL
|| outfh
== NULL
) {
142 if (Jim_GetLong(interp
, argv
[2], &maxlen
) != JIM_OK
) {
147 while (count
< maxlen
) {
148 int ch
= fgetc(infh
);
150 if (ch
== EOF
|| fputc(ch
, outfh
) == EOF
) {
157 Jim_SetResultFormatted(interp
, "error reading \"%#s\": %s", argv
[0], strerror(errno
));
163 Jim_SetResultFormatted(interp
, "error writing \"%#s\": %s", argv
[1], strerror(errno
));
168 Jim_SetResultInt(interp
, count
);
173 static int bio_cmd_write(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *argv
)
182 if (Jim_CompareStringImmediate(interp
, argv
[0], "-hex")) {
187 else if (argc
== 3) {
191 fh
= Jim_AioFilehandle(interp
, argv
[0]);
196 pt
= Jim_GetString(argv
[1], &len
);
208 if (fputc(ch
, fh
) == EOF
) {
215 Jim_SetResultString(interp
, "error during write", -1);
220 Jim_SetResultInt(interp
, total
);
225 static const jim_subcmd_type bio_command_table
[] = {
227 .function
= bio_cmd_read
,
228 .args
= "?-hex? fd var numbytes",
231 .description
= "Read binary bytes as an encoded string"
234 .function
= bio_cmd_write
,
235 .args
= "?-hex? fd buf",
238 .description
= "Write an encoded string as binary bytes"
241 .function
= bio_cmd_copy
,
242 .args
= "fromfd tofd ?bytes?",
245 .description
= "Read from one fd and write to another"
251 Jim_bioInit(Jim_Interp
*interp
)
253 Jim_CreateCommand(interp
, "bio", Jim_SubCmdProc
, (void *)bio_command_table
, NULL
);