Simple tools for networking / objects in plain C Snapshot
bf.h
Go to the documentation of this file.
00001 #ifndef __BUFF_H_
00002 #define __BUFF_H_ 
00003 
00004 #include <nutils/endutil.h>
00005 #include <string.h>
00006 
00007 /**
00008  @defgroup BF
00009  @brief protocol buffer. idea similar to skb_buff, does not own it's data.
00010  The following invariants hold
00011 
00012  START_OF_BUFFER <= start <= get_pos <= put_pos <= end <= END_OF_BUFFER.
00013 
00014  The effective buffer ranges from start up to end pointers - the range [start end)
00015  start may be larger than START_OF_BUFFER, as a way of reserving room for a header.
00016  end may be less than END_OF_BUFFER, as a way of reserving root for a footer.
00017  
00018  the get_pos position will advance as data is returned from the buffer 
00019  the pus_pos position will advance, as data is placed int the buffer.
00020 
00021  @{
00022  */
00023 typedef struct tagBF {
00024   uint8_t *bf;
00025   size_t   bf_size;
00026 
00027   uint8_t *start, *get_pos, *put_pos, *end;
00028 
00029 } BF;
00030 
00031 
00032 /**
00033  * @brief initialise an empty protocol buffer object. 
00034  * start and end cover the whole memory range.
00035      * nitiay get and put pointer are set to start of range.
00036  */
00037 M_INLINE void BF_init( BF *bf, void *buffer, size_t buffer_size )
00038 {
00039    bf->bf =  (uint8_t *) buffer;
00040    bf->bf_size = buffer_size;
00041 
00042    bf->start =   (uint8_t *) buffer;
00043    bf->end = buffer + buffer_size;
00044 
00045    bf->get_pos = bf->put_pos = bf->start;
00046 }
00047 
00048 /**
00049  * @brief validates a buffer - checks all invariants.
00050  */
00051 int BF_check( BF * bf );
00052 
00053 /**
00054  * @brief set pointers so that we can 'get' the whole range from start to end.
00055  */
00056 M_INLINE void BF_get_mode( BF *bf )
00057 {
00058     bf->get_pos = bf->start;
00059     bf->put_pos = bf->end;
00060 }
00061 
00062 
00063 /**
00064  * @brief set pointers so that we can 'put' the whole range from start to end.
00065  */
00066 M_INLINE void BF_put_mode( BF *bf )
00067 {
00068     bf->get_pos = bf->start;
00069     bf->put_pos = bf->start;
00070 }
00071 
00072 /**
00073  * @brief returns number of bytes that can be returned by _get_
00074  */
00075 M_INLINE size_t BF_get_size( BF *bf )
00076 {
00077   return bf->put_pos - bf->get_pos;
00078 }
00079 
00080 
00081 /**
00082  * @brief returns number of bytes that can be written by _put_
00083  */
00084 M_INLINE size_t BF_put_size( BF *bf )
00085 {
00086   return bf->end - bf->put_pos;
00087 }
00088 
00089 
00090 /** 
00091  * @brief set start position, position is relative to start of memory range.
00092  */
00093 int BF_set_start( BF * bf, size_t pos );
00094 
00095 /** 
00096  * @brief set end position, position is relative to start of memory range.
00097  */
00098 int BF_set_end( BF * bf, size_t pos );
00099 
00100 
00101 /** 
00102  * @brief set get position, position is relative to 'start' pointer.
00103  */
00104 int BF_set_get( BF * bf, size_t pos );
00105 
00106 /** 
00107  * @brief set put position, position is relative to 'start' pointer.
00108  */
00109 int BF_set_put( BF * bf, size_t pos );
00110 
00111 /**
00112  * @brief returns number of bytes that cam be read from this buffer (i.e. that BF_get_(type) return ) 
00113  */
00114 M_INLINE size_t BF_can_get( BF *bf )
00115 {
00116     return bf->put_pos - bf->get_pos;
00117 }
00118 
00119 /**
00120  * @brief returns number of bytes that cam be placed into this buffer (i.e. that BF_put_(type) places into this buffer ) 
00121  */
00122 M_INLINE size_t BF_can_put( BF *bf )
00123 {
00124     return bf->end - bf->put_pos;
00125 }
00126 
00127 /**
00128  * @brief return 1 if the whole buffer is fulled with data (get_pos == start && put_pos == end)
00129  */
00130 M_INLINE int BF_is_full( BF *bf )
00131 {
00132     return bf->get_pos == bf->start && bf->end == bf->put_pos;
00133 }
00134 
00135 /**
00136  * @brief moves get_pos to start position; moves content between get_pos and put_pos if not empty.a
00137  * Always succeeds
00138  * returns 0 if bytes were moved, 1 if buffer was empty to begin with.
00139  */
00140 int BF_compact( BF * bf );
00141 
00142 
00143 /**
00144   @ brief get the next line.
00145  */
00146 char *  BF_get_line( BF * bf, int eof_line);
00147 
00148 /**
00149   @ brief get the next line.
00150  */
00151 char *  BF_get_line_ext( BF * bf, const char *eof_line, size_t eof_line_size);
00152 
00153 
00154 #define BF_DECLARE_PUT_MACRO( type ) \
00155 M_INLINE int BF_put_##type ( BF *bf, type val ) \
00156 { \
00157    if ((bf->end - bf->put_pos) < (ptrdiff_t) sizeof( type ) ) { \
00158      return -1 ; \
00159    } \
00160    do { \
00161      type nval = h2n_##type ( val ); \
00162      *( ( type *) bf->put_pos) = nval; \
00163      bf->put_pos += sizeof ( type ); \
00164    } while(0); \
00165    return 0; \
00166 } 
00167 
00168 BF_DECLARE_PUT_MACRO( uint8_t )
00169 BF_DECLARE_PUT_MACRO( int8_t )
00170 BF_DECLARE_PUT_MACRO( uint16_t )
00171 BF_DECLARE_PUT_MACRO( int16_t )
00172 BF_DECLARE_PUT_MACRO( uint32_t )
00173 BF_DECLARE_PUT_MACRO( int32_t )
00174 BF_DECLARE_PUT_MACRO( uint64_t )
00175 BF_DECLARE_PUT_MACRO( int64_t )
00176 
00177 /**
00178  * @brief add memory block to buffer
00179  * @returns -1 not enough room left, 0 on success.
00180  */
00181 M_INLINE int BF_putn ( BF *bf, void *data, size_t data_size ) 
00182 { 
00183    if ((bf->end - bf->put_pos) < (ptrdiff_t) data_size ) { 
00184      return -1 ; 
00185    } 
00186    memcpy( bf->put_pos, data, data_size );
00187    bf->put_pos += data_size;
00188    return 0;
00189 } 
00190 
00191 
00192 #define BF_DECLARE_GET_MACRO( type ) \
00193 M_INLINE int BF_get_##type ( BF *bf, type *pval ) \
00194 { \
00195    if ((bf->put_pos - bf->get_pos) < (ptrdiff_t) sizeof( type ) ) { \
00196      return -1 ; \
00197    } \
00198    *pval = n2h_##type( *( ( type *) bf->get_pos) ); \
00199    bf->get_pos += sizeof( type ); \
00200    return 0; \
00201 }
00202 
00203 BF_DECLARE_GET_MACRO( uint8_t )
00204 BF_DECLARE_GET_MACRO( int8_t )
00205 BF_DECLARE_GET_MACRO( uint16_t )
00206 BF_DECLARE_GET_MACRO( int16_t )
00207 BF_DECLARE_GET_MACRO( uint32_t )
00208 BF_DECLARE_GET_MACRO( int32_t )
00209 BF_DECLARE_GET_MACRO( uint64_t )
00210 BF_DECLARE_GET_MACRO( int64_t )
00211 
00212 #define BF_DECLARE_PUT_UNSAFE_MACRO( type ) \
00213 M_INLINE void BF_put_unsafe_##type ( BF *bf, type val ) \
00214 { \
00215   type nval = h2n_##type ( val ); \
00216   *( ( type *) bf->put_pos) = nval; \
00217   bf->put_pos += sizeof ( type ); \
00218 } 
00219 
00220 BF_DECLARE_PUT_UNSAFE_MACRO(uint8_t)
00221 BF_DECLARE_PUT_UNSAFE_MACRO(int8_t) 
00222 BF_DECLARE_PUT_UNSAFE_MACRO(uint16_t)
00223 BF_DECLARE_PUT_UNSAFE_MACRO(int16_t) 
00224 BF_DECLARE_PUT_UNSAFE_MACRO(uint32_t)
00225 BF_DECLARE_PUT_UNSAFE_MACRO(int32_t)
00226 BF_DECLARE_PUT_UNSAFE_MACRO(uint64_t)
00227 BF_DECLARE_PUT_UNSAFE_MACRO(int64_t)
00228 
00229 #define BF_DECLARE_GET_UNSAFE_MACRO( type ) \
00230 M_INLINE type BF_get_unsafe_##type ( BF *bf ) { \
00231    type rval = n2h_##type( *( ( type *) bf->get_pos) ); \
00232    bf->get_pos += sizeof( type ); \
00233    return rval; \
00234 }
00235 
00236 BF_DECLARE_GET_UNSAFE_MACRO(uint8_t)
00237 BF_DECLARE_GET_UNSAFE_MACRO(int8_t)
00238 BF_DECLARE_GET_UNSAFE_MACRO(uint16_t)
00239 BF_DECLARE_GET_UNSAFE_MACRO(int16_t)
00240 BF_DECLARE_GET_UNSAFE_MACRO(uint32_t)
00241 BF_DECLARE_GET_UNSAFE_MACRO(int32_t)
00242 BF_DECLARE_GET_UNSAFE_MACRO(uint64_t)
00243 BF_DECLARE_GET_UNSAFE_MACRO(int64_t)
00244 
00245 /**
00246  @}
00247 */
00248 
00249 #endif