blob: 10a5106b795acdfb295c834e504538bf09a0c31c [file] [log] [blame]
/*
* Copyright IBM Corporation, 2012
* Contributor: Frank Filz <ffilz@us.ibm.com>
*
* --------------------------
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 3 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*
*/
/**
* @defgroup Display display_buffer implementation
* @{
*/
/**
* @file display.h
* @author Frank Filz <ffilz@us.ibm.com>
* @brief Implementation of a buffer for constructing string messages.
*
* This file provides a buffer descriptor for string messages that
* contains a current position as well as the buffer pointer and size.
* A variety of functions are provided to manipulate the buffer and
* append various strings to the buffer.
*/
#ifndef _DISPLAY_H
#define _DISPLAY_H
#include <stdio.h>
#include <string.h>
/**
* @page Display Safe display buffers
*
* A struct display_buffer describes a string buffer and the current position
* within it so that a string can be built of various components. This is
* especially useful for nested display functions for data types, where
* the top level display function may call display functions for sub-data types.
*
* While building a complex string, users SHOULD check the return value from
* each display function and exit if it is <= 0, however, continuing to call
* display functions will be totally safe.
*
* The only things that MUST be done if building a new display primitive is
* to call display_start at the beginning and display_finish at the end. A
* display primitive is a function that uses a non-display function (such as
* strcat, memcpy, sprintf) to copy bytes into the buffer. Such primitives must
* assure that any such routines do not overflow the buffer, and then the
* primitive must manage the b_current. display_finish will handle proper
* indication of a full buffer or buffer overflow.
*
* The core routines:
*
* display_start validate and prepare to start appending to the buffer.
* display_finish wrap up after appending to the buffer.
* display_reset_buffer reset a buffer for re-use to build a new string.
* display_printf append to the string using printf formatting
* display_opaque_value format an opaque value into the buffer
* display_cat append a simple string to the buffer
*
* There are variants of these functions.
*/
/**
* @brief Descriptor for display buffers.
*
* This structure defines a display buffer.
* Buffer may be allocated global, on the stack, or by malloc.
*/
struct display_buffer {
size_t b_size; /*< Size of the buffer, will hold b_size
- 1 chars plus a '\0' */
char *b_current; /*< Current position in the buffer, where the
next string will be appended */
char *b_start; /*< Start of the buffer */
};
int display_buffer_remain(struct display_buffer *dspbuf);
int display_start(struct display_buffer *dspbuf);
int display_finish(struct display_buffer *dspbuf);
int display_force_overflow(struct display_buffer *dspbuf);
/**
* @brief Reset current position in buffer to start.
*
* @param[in,out] dspbuf The buffer.
*
*/
static inline void display_reset_buffer(struct display_buffer *dspbuf)
{
/* To re-use a buffer, all we need to do is roll b_current back to
* b_start.
*/
dspbuf->b_current = dspbuf->b_start;
}
/**
* @brief Compute the string length of the buffer.
*
* @param[in] dspbuf The buffer to finish up.
*
* @return the length.
*
* This function is more efficient than strlen if the buffer hasn't overflowed.
*
*/
static inline size_t display_buffer_len(struct display_buffer *dspbuf)
{
size_t len = dspbuf->b_current - dspbuf->b_start;
if (len == dspbuf->b_size) {
/* Buffer has overflowed, due to forced overflow or partial
* UTF-8 fixup, the actual string length might actually be less
* than the full length of the buffer. Just use strlen.
*/
return strlen(dspbuf->b_start);
} else {
return len;
}
}
int display_vprintf(struct display_buffer *dspbuf, const char *fmt,
va_list args);
/**
* @brief Format a string into the buffer.
*
* @param[in,out] dspbuf The buffer.
* @param[in] fmt the format string
* @param[in] ... the args
*
* @return the bytes remaining in the buffer.
*
*/
static inline int display_printf(struct display_buffer *dspbuf, const char *fmt,
...)
{
va_list args;
int b_left;
va_start(args, fmt);
b_left = display_vprintf(dspbuf, fmt, args);
va_end(args);
return b_left;
}
int display_opaque_bytes(struct display_buffer *dspbuf, void *value, int len);
int display_opaque_value_max(struct display_buffer *dspbuf, void *value,
int len, int max);
/**
* @brief Display a number of opaque bytes as a hex string.
*
* @param[in,out] dspbuf The buffer.
* @param[in] value The bytes to display
* @param[in] len The number of bytes in the opaque value
*
* @return the bytes remaining in the buffer.
*
* This routine just calls display_opaque_value_max with max = len.
*
*/
static inline int display_opaque_value(struct display_buffer *dspbuf,
void *value, int len)
{
return display_opaque_value_max(dspbuf, value, len, len);
}
int display_len_cat(struct display_buffer *dspbuf, char *str, int len);
/**
* @brief Append a null delimited string to the buffer.
*
* @param[in,out] dspbuf The buffer.
* @param[in] str The string
*
* @return the bytes remaining in the buffer.
*
*/
static inline int display_cat(struct display_buffer *dspbuf, char *str)
{
return display_len_cat(dspbuf, str, strlen(str));
}
int display_cat_trunc(struct display_buffer *dspbuf, char *str, size_t max);
/** @} */
#endif /* _DISPLAY_H */