LP#1709710: Make chunk sizing smart about XML quoting
[opensrf-equinox.git] / include / opensrf / utils.h
index ebf05a5..34e0ba6 100644 (file)
@@ -1,5 +1,5 @@
 /*
-Copyright (C) 2005  Georgia Public Library Service 
+Copyright (C) 2005  Georgia Public Library Service
 Bill Erickson <highfalutin@gmail.com>
 Mike Rylander <mrylander@gmail.com>
 
@@ -14,6 +14,16 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 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
 
@@ -29,22 +39,40 @@ GNU General Public License for more details.
 #include <string.h>
 //#include <sys/timeb.h>
 
-#include "md5.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
 
+#include "md5.h"
+/**
+       @brief Macro version of safe_malloc()
+       @param ptr Pointer to be updated to point to newly allocated memory
+       @param size How many bytes to allocate
+*/
 #define OSRF_MALLOC(ptr, size) \
        do {\
-               ptr = (void*) malloc( size ); \
-               if( ptr == NULL ) { \
-                       perror("OSRF_MALLOC(): Out of Memory" );\
-                       exit(99); \
-               } \
-               memset( ptr, 0, size );\
-       } while(0)
-
-#ifndef NDEBUG
-// The original ... replace with noop once no more errors occur in NDEBUG mode
+                       size_t _size = size; \
+                       void* p = malloc( _size ); \
+                       if( p == NULL ) { \
+                               perror("OSRF_MALLOC(): Out of Memory" ); \
+                               exit(99); \
+                       } \
+                       memset( p, 0, _size ); \
+                       (ptr) = p; \
+               } while(0)
+
+#ifdef NDEBUG
 #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); \
@@ -54,36 +82,94 @@ GNU General Public License for more details.
        } 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; \
-               if(gb && data) {\
-                       __tl = strlen(data) + gb->n_used;\
-                       if( __tl < gb->size ) {\
-                               strcat(gb->buf, data);\
-                               gb->n_used = __tl; \
-                       } else { buffer_add(gb, data); }\
+               int _tl; \
+               growing_buffer* _gb = gb; \
+               const char* _data = data; \
+               if(_gb && _data) {\
+                       _tl = strlen(_data) + _gb->n_used;\
+                       if( _tl < _gb->size ) {\
+                               strcpy( _gb->buf + _gb->n_used, _data ); \
+                               _gb->n_used = _tl; \
+                       } else { buffer_add(_gb, _data); }\
                }\
        } 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; \
