diff options
Diffstat (limited to 'include/linux')
| -rw-r--r-- | include/linux/seq_buf.h | 67 |
1 files changed, 61 insertions, 6 deletions
diff --git a/include/linux/seq_buf.h b/include/linux/seq_buf.h index 0c0a0db04b09..7abeca1c166b 100644 --- a/include/linux/seq_buf.h +++ b/include/linux/seq_buf.h @@ -89,6 +89,27 @@ static inline unsigned int seq_buf_used(struct seq_buf *s) return min(s->len, s->size); } +/* + * NUL-terminate the buffer in @s: directly after the data when there is + * room for it, otherwise in the last byte of the buffer. @s->size must not + * be zero. + * + * Returns: the offset of the NUL. + */ +static inline size_t __seq_buf_terminate(struct seq_buf *s) +{ + size_t end; + + if (seq_buf_buffer_left(s)) + end = s->len; + else + end = s->size - 1; + + s->buffer[end] = 0; + + return end; +} + /** * seq_buf_str - get NUL-terminated C string from seq_buf * @s: the seq_buf handle @@ -98,7 +119,14 @@ static inline unsigned int seq_buf_used(struct seq_buf *s) * * Note, if this is called when the buffer has overflowed, then * the last byte of the buffer is zeroed, and the len will still - * point passed it. + * point passed it. The same happens when the buffer is exactly + * full: the NUL takes the place of the last byte written, which is + * lost, though seq_buf_used() still counts it. + * + * A zero-sized seq_buf has nowhere to put a NUL, so the empty string + * is returned instead of writing to @s->buffer. Any other seq_buf + * returns @s->buffer, even when it holds an empty string, so callers + * always get their own buffer back. * * After this function is called, s->buffer is safe to use * in string operations. @@ -107,18 +135,45 @@ static inline unsigned int seq_buf_used(struct seq_buf *s) */ static inline const char *seq_buf_str(struct seq_buf *s) { - if (WARN_ON(s->size == 0)) + if (s->size == 0) return ""; - if (seq_buf_buffer_left(s)) - s->buffer[s->len] = 0; - else - s->buffer[s->size - 1] = 0; + __seq_buf_terminate(s); return s->buffer; } /** + * seq_buf_strlen - get the length of the NUL-terminated C string in seq_buf + * @s: the seq_buf handle + * + * This makes sure that the buffer in @s is NUL-terminated, exactly as + * seq_buf_str() does, and returns the length of the resulting string + * without walking it. Unlike seq_buf_used(), this does not count the byte + * given up to the NUL when the buffer is full or has overflowed. When the + * buffer is exactly full, that byte is the last one written, and calling + * either function loses it. + * + * A zero-sized seq_buf holds no string, so 0 is returned without writing + * to @s->buffer, matching what seq_buf_str() returns for one. + * + * After this function is called, s->buffer is safe to use + * in string operations. + * + * Returns: the offset of the NUL that terminates @s->buffer. That is the + * length of the string unless an earlier NUL is in the way, either one the + * data written to @s carried itself, or one seq_buf_set_overflow() left + * behind when it cleared what no writer had claimed. + */ +static inline size_t seq_buf_strlen(struct seq_buf *s) +{ + if (s->size == 0) + return 0; + + return __seq_buf_terminate(s); +} + +/** * seq_buf_get_buf - get buffer to write arbitrary data to * @s: the seq_buf handle * @bufp: the beginning of the buffer is stored here |
