[Opensrf-commits] r1763 - in trunk: include/opensrf src/libopensrf (scottmk)
svn at svn.open-ils.org
svn at svn.open-ils.org
Sun Aug 30 23:48:29 EDT 2009
Author: scottmk
Date: 2009-08-30 23:48:26 -0400 (Sun, 30 Aug 2009)
New Revision: 1763
Modified:
trunk/include/opensrf/utils.h
trunk/src/libopensrf/utils.c
Log:
1. Add comments to be recognized by doxygen or other such
documentation generators.
2. Change the values returned by buffer_fadd(), buffer_add(),
buffer_add_n(), and buffer_add_char() to make them more
consistent. In practice we never pay any attention to the
return values anyway.
Modified: trunk/include/opensrf/utils.h
===================================================================
--- trunk/include/opensrf/utils.h 2009-08-28 20:31:31 UTC (rev 1762)
+++ trunk/include/opensrf/utils.h 2009-08-31 03:48:26 UTC (rev 1763)
@@ -14,6 +14,16 @@
GNU General Public License for more details.
*/
+/**
+ @file utils.h
+
+ @brief Prototypes for various low-level utility functions, and related macros.
+
+ Many of these facilities concern the growing_buffer structure,
+ a sort of poor man's string class that allocates more space for
+ itself as needed.
+*/
+
#ifndef UTILS_H
#define UTILS_H
@@ -34,7 +44,11 @@
#endif
#include "md5.h"
-
+/**
+ @brief Macro version of safe_malloc()
+ @param Pointer to be updated to point to newly allocated memory
+ @param How many bytes to allocate
+*/
#define OSRF_MALLOC(ptr, size) \
do {\
size_t _size = size; \
@@ -48,9 +62,17 @@
} while(0)
#ifdef NDEBUG
-// The original ... replace with noop once no more errors occur in NDEBUG mode
#define osrf_clearbuf( s, n ) memset( s, 0, n )
#else
+/**
+ @brief Fills a buffer with binary zeros (normal mode) or exclamation points (debugging mode)
+ @param s Pointer to buffer
+ @param n Length of buffer
+
+ This macro is used to help ferret out code that inappropriately assumes that a newly
+ allocated buffer is filled with binary zeros. No code should rely on it to do
+ anything in particular. Someday it may turn into a no-op.
+ */
#define osrf_clearbuf( s, n ) \
do { \
char * clearbuf_temp_s = (s); \
@@ -60,6 +82,12 @@
} while( 0 )
#endif
+/**
+ @brief Macro version of buffer_add()
+ @param gb Pointer to a growing_buffer
+ @param data Pointer to the string to be appended
+*/
+
#define OSRF_BUFFER_ADD(gb, data) \
do {\
int _tl; \
@@ -74,6 +102,12 @@
}\
} while(0)
+/**
+ @brief Macro version of buffer_add_n()
+ @param gb Pointer to a growing_buffer
+ @param data Pointer to the bytes to be appended
+ @param n How many characters to append
+*/
#define OSRF_BUFFER_ADD_N(gb, data, n) \
do {\
growing_buffer* gb__ = gb; \
@@ -89,6 +123,11 @@
}\
} while(0)
+/**
+ @brief Macro version of buffer_add_char()
+ @param gb Pointer to a growing buffer
+ @param c Character to be appended
+*/
#define OSRF_BUFFER_ADD_CHAR(gb, c)\
do {\
growing_buffer* _gb = gb;\
@@ -103,6 +142,10 @@
}\
}while(0)
+/**
+ @brief Macro version of buffer_reset()
+ @param gb Pointer to the growing_buffer to be reset
+*/
#define OSRF_BUFFER_RESET(gb) \
do {\
growing_buffer* _gb = gb;\
@@ -110,10 +153,23 @@
_gb->n_used = 0;\
}while(0)
+/**
+ @brief Resolves to a const pointer to the string inside a growing_buffer
+ @param Pointer to a growing_buffier
+*/
#define OSRF_BUFFER_C_STR( x ) ((const char *) (x)->buf)
-/* turns a va_list into a string */
+/**
+ @brief Turn a printf-style format string and a va_list into a string.
+ @param x A printf-style format string.
+
+ This macro can work only in a variadic function.
+
+ The resulting string is constructed in a local buffer, whose address is
+ given by the pointer VA_BUF, This buffer is NOT allocated dynamically,
+ so don't try to free it.
+*/
#define VA_LIST_TO_STRING(x) \
unsigned long __len = 0;\
va_list args; \
@@ -130,7 +186,13 @@
va_end(a_copy); \
char* VA_BUF = _b; \
-/* turns a long into a string */
+/**
+ @brief Format a long into a string.
+ @param l A long
+
+ The long is formatted into a local buffer whose address is given by the pointer
+ LONG_TO_STRING. This buffer is NOT allocated dynamically, so don't try to free it.
+*/
#define LONG_TO_STRING(l) \
unsigned int __len = snprintf(NULL, 0, "%ld", l) + 2;\
char __b[__len]; \
@@ -138,6 +200,13 @@
snprintf(__b, __len - 1, "%ld", l); \
char* LONGSTR = __b;
+/**
+ @brief Format a double into a string.
+ @param l A double
+
+ The double is formatted into a local buffer whose address is given by the pointer
+ LONG_TO_STRING. This buffer is NOT allocated dynamically, so don't try to free it.
+ */
#define DOUBLE_TO_STRING(l) \
unsigned int __len = snprintf(NULL, 0, "%f", l) + 2; \
char __b[__len]; \
@@ -145,6 +214,13 @@
snprintf(__b, __len - 1, "%f", l); \
char* DOUBLESTR = __b;
+/**
+ @brief Format a long double into a string.
+ @param l A long double
+
+ The long double is formatted into a local buffer whose address is given by the pointer
+ LONG_TO_STRING. This buffer is NOT allocated dynamically, so don't try to free it.
+ */
#define LONG_DOUBLE_TO_STRING(l) \
unsigned int __len = snprintf(NULL, 0, "%Lf", l) + 2; \
char __b[__len]; \
@@ -153,6 +229,13 @@
char* LONGDOUBLESTR = __b;
+/**
+ @brief Format an int into a string.
+ @param l An int
+
+ The int is formatted into a local buffer whose address is given by the pointer
+ LONG_TO_STRING. This buffer is NOT allocated dynamically, so don't try to free it.
+ */
#define INT_TO_STRING(l) \
unsigned int __len = snprintf(NULL, 0, "%d", l) + 2; \
char __b[__len]; \
@@ -184,6 +267,9 @@
+/**
+ @brief The maximum buffer size for a growing_buffer
+*/
#define BUFFER_MAX_SIZE 10485760
/* these are evil and should be condemned
@@ -192,7 +278,7 @@
set_proc_title.
the title is only allowed to be as big as the
initial process name of the process (full size of argv[]).
- truncation may occurr.
+ truncation may occur.
*/
int init_proc_title( int argc, char* argv[] );
int set_proc_title( const char* format, ... );
@@ -206,13 +292,30 @@
// ---------------------------------------------------------------------------------
// Generic growing buffer. Add data all you want
// ---------------------------------------------------------------------------------
+/**
+ @brief A poor man's string class in C.
+
+ A growing_buffer stores a character string. Related functions append data
+ and otherwise manage the string, allocating more memory automatically as needed
+ when the string gets too big for its buffer.
+
+ A growing_buffer is designed for text, not binary data. In particular: if you
+ try to store embedded nuls in one, something bad will almost certainly happen.
+*/
struct growing_buffer_struct {
+ /** @brief Pointer to the internal buffer */
char *buf;
+ /** @brief Length of the stored string */
int n_used;
+ /** @brief Size of the internal buffer */
int size;
};
typedef struct growing_buffer_struct growing_buffer;
+/**
+ @brief The length of the string stored by a growing_buffer.
+ @param x A pointer to the growing buffer.
+*/
#define buffer_length(x) (x)->n_used
growing_buffer* buffer_init( int initial_num_bytes);
@@ -267,14 +370,14 @@
int stringisnum(const char* s);
-/**
+/*
Calculates the md5 of the text provided.
The returned string must be freed by the caller.
*/
char* md5sum( const char* text, ... );
-/**
+/*
Checks the validity of the file descriptor
returns -1 if the file descriptor is invalid
returns 0 if the descriptor is OK
Modified: trunk/src/libopensrf/utils.c
===================================================================
--- trunk/src/libopensrf/utils.c 2009-08-28 20:31:31 UTC (rev 1762)
+++ trunk/src/libopensrf/utils.c 2009-08-31 03:48:26 UTC (rev 1763)
@@ -12,10 +12,33 @@
GNU General Public License for more details.
*/
+/**
+ @file utils.c
+
+ @brief A collection of various low-level utility functions.
+
+ About half of these functions concern the growing_buffer structure,
+ a sort of poor man's string class that allocates more space for
+ itself as needed.
+*/
#include <opensrf/utils.h>
#include <opensrf/log.h>
#include <errno.h>
+/**
+ @brief A thin wrapper for malloc().
+
+ @param size How many bytes to allocate.
+ @return a pointer to the allocated memory.
+
+ If the allocation fails, safe_malloc calls exit(). Consequently the
+ calling code doesn't have to check for NULL.
+
+ Currently safe_malloc() initializes the allocated buffer to all-bits-zero.
+ However the calling code should not rely on this behavior, because it is
+ likely to change. If you need your buffer filled with all-bits-zero, then
+ call safe_calloc() instead, or fill it yourself by calling memset().
+*/
inline void* safe_malloc( int size ) {
void* ptr = (void*) malloc( size );
if( ptr == NULL ) {
@@ -26,6 +49,15 @@
return ptr;
}
+/**
+ @brief A thin wrapper for calloc().
+
+ @param size How many bytes to allocate.
+ @return a pointer to the allocated memory.
+
+ If the allocation fails, safe_calloc calls exit(). Consequently the
+ calling code doesn't have to check for NULL.
+ */
inline void* safe_calloc( int size ) {
void* ptr = (void*) calloc( 1, size );
if( ptr == NULL ) {
@@ -35,18 +67,30 @@
return ptr;
}
-/****************
- The following static variables, and the following two functions,
- overwrite the argv array passed to main(). The purpose is to
- change the program name as reported by ps and similar utilities.
-
- Warning: this code makes the non-portable assumption that the
- strings to which argv[] points are contiguous in memory. The
- C Standard makes no such guarantee.
- ****************/
+/**
+ @brief Saves a pointer to the beginning of the argv[] array from main(). See init_proc_title().
+*/
static char** global_argv = NULL;
+/**
+ @brief Saves the length of the argv[] array from main(). See init_proc_title().
+ */
static int global_argv_size = 0;
+/**
+ @brief Save the size and location of the argv[] array.
+ @param argc The argc parameter to main().
+ @param argv The argv parameter to main().
+ @return zero.
+
+ Save a pointer to the argv[] array in the local static variable
+ global_argv. Add up the lengths of the strings in the argv[]
+ array, subtract 2, and store the result in the local variable
+ global_argv_size.
+
+ The return value, being invariant, is useless.
+
+ This function prepares for a subsequent call to set_proc_title().
+*/
int init_proc_title( int argc, char* argv[] ) {
global_argv = argv;
@@ -63,14 +107,39 @@
return 0;
}
+/**
+ @brief Replace the name of the running executable.
+ @param format A printf-style format string. Subsequent parameters, if any,
+ provide values to be formatted and inserted into the format string.
+ @return Length of the resulting string (or what the length would be if the
+ receiving buffer were big enough to hold it), or -1 in case of an encoding
+ error. Note: because some older versions of snprintf() don't work correctly,
+ this function may return -1 if the string is truncated for lack of space.
+
+ Formats a string as directed, and uses it to replace the name of the
+ currently running executable. This replacement string is what will
+ be seen and reported by utilities such as ps and top.
+
+ The replacement string goes into a location identified by a previous call
+ to init_proc_title().
+
+ WARNING: this function makes assumptions about the memory layout of
+ the argv[] array. ANSI C does not guarantee that these assumptions
+ are correct.
+*/
int set_proc_title( const char* format, ... ) {
VA_LIST_TO_STRING(format);
osrf_clearbuf( *(global_argv), global_argv_size);
return snprintf( *(global_argv), global_argv_size, VA_BUF );
}
+/**
+ @brief Determine current date and time to high precision.
+ @return Current date and time as seconds since the Epoch.
-/* utility method for profiling */
+ Used for profiling. The time resolution is system-dependent but is no finer
+ than microseconds.
+*/
double get_timestamp_millis( void ) {
struct timeval tv;
gettimeofday(&tv, NULL);
@@ -79,7 +148,18 @@
}
-/* setting/clearing file flags */
+/**
+ @brief Set designated file status flags for an open file descriptor.
+ @param fd The file descriptor to be tweaked.
+ @param flags A set of bitflags.
+ @return 0 if successful, -1 or if not.
+
+ Whatever bits are set in the flags parameter become set in the file status flags of
+ the file descriptor -- subject to the limitation that the only bits affected (at
+ least on Linux) are O_APPEND, O_ASYNC, O_DIRECT, O_NOATIME, and O_NONBLOCK.
+
+ See also clr_fl().
+*/
int set_fl( int fd, int flags ) {
int val;
@@ -95,6 +175,18 @@
return 0;
}
+/**
+ @brief Clear designated file status flags for an open file descriptor.
+ @param fd The file descriptor to be tweaked.
+ @param flags A set of bitflags.
+ @return 0 if successful, or -1 if not.
+
+ Whatever bits are set in the flags parameter become cleared in the file status flags
+ of the file descriptor -- subject to the limitation that the only bits affected (at
+ least on Linux) are O_APPEND, O_ASYNC, O_DIRECT, O_NOATIME, and O_NONBLOCK.
+
+ See also set_fl().
+ */
int clr_fl( int fd, int flags ) {
int val;
@@ -110,15 +202,33 @@
return 0;
}
+/**
+ @brief Determine how lohg a string will be after printf-style formatting.
+ @param format The format string.
+ @param args The variable-length list of arguments
+ @return If successful: the length of the string that would be created, plus 1 for
+ a terminal nul, plus another 1, presumably to be on the safe side. If unsuccessful
+ due to a formatting error: 1.
+
+ WARNINGS: the first parameter is not checked for NULL. The return value in case of an
+ error is not obviously sensible.
+*/
long va_list_size(const char* format, va_list args) {
int len = 0;
len = vsnprintf(NULL, 0, format, args);
va_end(args);
- len += 2;
- return len;
+ return len + 2;
}
+/**
+ @brief Format a printf-style string into a newly allocated buffer.
+ @param format The format string. Subsequent parameters, if any, will be
+ formatted and inserted into the resulting string.
+ @return A pointer to the string so created.
+
+ The calling code is responsible for freeing the string.
+*/
char* va_list_to_string(const char* format, ...) {
long len = 0;
@@ -143,6 +253,19 @@
// Flesh out a ubiqitous growing string buffer
// ---------------------------------------------------------------------------------
+/**
+ @brief Create a growing_buffer containing an empty string.
+ @param num_initial_bytes The initial size of the internal buffer, not counting the
+ terminal nul.
+ @return A pointer to the newly created growing_buffer.
+
+ The value of num_initial_bytes should typically be a plausible guess of how big
+ the string will ever be. However the guess doesn't have to accurate, because more
+ memory will be allocated as needed.
+
+ The calling code is responsible for freeing the growing_buffer by calling buffer_free()
+ or buffer_release().
+*/
growing_buffer* buffer_init(int num_initial_bytes) {
if( num_initial_bytes > BUFFER_MAX_SIZE ) return NULL;
@@ -160,16 +283,19 @@
}
-/* Expand the internal buffer of a growing_buffer so that it */
-/* will accommodate a specified string length. Return 0 if */
-/* successful, or 1 otherwise. */
+/**
+ @brief Allocate more memory for a growing_buffer.
+ @param gb A pointer to the growing_buffer.
+ @return 0 if successful, or 1 if not.
-/* Note that we do not check to see if the buffer is already */
-/* big enough. It is the responsibility of the calling */
-/* function to call this only when necessary. */
-
+ This function fails if it is asked to allocate BUFFER_MAX_SIZE
+ or more bytes.
+*/
static int buffer_expand( growing_buffer* gb, size_t total_len ) {
+ // We do not check to see if the buffer is already big enough. It is the
+ //responsibility of the calling function to call this only when necessary.
+
// Make sure the request is not excessive
if( total_len >= BUFFER_MAX_SIZE ) {
@@ -203,9 +329,19 @@
}
+/**
+ @brief Append a formatted string to a growing_buffer.
+ @param gb A pointer to the growing_buffer.
+ @param format A printf-style format string. Subsequent parameters, if any, will be
+ formatted and inserted into the resulting string.
+ @return If successful,the length of the resulting string; otherwise -1.
+
+ This function fails if either of the first two parameters is NULL,
+ or if the resulting string requires BUFFER_MAX_SIZE or more bytes.
+*/
int buffer_fadd(growing_buffer* gb, const char* format, ... ) {
- if(!gb || !format) return 0;
+ if(!gb || !format) return -1;
long len = 0;
va_list args;
@@ -224,16 +360,21 @@
va_end(a_copy);
return buffer_add(gb, buf);
-
}
+/**
+ @brief Appends a string to a growing_buffer.
+ @param gb A pointer to the growing_buffer.
+ @param data A pointer to the string to be appended.
+ @return If successful, the length of the resulting string; or if not, -1.
+*/
int buffer_add(growing_buffer* gb, const char* data) {
- if(!(gb && data)) return 0;
+ if(!(gb && data)) return -1;
int data_len = strlen( data );
- if(data_len == 0) return 0;
+ if(data_len == 0) return gb->n_used;
int total_len = data_len + gb->n_used;
@@ -247,12 +388,18 @@
return total_len;
}
-/** Append a specified number of characters to a growing_buffer.
- If the characters so appended include an embedded nul, the results
- are likely to be unhappy.
+/**
+ @brief Append a specified number of characters to a growing_buffer.
+ @param gb A pointer to the growing_buffer.
+ @param data A pointer to the characters to be appended.
+ @param n How many characters to be append.
+ @return If sccessful, the length of the resulting string; or if not, -1.
+
+ If the characters to be appended include an embedded nul byte, it will be appended
+ along with the others. The results are likely to be unpleasant.
*/
int buffer_add_n(growing_buffer* gb, const char* data, size_t n) {
- if(!(gb && data)) return 0;
+ if(!(gb && data)) return -1;
if(n == 0) return 0;
@@ -270,6 +417,11 @@
}
+/**
+ @brief Reset a growing_buffer so that it contains an empty string.
+ @param gb A pointer to the growing_buffer.
+ @return 0 if successful, -1 if not.
+*/
int buffer_reset( growing_buffer *gb){
if( gb == NULL ) { return -1; }
if( gb->buf == NULL ) { return -1; }
@@ -279,9 +431,16 @@
return gb->n_used;
}
-/* Return a pointer to the text within a growing_buffer, */
-/* while destroying the growing_buffer itself. */
+/**
+ @brief Free a growing_buffer and return a pointer to the string inside.
+ @param gb A pointer to the growing_buffer.
+ @return A pointer to the string previously contained by the growing buffer.
+ The calling code is responsible for freeing the string.
+
+ This function is equivalent to buffer_data() followed by buffer_free(). However
+ it is more efficient, because it avoids calls to strudup and free().
+*/
char* buffer_release( growing_buffer* gb) {
char* s = gb->buf;
s[gb->n_used] = '\0';
@@ -289,20 +448,37 @@
return s;
}
-/* Destroy a growing_buffer and the text it contains */
-
+/**
+ @brief Free a growing_buffer and its contents.
+ @param gb A pointer to the growing_buffer.
+ @return 1 if successful, or 0 if not (because the input parameter is NULL).
+*/
int buffer_free( growing_buffer* gb ) {
- if( gb == NULL )
+ if( gb == NULL )
return 0;
free( gb->buf );
free( gb );
return 1;
}
+/**
+ @brief Create a copy of the string inside a growing_buffer.
+ @param gb A pointer to the growing_buffer.
+ @return A pointer to the newly created copy.
+
+ The growing_buffer itself is not affected.
+
+ The calling code is responsible for freeing the string.
+*/
char* buffer_data( const growing_buffer *gb) {
return strdup( gb->buf );
}
+/**
+ @brief Remove the last character from a growing_buffer.
+ @param gb A pointer to the growing_buffer.
+ @return The character removed (or '\0' if the string is already empty).
+*/
char buffer_chomp(growing_buffer* gb) {
char c = '\0';
if(gb && gb->n_used > 0) {
@@ -314,6 +490,15 @@
}
+/**
+ @brief Append a single character to a growing_buffer.
+ @param gb A pointer to the growing_buffer.
+ @param c The character to be appended.
+ @return The length of the resulting string.
+
+ If the character appended is a nul byte (i.e. '\0') it will still be appended as if
+ it were a normal character. The results are likely to be unpleasant.
+*/
int buffer_add_char(growing_buffer* gb, char c ) {
if(gb && gb->buf) {
@@ -326,12 +511,35 @@
gb->buf[ gb->n_used ] = c;
gb->buf[ ++gb->n_used ] = '\0';
- }
-
- return gb->n_used;
+ return gb->n_used;
+ } else
+ return 0;
}
+/**
+ @brief Translate a UTF8 string into escaped ASCII, suitable for JSON.
+ @param string The input string to be translated.
+ @param size The length of the input string (need not be accurate).
+ @param full_escape Boolean; true turns on the escaping of certain
+ special characters.
+ @return A pointer to the translated version of the string.
+
+ Deprecated. Use buffer_append_utf8() instead.
+
+ If full_escape is non-zero, the translation will escape certain
+ certain characters with a backslash, according to the conventions
+ used in C and other languages: quotation marks, bell characters,
+ form feeds, horizontal tabs, carriage returns, line feeds, and
+ backslashes. A character with a numerical value less than 32, and
+ not one of the special characters mentioned above, will be
+ translated to a backslash followed by four hexadecimal characters.
+
+ If full_escape is zero, the translation will (incorrectly) leave
+ these characters unescaped and unchanged.
+
+ The calling code is responsible for freeing the returned string.
+*/
char* uescape( const char* string, int size, int full_escape ) {
if( NULL == string )
@@ -436,7 +644,14 @@
}
-// A function to turn a process into a daemon
+/**
+ @brief Become a proper daemon.
+ @return 0 if successful, or -1 if not.
+
+ Call fork(). The parent exits. The child moves to the root
+ directory, detaches from the terminal, and redirects the
+ standard streams (stdin, stdout, stderr) to /dev/null.
+*/
int daemonize( void ) {
pid_t f = fork();
@@ -468,9 +683,17 @@
}
-/* Return 1 if the string represents an integer, */
-/* as recognized by strtol(); Otherwise return 0. */
+/**
+ @brief Determine whether a string represents a decimal integer.
+ @param s A pointer to the string.
+ @return 1 if the string represents a decimal integer, or 0 if it
+ doesn't.
+ To qualify as a decimal integer, the string must consist entirely
+ of optional leading white space, an optional leading sign, and
+ one or more decimal digits. In addition, the number must be
+ representable as a long.
+*/
int stringisnum(const char* s) {
char* w;
strtol(s, &w, 10);
@@ -479,6 +702,17 @@
+/**
+ @brief Translate a printf-style formatted string into an MD5 message digest.
+ @param text The format string. Subsequent parameters, if any, provide values to be
+ formatted and inserted into the format string.
+ @return A pointer to a string of 32 hexadecimal characters.
+
+ The calling code is responsible for freeing the returned string.
+
+ This function is a wrapper for some public domain routines written by David Madore,
+ Ron Rivest, and Colin Plumb.
+*/
char* md5sum( const char* text, ... ) {
struct md5_ctx ctx;
@@ -507,6 +741,13 @@
}
+/**
+ @brief Determine whether a given file descriptor is valid.
+ @param fd The file descriptor to be checked.
+ @return 0 if the file descriptor is valid, or -1 if it isn't.
+
+ The most likely reason a file descriptor would be invalid is if it isn't open.
+*/
int osrfUtilsCheckFileDescriptor( int fd ) {
fd_set tmpset;
More information about the opensrf-commits
mailing list