/*
This file is part of GNUnet.
Copyright (C) 2009 GNUnet e.V.
GNUnet is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License,
or (at your option) any later version.
GNUnet 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
Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
SPDX-License-Identifier: AGPL3.0-or-later
*/
/**
* @addtogroup libgnunetutil
* Multi-function utilities library for GNUnet programs
* @{
*
* @author Christian Grothoff
*
* @file
* Buffered IO library
*
* @defgroup bio BIO library
* Buffered binary disk IO (with endianness conversion)
* @{
*/
#if !defined (__GNUNET_UTIL_LIB_H_INSIDE__)
#error "Only can be included directly."
#endif
#ifndef GNUNET_BIO_LIB_H
#define GNUNET_BIO_LIB_H
#include "gnunet_container_lib.h"
#ifdef __cplusplus
extern "C"
{
#if 0 /* keep Emacsens' auto-indent happy */
}
#endif
#endif
/****************************** READING API *******************************/
/**
* Handle for buffered reading.
*/
struct GNUNET_BIO_ReadHandle;
/**
* Open a file for reading.
*
* @param fn file name to be opened
* @return IO handle on success, NULL on error
*/
struct GNUNET_BIO_ReadHandle *
GNUNET_BIO_read_open_file (const char *fn);
/**
* Create a handle from an existing allocated buffer.
*
* @param buffer the buffer to use as source
* @param size the total size in bytes of the buffer
* @return IO handle on success, NULL on error
*/
struct GNUNET_BIO_ReadHandle *
GNUNET_BIO_read_open_buffer (void *buffer, size_t size);
/**
* Close an open handle. Reports if any errors reading
* from the file were encountered.
*
* @param h file handle
* @param emsg set to the error message
* @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
*/
int
GNUNET_BIO_read_close (struct GNUNET_BIO_ReadHandle *h, char **emsg);
/**
* Set read error to handle
*
* @param h the handle
* @param emsg the message
*/
void
GNUNET_BIO_read_set_error (struct GNUNET_BIO_ReadHandle *h, const char* emsg);
/**
* Read some contents into a buffer.
*
* @param h the IO handle to read from
* @param what describes what is being read (for error message creation)
* @param result the buffer to write the result to
* @param len the number of bytes to read
* @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
*/
int
GNUNET_BIO_read (struct GNUNET_BIO_ReadHandle *h,
const char *what,
void *result,
size_t len);
/**
* Read 0-terminated string.
*
* @param h the IO handle to read from
* @param what describes what is being read (for error message creation)
* @param result where to store the pointer to the (allocated) string
* (note that *result could be set to NULL as well)
* @param max_length maximum allowed length for the string
* @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
*/
int
GNUNET_BIO_read_string (struct GNUNET_BIO_ReadHandle *h,
const char *what,
char **result,
size_t max_length);
/**
* Read a float.
*
* @param h the IO handle to read from
* @param what describes what is being read (for error message creation)
* @param f address of float to read
*/
int
GNUNET_BIO_read_float (struct GNUNET_BIO_ReadHandle *h,
const char *what,
float *f);
/**
* Read a double.
*
* @param h the IO handle to read from
* @param what describes what is being read (for error message creation)
* @param f address of double to read
*/
int
GNUNET_BIO_read_double (struct GNUNET_BIO_ReadHandle *h,
const char *what,
double *f);
/**
* Read an (u)int32_t.
*
* @param h the IO handle to read from
* @param what describes what is being read (for error message creation)
* @param i where to store the data
* @return #GNUNET_OK on success, #GNUNET_SYSERR on error
*/
int
GNUNET_BIO_read_int32 (struct GNUNET_BIO_ReadHandle *h,
const char *what,
int32_t *i);
/**
* Read an (u)int64_t.
*
* @param h the IO handle to read from
* @param what describes what is being read (for error message creation)
* @param i where to store the data
* @return #GNUNET_OK on success, #GNUNET_SYSERR on error
*/
int
GNUNET_BIO_read_int64 (struct GNUNET_BIO_ReadHandle *h,
const char *what,
int64_t *i);
/****************************** WRITING API *******************************/
/**
* Handle for buffered writing.
*/
struct GNUNET_BIO_WriteHandle;
/**
* Open a file for writing.
*
* @param fn name of the file to be opened
* @return IO handle on success, NULL on error
*/
struct GNUNET_BIO_WriteHandle *
GNUNET_BIO_write_open_file (const char *fn);
/**
* Create a handle backed by an in-memory buffer.
*
* @return IO handle on success, NULL on error
*/
struct GNUNET_BIO_WriteHandle *
GNUNET_BIO_write_open_buffer (void);
/**
* Force a file-based buffered writer to flush its buffer.
* If the handle does not use a file, this function returns #GNUNET_OK
* without doing anything.
*
* @param h the IO handle
* @return #GNUNET_OK upon success. Upon failure #GNUNET_SYSERR is returned
* and the file is closed
*/
int
GNUNET_BIO_flush (struct GNUNET_BIO_WriteHandle *h);
/**
* Get the IO handle's contents.
* If the handle doesn't use an in-memory buffer, this function returns
* #GNUNET_SYSERR.
*
* @param h the IO handle
* @param emsg set to the (allocated) error message
* if the handle has an error message the return value is #GNUNET_SYSERR
* @param contents where to store the pointer to the handle's contents
* @param size where to store the size of @e contents
* @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
*/
int
GNUNET_BIO_get_buffer_contents (struct GNUNET_BIO_WriteHandle *h,
char **emsg,
void **contents,
size_t *size);
/**
* Close an IO handle.
* If the handle was using a file, the file will be closed.
*
* @param h file handle
* @param emsg set to the (allocated) error message
* if the handle has an error message, the return value is #GNUNET_SYSERR
* @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
*/
int
GNUNET_BIO_write_close (struct GNUNET_BIO_WriteHandle *h, char **emsg);
/**
* Write a buffer to a handle.
*
* @param h the IO handle to write to
* @param what what is being written (for error message creation)
* @param buffer the data to write
* @param n number of bytes to write
* @return #GNUNET_OK on success, #GNUNET_SYSERR on error
*/
int
GNUNET_BIO_write (struct GNUNET_BIO_WriteHandle *h,
const char *what,
const void *buffer,
size_t n);
/**
* Write a 0-terminated string.
*
* @param h the IO handle to write to
* @param what what is being written (for error message creation)
* @param s string to write (can be NULL)
* @return #GNUNET_OK on success, #GNUNET_SYSERR on error
*/
int
GNUNET_BIO_write_string (struct GNUNET_BIO_WriteHandle *h,
const char *what,
const char *s);
/**
* Write a float.
*
* @param h the IO handle to write to
* @param what what is being written (for error message creation)
* @param f float to write (must be a variable)
*/
int
GNUNET_BIO_write_float (struct GNUNET_BIO_WriteHandle *h,
const char *what,
float f);
/**
* Write a double.
*
* @param h the IO handle to write to
* @param what what is being written (for error message creation)
* @param f double to write (must be a variable)
*/
int
GNUNET_BIO_write_double (struct GNUNET_BIO_WriteHandle *h,
const char *what,
double f);
/**
* Write an (u)int32_t.
*
* @param h the IO handle to write to
* @param what what is being written (for error message creation)
* @param i 32-bit integer to write
* @return #GNUNET_OK on success, #GNUNET_SYSERR on error
*/
int
GNUNET_BIO_write_int32 (struct GNUNET_BIO_WriteHandle *h,
const char *what,
int32_t i);
/**
* Write an (u)int64_t.
*
* @param h the IO handle to write to
* @param what what is being written (for error message creation)
* @param i 64-bit integer to write
* @return #GNUNET_OK on success, #GNUNET_SYSERR on error
*/
int
GNUNET_BIO_write_int64 (struct GNUNET_BIO_WriteHandle *h,
const char *what,
int64_t i);
/****************************** READ SPEC API ***************************/
/**
* Function used to deserialize data read from @a h and store it into @a
* target.
*
* @param cls closure (can be NULL)
* @param h the IO handle to read from
* @param what what is being read (for error message creation)
* @param target where to store the data
* @param target_size how many bytes can be written in @a target
* can be 0 if the size is unknown or is not fixed
* @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
*/
typedef int
(*GNUNET_BIO_ReadHandler)(void *cls,
struct GNUNET_BIO_ReadHandle *h,
const char *what,
void *target,
size_t target_size);
/**
* Structure specifying a reading operation on an IO handle.
*/
struct GNUNET_BIO_ReadSpec
{
/**
* Function performing data deserialization.
*/
GNUNET_BIO_ReadHandler rh;
/**
* Closure for @e rh. Can be NULL.
*/
void *cls;
/**
* What is being read (for error message creation)
*/
const char *what;
/**
* Destination buffer. Can also be a pointer to a pointer, especially for
* dynamically allocated structures.
*/
void *target;
/**
* Size of @e target. Can be 0 if unknown or not fixed.
*/
size_t size;
};
/**
* End of specifications marker.
*/
#define GNUNET_BIO_read_spec_end() \
{ NULL, NULL, NULL, NULL, 0 }
/**
* Create the specification to read a certain amount of bytes.
*
* @param what describes what is being read (for error message creation)
* @param result the buffer to write the result to
* @param len the number of bytes to read
* @return the read spec
*/
struct GNUNET_BIO_ReadSpec
GNUNET_BIO_read_spec_object (const char *what,
void *result,
size_t size);
/**
* Create the specification to read a 0-terminated string.
*
* @param what describes what is being read (for error message creation)
* @param result where to store the pointer to the (allocated) string
* (note that *result could be set to NULL as well)
* @param max_length maximum allowed length for the string
* @return the read spec
*/
struct GNUNET_BIO_ReadSpec
GNUNET_BIO_read_spec_string (const char *what,
char **result,
size_t max_length);
/**
* Create the specification to read an (u)int32_t.
*
* @param what describes what is being read (for error message creation)
* @param i where to store the data
* @return the read spec
*/
struct GNUNET_BIO_ReadSpec
GNUNET_BIO_read_spec_int32 (const char *what,
int32_t *i);
/**
* Create the specification to read an (u)int64_t.
*
* @param what describes what is being read (for error message creation)
* @param i where to store the data
* @return the read spec
*/
struct GNUNET_BIO_ReadSpec
GNUNET_BIO_read_spec_int64 (const char *what,
int64_t *i);
/**
* Create the specification to read a float.
*
* @param what describes what is being read (for error message creation)
* @param f address of float to read
*/
struct GNUNET_BIO_ReadSpec
GNUNET_BIO_read_spec_float (const char *what, float *f);
/**
* Create the specification to read a double.
*
* @param what describes what is being read (for error message creation)
* @param f address of double to read
*/
struct GNUNET_BIO_ReadSpec
GNUNET_BIO_read_spec_double (const char *what, double *f);
/**
* Execute the read specifications in order.
*
* @param h the IO handle to read from
* @param rs array of read specs
* the last element must be #GNUNET_BIO_read_spec_end
* @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
*/
int
GNUNET_BIO_read_spec_commit (struct GNUNET_BIO_ReadHandle *h,
struct GNUNET_BIO_ReadSpec *rs);
/******************************* WRITE SPEC API *****************************/
/**
* Function used to serialize data from a buffer and write it to @a h.
*
* @param cls closure (can be NULL)
* @param h the IO handle to write to
* @param what what is being written (for error message creation)
* @param source the data to write
* @param source_size how many bytes should be written
* @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
*/
typedef int
(*GNUNET_BIO_WriteHandler) (void *cls,
struct GNUNET_BIO_WriteHandle *h,
const char *what,
void *source,
size_t source_size);
/**
* Structure specifying a writing operation on an IO handle.
*/
struct GNUNET_BIO_WriteSpec
{
/**
* Function performing data serialization.
*/
GNUNET_BIO_WriteHandler wh;
/**
* Closure for @e rh. Can be NULL.
*/
void *cls;
/**
* What is being read (for error message creation)
*/
const char *what;
/**
* Source buffer. The data in this buffer will be written to the handle.
*/
void *source;
/**
* Size of @e source. If it's smaller than the real size of @e source, only
* this many bytes will be written.
*/
size_t source_size;
};
/**
* End of specifications marker.
*/
#define GNUNET_BIO_write_spec_end() \
{ NULL, NULL, NULL, NULL, 0 }
/**
* Create the specification to read some bytes.
*
* @param what describes what is being written (for error message creation)
* @param source the data to write
* @param size how many bytes should be written
* @return the write spec
*/
struct GNUNET_BIO_WriteSpec
GNUNET_BIO_write_spec_object (const char *what,
void *source,
size_t size);
/**
* Create the specification to write a 0-terminated string.
*
* @param what describes what is being read (for error message creation)
* @param s string to write (can be NULL)
* @return the read spec
*/
struct GNUNET_BIO_WriteSpec
GNUNET_BIO_write_spec_string (const char *what,
const char *s);
/**
* Create the specification to write an (u)int32_t.
*
* @param what describes what is being written (for error message creation)
* @param i pointer to a 32-bit integer
* @return the write spec
*/
struct GNUNET_BIO_WriteSpec
GNUNET_BIO_write_spec_int32 (const char *what,
int32_t *i);
/**
* Create the specification to write an (u)int64_t.
*
* @param what describes what is being written (for error message creation)
* @param i pointer to a 64-bit integer
* @return the write spec
*/
struct GNUNET_BIO_WriteSpec
GNUNET_BIO_write_spec_int64 (const char *what,
int64_t *i);
/**
* Create the specification to write a float.
*
* @param what describes what is being written (for error message creation)
* @param f pointer to a float
* @return the write spec
*/
struct GNUNET_BIO_WriteSpec
GNUNET_BIO_write_spec_float (const char *what, float *f);
/**
* Create the specification to write an double.
*
* @param what describes what is being written (for error message creation)
* @param f pointer to a double
* @return the write spec
*/
struct GNUNET_BIO_WriteSpec
GNUNET_BIO_write_spec_double (const char *what, double *f);
/**
* Execute the write specifications in order.
*
* @param h the IO handle to write to
* @param ws array of write specs
* the last element must be #GNUNET_BIO_write_spec_end
* @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
*/
int
GNUNET_BIO_write_spec_commit (struct GNUNET_BIO_WriteHandle *h,
struct GNUNET_BIO_WriteSpec *ws);
#if 0 /* keep Emacsens' auto-indent happy */
{
#endif
#ifdef __cplusplus
}
#endif
/* ifndef GNUNET_BIO_LIB_H */
#endif
/** @} */ /* end of group bio */
/** @} */ /* end of group addition */
/* end of gnunet_bio_lib.h */