/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */1/* include/k5-buf.h - k5buf interface declarations */2/*3* Copyright 2008 Massachusetts Institute of Technology.4* All Rights Reserved.5*6* Export of this software from the United States of America may7* require a specific license from the United States Government.8* It is the responsibility of any person or organization contemplating9* export to obtain such a license before exporting.10*11* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and12* distribute this software and its documentation for any purpose and13* without fee is hereby granted, provided that the above copyright14* notice appear in all copies and that both that copyright notice and15* this permission notice appear in supporting documentation, and that16* the name of M.I.T. not be used in advertising or publicity pertaining17* to distribution of the software without specific, written prior18* permission. Furthermore if you modify this software you must label19* your software as modified software and not distribute it in such a20* fashion that it might be confused with the original M.I.T. software.21* M.I.T. makes no representations about the suitability of22* this software for any purpose. It is provided "as is" without express23* or implied warranty.24*/2526#ifndef K5_BUF_H27#define K5_BUF_H2829#include <stdarg.h>30#include <string.h>3132/*33* The k5buf module is intended to allow multi-step string construction in a34* fixed or dynamic buffer without the need to check for a failure at each step35* (and without aborting on malloc failure). If an allocation failure occurs36* or the fixed buffer runs out of room, the buffer will be set to an error37* state which can be detected with k5_buf_status. Data in a buffer is not38* automatically terminated with a zero byte; call k5_buf_cstring() to use the39* contents as a C string.40*41* k5buf structures are usually stack-allocated. Do not put k5buf structure42* pointers into public APIs. It is okay to reference the data and len fields43* of a buffer (they will be NULL/0 if the buffer is in an error state), but do44* not change them.45*/4647/* Buffer type values */48enum k5buftype { K5BUF_ERROR, K5BUF_FIXED, K5BUF_DYNAMIC, K5BUF_DYNAMIC_ZAP };4950struct k5buf {51enum k5buftype buftype;52void *data;53size_t space;54size_t len;55};5657#define EMPTY_K5BUF { K5BUF_ERROR }5859/* Initialize a k5buf using a fixed-sized, existing buffer. SPACE must be60* more than zero, or an assertion failure will result. */61void k5_buf_init_fixed(struct k5buf *buf, void *data, size_t space);6263/* Initialize a k5buf using an internally allocated dynamic buffer. */64void k5_buf_init_dynamic(struct k5buf *buf);6566/* Initialize a k5buf using an internally allocated dynamic buffer, zeroing67* memory when reallocating or freeing. */68void k5_buf_init_dynamic_zap(struct k5buf *buf);6970/* Add a C string to BUF. */71void k5_buf_add(struct k5buf *buf, const char *data);7273/* Add a counted series of bytes to BUF. */74void k5_buf_add_len(struct k5buf *buf, const void *data, size_t len);7576/* Add sprintf-style formatted data to BUF. For a fixed-length buffer this77* operation will fail if there isn't room for a zero terminator. */78void k5_buf_add_fmt(struct k5buf *buf, const char *fmt, ...)79#if !defined(__cplusplus) && (__GNUC__ > 2)80__attribute__((__format__(__printf__, 2, 3)))81#endif82;8384/* Add sprintf-style formatted data to BUF, with a va_list. The value of ap is85* undefined after the call. */86void k5_buf_add_vfmt(struct k5buf *buf, const char *fmt, va_list ap)87#if !defined(__cplusplus) && (__GNUC__ > 2)88__attribute__((__format__(__printf__, 2, 0)))89#endif90;9192/* Without changing the length of buf, ensure that there is a zero byte after93* buf.data and return it. Return NULL on error. */94char *k5_buf_cstring(struct k5buf *buf);9596/* Extend the length of buf by len and return a pointer to the reserved space,97* to be filled in by the caller. Return NULL on error. */98void *k5_buf_get_space(struct k5buf *buf, size_t len);99100/* Truncate BUF. LEN must be between 0 and the existing buffer101* length, or an assertion failure will result. */102void k5_buf_truncate(struct k5buf *buf, size_t len);103104/* Return ENOMEM if buf is in an error state, 0 otherwise. */105int k5_buf_status(struct k5buf *buf);106107/*108* Free the storage used in the dynamic buffer BUF. The caller may choose to109* take responsibility for freeing the data pointer instead of using this110* function. If BUF is a fixed buffer, an assertion failure will result.111* Freeing a buffer in the error state, a buffer initialized with EMPTY_K5BUF,112* or a zeroed k5buf structure is a no-op.113*/114void k5_buf_free(struct k5buf *buf);115116static inline void117k5_buf_add_byte(struct k5buf *buf, uint8_t val)118{119k5_buf_add_len(buf, &val, 1);120}121122static inline void123k5_buf_add_uint16_be(struct k5buf *buf, uint16_t val)124{125void *p = k5_buf_get_space(buf, 2);126127if (p != NULL)128store_16_be(val, p);129}130131static inline void132k5_buf_add_uint16_le(struct k5buf *buf, uint16_t val)133{134void *p = k5_buf_get_space(buf, 2);135136if (p != NULL)137store_16_le(val, p);138}139140static inline void141k5_buf_add_uint32_be(struct k5buf *buf, uint32_t val)142{143void *p = k5_buf_get_space(buf, 4);144145if (p != NULL)146store_32_be(val, p);147}148149static inline void150k5_buf_add_uint32_le(struct k5buf *buf, uint32_t val)151{152void *p = k5_buf_get_space(buf, 4);153154if (p != NULL)155store_32_le(val, p);156}157158static inline void159k5_buf_add_uint64_be(struct k5buf *buf, uint64_t val)160{161void *p = k5_buf_get_space(buf, 8);162163if (p != NULL)164store_64_be(val, p);165}166167static inline void168k5_buf_add_uint64_le(struct k5buf *buf, uint64_t val)169{170void *p = k5_buf_get_space(buf, 8);171172if (p != NULL)173store_64_le(val, p);174}175176#endif /* K5_BUF_H */177178179