Simple tools for networking / objects in plain C Snapshot
|
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