+               const char* data__ = data; \
+               size_t n__ = n; \
+               if(gb__ && data__) {\
+                       int tl__ = n__ + gb__->n_used;\
+                       if( tl__ < gb__->size ) {\
+                               memcpy( gb__->buf + gb__->n_used, data__, n__ ); \
+                               gb__->buf[tl__] = '\0'; \
+                               gb__->n_used = tl__; \
+} else { buffer_add_n(gb__, data__, n__); }\
+}\
+} 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 {\
-               if(gb) {\
-                       if(gb->n_used < gb->size - 1)\
-                               gb->buf[gb->n_used++] = c;\
+               growing_buffer* _gb = gb;\
+               char _c = c;\
+               if(_gb) {\
+                       if(_gb->n_used < _gb->size - 1) {\
+                               _gb->buf[_gb->n_used++] = _c;\
+                               _gb->buf[_gb->n_used]   = '\0';\
+                       }\
                        else\
-                               buffer_add_char(gb, c);\
+                               buffer_add_char(_gb, _c);\
                }\
        }while(0)
 
+/**
+       @brief Macro version of buffer_reset()
+       @param gb Pointer to the growing_buffer to be reset
+*/
 #define OSRF_BUFFER_RESET(gb) \
-    memset(gb->buf, 0, gb->size);\
-    gb->n_used = 0;
+       do {\
+               growing_buffer* _gb = gb;\
+               memset(_gb->buf, 0, _gb->size);\
+               _gb->n_used = 0;\
+       }while(0)
+
+/**
+       @brief Resolves to a const pointer to the string inside a growing_buffer
+       @param x Pointer to a growing_buffier
+*/
+#define OSRF_BUFFER_C_STR( x ) ((const char *) (x)->buf)
 
-       
 
+/**
+       @brief Turn a printf-style format string and a va_list into a string.
+       @param x A printf-style format string.
 
-/* turns a va_list into a 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; \
@@ -100,7 +186,13 @@ GNU General Public License for more details.
        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
+       LONGSTR.  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]; \
@@ -108,6 +200,13 @@ GNU General Public License for more details.
        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
+       DOUBLESTR.  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]; \
@@ -115,6 +214,13 @@ GNU General Public License for more details.
        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
+       LONGDOUBLESTR.  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]; \
@@ -123,6 +229,13 @@ GNU General Public License for more details.
        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
+       INTSTR.  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]; \
@@ -151,24 +264,24 @@ GNU General Public License for more details.
        */
 
 
-       
-
-
-#define BUFFER_MAX_SIZE 10485760 
+/**
+       @brief The maximum buffer size for a growing_buffer
+*/
+#define BUFFER_MAX_SIZE 10485760
 
-/* these are evil and should be condemned 
+/* these are evil and should be condemned
        ! Only use these if you are done with argv[].
        call init_proc_title() first, then call
-       set_proc_title. 
+       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( char* format, ... );
+int set_proc_title( const char* format, ... );
 
-
-int daemonize();
+int daemonizeWithCallback( void (*)(pid_t, int), int );
+int daemonize( void );
 
 void* safe_malloc(int size);
 void* safe_calloc(int size);
@@ -176,47 +289,65 @@ void* safe_calloc(int size);
 // ---------------------------------------------------------------------------------
 // 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;
 
-growing_buffer* buffer_init( int initial_num_bytes);
+/**
+       @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
 
-// XXX This isn't defined in utils.c!! removing for now...
-//int buffer_addchar(growing_buffer* gb, char c);
+growing_buffer* buffer_init( int initial_num_bytes);
 
-int buffer_add(growing_buffer* gb, char* c);
+int buffer_add(growing_buffer* gb, const char* c);
+int buffer_add_n(growing_buffer* gb, const char* data, size_t n);
 int buffer_fadd(growing_buffer* gb, const char* format, ... );
 int buffer_reset( growing_buffer* gb);
-char* buffer_data( growing_buffer* gb);
+char* buffer_data( const growing_buffer* gb);
 char* buffer_release( growing_buffer* gb );
 int buffer_free( growing_buffer* gb );
 int buffer_add_char(growing_buffer* gb, char c);
+char buffer_chomp(growing_buffer* gb); // removes the last character from the buffer
 
-/* returns the size needed to fill in the vsnprintf buffer.  
-       * ! this calls va_end on the va_list argument*
-       */
+/*
+       returns the size needed to fill in the vsnprintf buffer.
+       this calls va_end on the va_list argument*
+*/
 long va_list_size(const char* format, va_list);
 
-/* turns a va list into a string, caller must free the 
+/* turns a va list into a string, caller must free the
        allocated char */
 char* va_list_to_string(const char* format, ...);
 
 
-/* string escape utility method.  escapes unicode embeded characters.
-       escapes the usual \n, \t, etc. 
+/* string escape utility method.  escapes unicode embedded characters.
+       escapes the usual \n, \t, etc.
        for example, if you provide a string like so:
 
        hello,
                you
 
        you would get back:
-       hello,\n\tyou
- */
+       \thello,\n\t\tyou
+*/
 char* uescape( const char* string, int size, int full_escape );
 
 /* utility methods */
@@ -224,33 +355,36 @@ int set_fl( int fd, int flags );
 int clr_fl( int fd, int flags );
 
 
-
 // Utility method
-double get_timestamp_millis();
+double get_timestamp_millis( void );
 
 
 /* returns true if the whole string is a number */
-int stringisnum(char* s);
+int stringisnum(const char* s);
 
-/* reads a file and returns the string version of the file
-       user is responsible for freeing the returned char*
-       */
-char* file_to_string(const char* filename);
 
+/*
+       Calculates the md5 of the text provided.
+       The returned string must be freed by the caller.
+*/
+char* md5sum( const char* text, ... );
 
 
-/** 
-  Calculates the md5 of the text provided.
-  The returned string must be freed by the caller.
-  */
-char* md5sum( char* text, ... );
+/*
+       Checks the validity of the file descriptor
+       returns -1 if the file descriptor is invalid
+       returns 0 if the descriptor is OK
+*/
+int osrfUtilsCheckFileDescriptor( int fd );
 
+/*
+       Returns the approximate additional length of
+       a string after XML escaping <, >, &, and ".
+*/
+size_t osrfXmlEscapingLength ( const char* str );
 
-/**
-  Checks the validity of the file descriptor
-  returns -1 if the file descriptor is invalid
-  returns 0 if the descriptor is OK
-  */
-int osrfUtilsCheckFileDescriptor( int fd );
+#ifdef __cplusplus
+}
+#endif
 
 #endif