diff options
author | Mattias Andrée <m@maandree.se> | 2025-02-20 20:24:28 +0100 |
---|---|---|
committer | Mattias Andrée <m@maandree.se> | 2025-02-20 20:24:28 +0100 |
commit | 4c745dab4c6925fa17714c2214ed5941e5cbf64d (patch) | |
tree | 30129b2838d7a27a7a37fd37f5f95d6b355b7203 | |
parent | Add state marshalling and unmarshalling functions (diff) | |
download | libterminput-4c745dab4c6925fa17714c2214ed5941e5cbf64d.tar.gz libterminput-4c745dab4c6925fa17714c2214ed5941e5cbf64d.tar.bz2 libterminput-4c745dab4c6925fa17714c2214ed5941e5cbf64d.tar.xz |
Validate unmarshalled state + add man pages for (un)marshal functions
Signed-off-by: Mattias Andrée <m@maandree.se>
-rw-r--r-- | Makefile | 30 | ||||
-rw-r--r-- | common.h | 89 | ||||
-rw-r--r-- | libterminput.h | 130 | ||||
l--------- | libterminput_marshal_input.3 | 1 | ||||
-rw-r--r-- | libterminput_marshal_keypress__.c | 2 | ||||
-rw-r--r-- | libterminput_marshal_mouseevent__.c | 2 | ||||
-rw-r--r-- | libterminput_marshal_state.3 | 121 | ||||
-rw-r--r-- | libterminput_marshal_text__.c | 4 | ||||
-rw-r--r-- | libterminput_read.3 | 4 | ||||
-rw-r--r-- | libterminput_set_flags.3 | 4 | ||||
l--------- | libterminput_unmarshal_input.3 | 1 | ||||
-rw-r--r-- | libterminput_unmarshal_input.c | 24 | ||||
-rw-r--r-- | libterminput_unmarshal_keypress__.c | 6 | ||||
-rw-r--r-- | libterminput_unmarshal_mouseevent__.c | 19 | ||||
-rw-r--r-- | libterminput_unmarshal_position__.c | 2 | ||||
-rw-r--r-- | libterminput_unmarshal_state.3 | 122 | ||||
-rw-r--r-- | libterminput_unmarshal_state.c | 27 | ||||
-rw-r--r-- | libterminput_unmarshal_text__.c | 11 |
18 files changed, 557 insertions, 42 deletions
@@ -11,7 +11,7 @@ include mk/$(OS).mk LIB_MAJOR = 1 -LIB_MINOR = 0 +LIB_MINOR = 1 LIB_VERSION = $(LIB_MAJOR).$(LIB_MINOR) @@ -19,22 +19,14 @@ MAN3 =\ libterminput_read.3\ libterminput_is_ready.3\ libterminput_set_flags.3\ - libterminput_clear_flags.3 + libterminput_clear_flags.3\ + libterminput_marshal_input.3\ + libterminput_marshal_state.3\ + libterminput_unmarshal_input.3\ + libterminput_unmarshal_state.3 OBJ =\ $(MAN3:.3=.o)\ - libterminput_marshal_input.o\ - libterminput_marshal_state.o\ - libterminput_unmarshal_input.o\ - libterminput_unmarshal_state.o\ - libterminput_marshal_keypress__.o\ - libterminput_marshal_text__.o\ - libterminput_marshal_mouseevent__.o\ - libterminput_marshal_position__.o\ - libterminput_unmarshal_keypress__.o\ - libterminput_unmarshal_text__.o\ - libterminput_unmarshal_mouseevent__.o\ - libterminput_unmarshal_position__.o\ libterminput_encode_utf8__.o\ libterminput_check_utf8_char__.o\ libterminput_utf8_decode__.o\ @@ -44,7 +36,15 @@ OBJ =\ libterminput_parse_csi_t_mouse_tracking__.o\ libterminput_parse_csi_small_t_mouse_tracking__.o\ libterminput_parse_sequence__.o\ - libterminput_read_symbol__.o + libterminput_read_symbol__.o\ + libterminput_marshal_keypress__.o\ + libterminput_marshal_text__.o\ + libterminput_marshal_mouseevent__.o\ + libterminput_marshal_position__.o\ + libterminput_unmarshal_keypress__.o\ + libterminput_unmarshal_text__.o\ + libterminput_unmarshal_mouseevent__.o\ + libterminput_unmarshal_position__.o HDR =\ libterminput.h\ @@ -5,6 +5,7 @@ #include <ctype.h> #include <errno.h> #include <limits.h> +#include <stdint.h> #include <string.h> #include <unistd.h> @@ -143,14 +144,100 @@ HIDDEN void libterminput_parse_sequence__(union libterminput_input *input, struc */ HIDDEN int libterminput_read_symbol__(int fd, struct input *input, struct libterminput_state *ctx); -/* TODO doc, test */ +/** + * Marshal the parsed input + * + * @param how Object used to store the serialization + * @param what The input to marshal + * @return 0 on success, -1 on failure + * + * This function will fail for any reason `*how->store` fails + */ HIDDEN int libterminput_marshal_keypress__(struct libterminput_marshaller *how, const struct libterminput_keypress *what); + +/** + * Marshal the parsed input + * + * @param how Object used to store the serialization + * @param what The input to marshal + * @return 0 on success, -1 on failure + * + * This function will fail for any reason `*how->store` fails + */ HIDDEN int libterminput_marshal_text__(struct libterminput_marshaller *how, const struct libterminput_text *what); + +/** + * Marshal the parsed input + * + * @param how Object used to store the serialization + * @param what The input to marshal + * @return 0 on success, -1 on failure + * + * This function will fail for any reason `*how->store` fails + */ HIDDEN int libterminput_marshal_mouseevent__(struct libterminput_marshaller *how, const struct libterminput_mouseevent *what); + +/** + * Marshal the parsed input + * + * @param how Object used to store the serialization + * @param what The input to marshal + * @return 0 on success, -1 on failure + * + * This function will fail for any reason `*how->store` fails + */ HIDDEN int libterminput_marshal_position__(struct libterminput_marshaller *how, const struct libterminput_position *what); + +/** + * Unmarshal the parsed input + * + * @param how Object used to load the serialization + * @param what Output parameter for the unmarshalled input + * @return 0 on success, -1 on failure + * + * @throws EINVAL Invalid serialisation + * + * This function will fail for any reason `*how->load` fails + */ HIDDEN int libterminput_unmarshal_keypress__(struct libterminput_unmarshaller *how, struct libterminput_keypress *what); + +/** + * Unmarshal the parsed input + * + * @param how Object used to load the serialization + * @param what Output parameter for the unmarshalled input + * @return 0 on success, -1 on failure + * + * @throws EINVAL Invalid serialisation + * + * This function will fail for any reason `*how->load` fails + */ HIDDEN int libterminput_unmarshal_text__(struct libterminput_unmarshaller *how, struct libterminput_text *what); + +/** + * Unmarshal the parsed input + * + * @param how Object used to load the serialization + * @param what Output parameter for the unmarshalled input + * @return 0 on success, -1 on failure + * + * @throws EINVAL Invalid serialisation + * + * This function will fail for any reason `*how->load` fails + */ HIDDEN int libterminput_unmarshal_mouseevent__(struct libterminput_unmarshaller *how, struct libterminput_mouseevent *what); + +/** + * Unmarshal the parsed input + * + * @param how Object used to load the serialization + * @param what Output parameter for the unmarshalled input + * @return 0 on success, -1 on failure + * + * @throws EINVAL Invalid serialisation + * + * This function will fail for any reason `*how->load` fails + */ HIDDEN int libterminput_unmarshal_position__(struct libterminput_unmarshaller *how, struct libterminput_position *what); diff --git a/libterminput.h b/libterminput.h index d69cb0d..ce82ad0 100644 --- a/libterminput.h +++ b/libterminput.h @@ -10,6 +10,8 @@ * set or clear his flag after setting or clearing it on * the terminal, and the user must make sure that the * terminal support this flag if set + * + * @since 1.0 (applies to all members unless stated otherwise) */ enum libterminput_flags { /** @@ -81,6 +83,8 @@ enum libterminput_flags { * risk of misparsing input. However, if mouse tracking * is not activated, it makes since to enable this * flag. + * + * @since 1.1 */ LIBTERMINPUT_MACRO_ON_BLOCK = 0x0080 }; @@ -91,6 +95,8 @@ enum libterminput_flags { * * These are the commonly reported modifiers, * but additional modifiers are possible + * + * @since 1.0 (applies to all members unless stated otherwise) */ enum libterminput_mod { /** @@ -118,6 +124,8 @@ enum libterminput_mod { * against, not compiled against, so other values can be * reported the application is linked against a newer version * of the library than it is compiled against + * + * @since 1.0 (applies to all members unless stated otherwise) */ enum libterminput_key { /** @@ -178,6 +186,8 @@ enum libterminput_key { LIBTERMINPUT_KEYPAD_COMMA, LIBTERMINPUT_KEYPAD_POINT, LIBTERMINPUT_KEYPAD_ENTER + +#define LIBTERMINPUT_KEYPAD__LAST__ LIBTERMINPUT_KEYPAD_ENTER /* for internal use */ }; @@ -186,6 +196,8 @@ enum libterminput_key { * * It is possible that non-listed buttons are * reported in events + * + * @since 1.0 (applies to all members unless stated otherwise) */ enum libterminput_button { /** @@ -270,6 +282,8 @@ enum libterminput_button { /** * Input event type + * + * @since 1.0 (applies to all members unless stated otherwise) */ enum libterminput_type { /** @@ -323,6 +337,8 @@ enum libterminput_type { /** * Mouse event subtype + * + * @since 1.0 (applies to all members unless stated otherwise) */ enum libterminput_event { /** @@ -359,6 +375,8 @@ enum libterminput_event { * particularly when mouse tracking is disabled. * In particular, mouse scrolling may appear as * repeated Up key or Down key pesses + * + * @since 1.0 (applies to all members unless stated otherwise) */ struct libterminput_keypress { /** @@ -404,6 +422,8 @@ struct libterminput_keypress { /** * Text from a bracketed paste + * + * @since 1.0 (applies to all members unless stated otherwise) */ struct libterminput_text { /** @@ -434,6 +454,8 @@ struct libterminput_text { /** * Mouse event + * + * @since 1.0 (applies to all members unless stated otherwise) */ struct libterminput_mouseevent { /** @@ -509,6 +531,8 @@ struct libterminput_mouseevent { /** * Cursor position response + * + * @since 1.0 (applies to all members unless stated otherwise) */ struct libterminput_position { /** @@ -534,6 +558,8 @@ struct libterminput_position { /** * Input event + * + * @since 1.0 (applies to all members unless stated otherwise) */ union libterminput_input { /** @@ -584,6 +610,8 @@ union libterminput_input { * NB! This struct should be considered opaque * * Initialised with by setting all bytes to 0 + * + * @since 1.0 */ struct libterminput_state { int inited; /* whether the input in initialised, not this struct */ @@ -599,6 +627,7 @@ struct libterminput_state { unsigned char paused : 1; /* 1 if the available buffered input is incomplete */ unsigned char blocked : 1; /* 1 if the available no data was available for read(2) */ unsigned char queued : 1; /* 1 if a keypress is queued for output if there is no more data at next read(2) */ + unsigned char unused_bits : 5; /* should be zero due to how the struct should be initialised */ unsigned char npartial; /* number of bytes available in `.partial` */ char partial[7]; /* partially read character */ char key[44]; /* processed bytes the identify the pressed key or non-key-press event */ @@ -606,9 +635,26 @@ struct libterminput_state { }; -/* TODO doc */ +/** + * User provided function and associated binary + * data used to store the state + * + * @since 1.1 (applies to all members unless stated otherwise) + */ struct libterminput_marshaller { + /** + * Callback function to store data + * + * @param this Pointer to the object containing this function + * @param data The data to store + * @param size The number of bytes in `data` + * @return 0 on success, -1 on failure + */ int (*store)(struct libterminput_marshaller *this, const void *data, size_t size); + + /** + * User-defined data + */ union { void *ptr; int i; @@ -617,9 +663,26 @@ struct libterminput_marshaller { }; -/* TODO doc */ +/** + * User provided function and associated binary + * data used to load the state + * + * @since 1.1 (applies to all members unless stated otherwise) + */ struct libterminput_unmarshaller { + /** + * Callback function to load data + * + * @param this Pointer to the object containing this function + * @param data Output buffer for the data + * @param size The number of bytes to load into `data` + * @return 0 on success, -1 on failure + */ int (*load)(struct libterminput_unmarshaller *this, void *data, size_t size); + + /** + * User-defined data + */ union { void *ptr; int i; @@ -637,6 +700,8 @@ struct libterminput_unmarshaller { * @return 1 normally, 0 on end of input, -1 on error * * @throws Any reason specified for read(3) + * + * @since 1.0 */ int libterminput_read(int fd, union libterminput_input *input, struct libterminput_state *ctx); @@ -657,6 +722,8 @@ int libterminput_read(int fd, union libterminput_input *input, struct libterminp * @param input Input gathered by `libterminput_read` * @param ctx State for the terminal * @return 1 if there there is more input available, 0 otherwise + * + * @since 1.0 */ inline int libterminput_is_ready(const union libterminput_input *input, const struct libterminput_state *ctx) @@ -676,6 +743,8 @@ libterminput_is_ready(const union libterminput_input *input, const struct libter * @return 0 on success, -1 on failure * * The current version of this function cannot fail + * + * @since 1.0 */ int libterminput_set_flags(struct libterminput_state *ctx, enum libterminput_flags flags); @@ -687,13 +756,68 @@ int libterminput_set_flags(struct libterminput_state *ctx, enum libterminput_fla * @return 0 on success, -1 on failure * * The current version of this function cannot fail + * + * @since 1.0 */ int libterminput_clear_flags(struct libterminput_state *ctx, enum libterminput_flags flags); -/* TODO doc, man */ +/** + * Marshal the parsed input + * + * @param how Object used to store the serialisation + * @param what The input to marshal + * @return 0 on success, -1 on failure + * + * This function will fail for any reason `*how->store` fails + * + * @since 1.1 + */ int libterminput_marshal_input(struct libterminput_marshaller *how, const union libterminput_input *what); + +/** + * Marshal the input parsing state + * + * It's important to also use `libterminput_marshal_input` + * as it may contain part of the state + * + * @param how Object used to store the serialisation + * @param what The state to marshal + * @return 0 on success, -1 on failure + * + * This function will fail for any reason `*how->store` fails + * + * @since 1.1 + */ int libterminput_marshal_state(struct libterminput_marshaller *how, const struct libterminput_state *what); + +/** + * Unmarshal the parsed input + * + * @param how Object used to load the serialisation + * @param what Output parameter for the unmarshalled input + * @return 0 on success, -1 on failure + * + * @throws EINVAL Invalid serialisation + * + * This function will also fail for any reason `*how->load` fails + * + * @since 1.1 + */ int libterminput_unmarshal_input(struct libterminput_unmarshaller *how, union libterminput_input *what); + +/** + * Unmarshal the input parsing state + * + * @param how Object used to load the serialisation + * @param what Output parameter for the unmarshalled state + * @return 0 on success, -1 on failure + * + * @throws EINVAL Invalid serialisation + * + * This function will also fail for any reason `*how->load` fails + * + * @since 1.1 + */ int libterminput_unmarshal_state(struct libterminput_unmarshaller *how, struct libterminput_state *what); diff --git a/libterminput_marshal_input.3 b/libterminput_marshal_input.3 new file mode 120000 index 0000000..0656462 --- /dev/null +++ b/libterminput_marshal_input.3 @@ -0,0 +1 @@ +libterminput_marshal_state.3
\ No newline at end of file diff --git a/libterminput_marshal_keypress__.c b/libterminput_marshal_keypress__.c index 1ffba01..8924b4f 100644 --- a/libterminput_marshal_keypress__.c +++ b/libterminput_marshal_keypress__.c @@ -3,7 +3,7 @@ int -libterminput_marshal_keypress__(struct libterminput_marshaller *how, const struct libterminput_keypress *what) +libterminput_marshal_keypress__(struct libterminput_marshaller *how, const struct libterminput_keypress *what) /* TODO test */ { if (how->store(how, &what->key, sizeof(what->key)) || how->store(how, &what->times, sizeof(what->times)) || diff --git a/libterminput_marshal_mouseevent__.c b/libterminput_marshal_mouseevent__.c index 8fe64c7..7da80fe 100644 --- a/libterminput_marshal_mouseevent__.c +++ b/libterminput_marshal_mouseevent__.c @@ -3,7 +3,7 @@ int -libterminput_marshal_mouseevent__(struct libterminput_marshaller *how, const struct libterminput_mouseevent *what) +libterminput_marshal_mouseevent__(struct libterminput_marshaller *how, const struct libterminput_mouseevent *what) /* TODO test */ { if (how->store(how, &what->event, sizeof(what->event)) || how->store(how, &what->x, sizeof(size_t) * 2U)) diff --git a/libterminput_marshal_state.3 b/libterminput_marshal_state.3 new file mode 100644 index 0000000..26f7a49 --- /dev/null +++ b/libterminput_marshal_state.3 @@ -0,0 +1,121 @@ +.TH LIBTERMINPUT_MARSHAL_STATE 3 LIBTERMINPUT +.SH NAME +libterminput_marshal_state \- Marshal the input parsing state +.br +libterminput_marshal_input \- Marshal the parsed input + +.SH SYNOPSIS +.nf +#include <libterminput.h> + +struct libterminput_marshaller { + int (*store)(struct libterminput_marshaller *\fIthis\fP, const void *\fIdata\fP, size_t \fIsize\fP); + union { + void *ptr; + int i; + size_t zu; + } user; +}; + +int libterminput_marshal_state(struct libterminput_marshaller *\fIhow\fP, const struct libterminput_state *\fIwhat\fP); +int libterminput_marshal_input(struct libterminput_marshaller *\fIhow\fP, const union libterminput_input *\fIwhat\fP); +.fi +.PP +Link with +.IR \-lterminput . + +.SH DESCRIPTION +The +.BR libterminput_marshal_state () +and +.BR libterminput_marshal_input () +function marshals the contents of +.I what +using +.IR *how->store . +.PP +It's important to also use the +.BR libterminput_marshal_input () +function in addition to the +.BR libterminput_marshal_state () +function as part of the state may be stored in the +.IR "union libterminput_input" . +.PP +.I *how->store +must return 0 on success and -1 on failure, and may set +.I errno +to indicate the error. +.I how +is fed back into +.I *how->store +(as +.IR this ) +so that the +.I *how->store +function can use and modify +.I how->user +which contains application-defined data +(typically a buffer, a file descriptor, or +the size of the serialisation). +.I data +will be set to the binary data to store, and +.I size +will be set to the number of bytes from +.I data +to store. + +.SH RETURN VALUE +The +.BR libterminput_marshal_state () +and +.BR libterminput_marshal_input () +functions return 0 upon successful completion. +On failure, +.B -1 +is returnes, but +.I errno +remains unmodified, however any changes to +.I errno +by +.I *how->store +will remain. + +.SH ERRORS +The +.BR libterminput_marshal_state () +and +.BR libterminput_marshal_input () +functions fail, without further modifying +.IR errno , +if +.I *how->store +fails. + +.SH EXAMPLES +None. + +.SH APPLICATION USAGE +None. + +.SH RATIONALE +None. + +.SH FUTURE DIRECTIONS +None. + +.SH HISTORY +The +.BR libterminput_marshal_state () +and +.BR libterminput_marshal_input () +functions were added in version 1.1 of libterminput. + +.SH NOTES +None. + +.SH BUGS +None. + +.SH SEE ALSO +.BR libterminput_unmarshal_state (3), +.BR libterminput_read (3) diff --git a/libterminput_marshal_text__.c b/libterminput_marshal_text__.c index fa9b542..264ec04 100644 --- a/libterminput_marshal_text__.c +++ b/libterminput_marshal_text__.c @@ -3,10 +3,10 @@ int -libterminput_marshal_text__(struct libterminput_marshaller *how, const struct libterminput_text *what) +libterminput_marshal_text__(struct libterminput_marshaller *how, const struct libterminput_text *what) /* TODO test */ { if (how->store(how, &what->nbytes, sizeof(what->nbytes)) || - how->store(how, what->bytes, sizeof(what->nbytes))) + how->store(how, what->bytes, what->nbytes)) return -1; return 0; } diff --git a/libterminput_read.3 b/libterminput_read.3 index deabd63..742c95a 100644 --- a/libterminput_read.3 +++ b/libterminput_read.3 @@ -426,6 +426,7 @@ therefore the flag must be set with the .BR libterminput_set_flags (3) function. + .SH RETURN VALUE The .BR libterminput_read () @@ -467,4 +468,5 @@ None. .SH SEE ALSO .BR libterminput_is_ready (3), -.BR libterminput_set_flags (3) +.BR libterminput_set_flags (3), +.BR libterminput_marshal_state (3) diff --git a/libterminput_set_flags.3 b/libterminput_set_flags.3 index b55c231..30301bc 100644 --- a/libterminput_set_flags.3 +++ b/libterminput_set_flags.3 @@ -138,6 +138,10 @@ None. .SH FUTURE DIRECTIONS None. +.SH HISTORY +.B LIBTERMINPUT_MACRO_ON_BLOCK +was added in version 1.1 of libterminput. + .SH NOTES None. diff --git a/libterminput_unmarshal_input.3 b/libterminput_unmarshal_input.3 new file mode 120000 index 0000000..2490adb --- /dev/null +++ b/libterminput_unmarshal_input.3 @@ -0,0 +1 @@ +libterminput_unmarshal_state.3
\ No newline at end of file diff --git a/libterminput_unmarshal_input.c b/libterminput_unmarshal_input.c index ef8606c..851d0be 100644 --- a/libterminput_unmarshal_input.c +++ b/libterminput_unmarshal_input.c @@ -15,16 +15,30 @@ libterminput_unmarshal_input(struct libterminput_unmarshaller *how, union libter if (how->load(how, &what->type, sizeof(what->type))) return -1; } - if (what->type == LIBTERMINPUT_KEYPRESS) + switch ((int)what->type) { + case LIBTERMINPUT_KEYPRESS: r = libterminput_unmarshal_keypress__(how, &what->keypress); - else if (what->type == LIBTERMINPUT_TEXT) + break; + case LIBTERMINPUT_TEXT: r = libterminput_unmarshal_text__(how, &what->text); - else if (what->type == LIBTERMINPUT_MOUSEEVENT) + break; + case LIBTERMINPUT_MOUSEEVENT: r = libterminput_unmarshal_mouseevent__(how, &what->mouseevent); - else if (what->type == LIBTERMINPUT_CURSOR_POSITION) + break; + case LIBTERMINPUT_CURSOR_POSITION: r = libterminput_unmarshal_position__(how, &what->position); - else + break; + case LIBTERMINPUT_NONE: + case LIBTERMINPUT_BRACKETED_PASTE_START: + case LIBTERMINPUT_BRACKETED_PASTE_END: + case LIBTERMINPUT_TERMINAL_IS_OK: + case LIBTERMINPUT_TERMINAL_IS_NOT_OK: r = 0; + break; + default: + errno = EINVAL; + return -1; + } what->type = type; return r; } diff --git a/libterminput_unmarshal_keypress__.c b/libterminput_unmarshal_keypress__.c index 68a622d..f4b4fc6 100644 --- a/libterminput_unmarshal_keypress__.c +++ b/libterminput_unmarshal_keypress__.c @@ -3,13 +3,17 @@ int -libterminput_unmarshal_keypress__(struct libterminput_unmarshaller *how, struct libterminput_keypress *what) +libterminput_unmarshal_keypress__(struct libterminput_unmarshaller *how, struct libterminput_keypress *what) /* TODO test */ { what->type = LIBTERMINPUT_KEYPRESS; if (how->load(how, &what->key, sizeof(what->key)) || how->load(how, &what->times, sizeof(what->times)) || how->load(how, &what->mods, sizeof(what->mods))) return -1; + if ((uintmax_t)what->key > (uintmax_t)LIBTERMINPUT_KEYPAD__LAST__) { + errno = EINVAL; + return -1; + } if (what->key == LIBTERMINPUT_SYMBOL) { return how->load(how, what->symbol, sizeof(what->symbol)); } else { diff --git a/libterminput_unmarshal_mouseevent__.c b/libterminput_unmarshal_mouseevent__.c index 55f72ea..f91b606 100644 --- a/libterminput_unmarshal_mouseevent__.c +++ b/libterminput_unmarshal_mouseevent__.c @@ -3,7 +3,7 @@ int -libterminput_unmarshal_mouseevent__(struct libterminput_unmarshaller *how, struct libterminput_mouseevent *what) +libterminput_unmarshal_mouseevent__(struct libterminput_unmarshaller *how, struct libterminput_mouseevent *what) /* TODO test */ { what->type = LIBTERMINPUT_MOUSEEVENT; if (how->load(how, &what->event, sizeof(what->event)) || @@ -11,13 +11,20 @@ libterminput_unmarshal_mouseevent__(struct libterminput_unmarshaller *how, struc return -1; what->mods = 0; what->button = LIBTERMINPUT_BUTTON1; - if (what->event == LIBTERMINPUT_HIGHLIGHT_OUTSIDE) { - if (how->load(how, &what->start_x, sizeof(size_t) * 4U)) - return -1; - } else if (what->event != LIBTERMINPUT_HIGHLIGHT_INSIDE) { + switch ((int)what->event) { + case LIBTERMINPUT_PRESS: + case LIBTERMINPUT_RELEASE: + case LIBTERMINPUT_MOTION: if (how->load(how, &what->mods, sizeof(what->mods)) || how->load(how, &what->button, sizeof(what->button))) return -1; + /* fall through */ + case LIBTERMINPUT_HIGHLIGHT_INSIDE: + return 0; + case LIBTERMINPUT_HIGHLIGHT_OUTSIDE: + return how->load(how, &what->start_x, sizeof(size_t) * 4U); + default: + errno = EINVAL; + return -1; } - return 0; } diff --git a/libterminput_unmarshal_position__.c b/libterminput_unmarshal_position__.c index 9040c50..093c0b1 100644 --- a/libterminput_unmarshal_position__.c +++ b/libterminput_unmarshal_position__.c @@ -3,7 +3,7 @@ int -libterminput_unmarshal_position__(struct libterminput_unmarshaller *how, struct libterminput_position *what) +libterminput_unmarshal_position__(struct libterminput_unmarshaller *how, struct libterminput_position *what) /* TODO test */ { what->type = LIBTERMINPUT_CURSOR_POSITION; return how->load(how, &what->x, sizeof(size_t) * 2U); diff --git a/libterminput_unmarshal_state.3 b/libterminput_unmarshal_state.3 new file mode 100644 index 0000000..dd498fa --- /dev/null +++ b/libterminput_unmarshal_state.3 @@ -0,0 +1,122 @@ +.TH LIBTERMINPUT_UNMARSHAL_STATE 3 LIBTERMINPUT +.SH NAME +libterminput_unmarshal_state \- Unmarshal the input parsing state +.br +libterminput_unmarshal_input \- Unmarshal the parsed input + +.SH SYNOPSIS +.nf +#include <libterminput.h> + +struct libterminput_unmarshaller { + int (*load)(struct libterminput_unmarshaller *\fIthis\fP, void *\fIdata\fP, size_t \fIsize\fP); + union { + void *ptr; + int i; + size_t zu; + } user; +}; + +int libterminput_unmarshal_state(struct libterminput_unmarshaller *\fIhow\fP, struct libterminput_state *\fIwhat\fP); +int libterminput_unmarshal_input(struct libterminput_unmarshaller *\fIhow\fP, union libterminput_input *\fIwhat\fP); +.fi +.PP +Link with +.IR \-lterminput . + +.SH DESCRIPTION +The +.BR libterminput_unmarshal_state () +and +.BR libterminput_unmarshal_input () +function unmarshals state into +.I *what +using +.IR *how->load . +.PP +.I *how->load +must return 0 on success and -1 on failure, and may set +.I errno +to indicate the error. +.I how +is fed back into +.I *how->load +(as +.IR this ) +so that the +.I *how->load +function can use and modify +.I how->user +which contains application-defined data +(typically a buffer, a file descriptor, or +the size of the serialisation). +.I data +will be set to the output buffer for the data +read by +.I *how-load +and +.I size +will be set to the number of bytes to read +into from +.IR data . + +.SH RETURN VALUE +The +.BR libterminput_unmarshal_state () +and +.BR libterminput_unmarshal_input () +functions return 0 upon successful completion. +On failure, +.B -1 +is returnes, but +.I errno +remains unmodified, however any changes to +.I errno +by +.I *how->load +will remain. + +.SH ERRORS +The +.BR libterminput_unmarshal_state () +and +.BR libterminput_unmarshal_input () +functions fail, without further modifying +.IR errno , +if +.I *how->load +fails. The functions will also fail if: +.TP +.B EINVAL +The read serialisation was invalid for the used +version of the library (not a proper serialisation +or containing data from a newer version of the +library). + +.SH EXAMPLES +None. + +.SH APPLICATION USAGE +None. + +.SH RATIONALE +None. + +.SH FUTURE DIRECTIONS +None. + +.SH HISTORY +The +.BR libterminput_unmarshal_state () +and +.BR libterminput_unmarshal_input () +functions were added in version 1.1 of libterminput. + +.SH NOTES +None. + +.SH BUGS +None. + +.SH SEE ALSO +.BR libterminput_marshal_state (3) diff --git a/libterminput_unmarshal_state.c b/libterminput_unmarshal_state.c index fd1d6db..a41c4fe 100644 --- a/libterminput_unmarshal_state.c +++ b/libterminput_unmarshal_state.c @@ -5,5 +5,30 @@ int libterminput_unmarshal_state(struct libterminput_unmarshaller *how, struct libterminput_state *what) /* TODO test */ { - return how->load(how, what, sizeof(*what)); + if (how->load(how, what, sizeof(*what))) + return -1; + if (what->inited < 0 || what->inited > 1 || + what->bracketed_paste > 1U || + what->meta > 2U || + what->n >= sizeof(what->partial) || + what->npartial >= sizeof(what->partial) || + what->stored_tail > what->stored_head || + what->stored_head > sizeof(what->stored) || + what->unused_bits) + goto einval; + switch (what->mouse_tracking) { + case 0: + case 1: + case 2: + case 3: + case 6: + break; + default: + goto einval; + } + return 0; + +einval: + errno = EINVAL; + return -1; } diff --git a/libterminput_unmarshal_text__.c b/libterminput_unmarshal_text__.c index 4843db4..bb25fe4 100644 --- a/libterminput_unmarshal_text__.c +++ b/libterminput_unmarshal_text__.c @@ -3,11 +3,14 @@ int -libterminput_unmarshal_text__(struct libterminput_unmarshaller *how, struct libterminput_text *what) +libterminput_unmarshal_text__(struct libterminput_unmarshaller *how, struct libterminput_text *what) /* TODO test */ { what->type = LIBTERMINPUT_TEXT; - if (how->load(how, &what->nbytes, sizeof(what->nbytes)) || - how->load(how, what->bytes, sizeof(what->nbytes))) + if (how->load(how, &what->nbytes, sizeof(what->nbytes))) return -1; - return 0; + if (what->nbytes > sizeof(what->bytes)) { + errno = EINVAL; + return -1; + } + return how->load(how, what->bytes, what->nbytes); } |