00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include <ldns/config.h>
00011
00012 #include <ldns/ldns.h>
00013 #include <ldns/buffer.h>
00014
00015 ldns_buffer *
00016 ldns_buffer_new(size_t capacity)
00017 {
00018 ldns_buffer *buffer = LDNS_MALLOC(ldns_buffer);
00019
00020 if (!buffer) {
00021 return NULL;
00022 }
00023
00024 buffer->_data = (uint8_t *) LDNS_XMALLOC(uint8_t, capacity);
00025 if (!buffer->_data) {
00026 LDNS_FREE(buffer);
00027 return NULL;
00028 }
00029
00030 buffer->_position = 0;
00031 buffer->_limit = buffer->_capacity = capacity;
00032 buffer->_fixed = 0;
00033 buffer->_status = LDNS_STATUS_OK;
00034
00035 ldns_buffer_invariant(buffer);
00036
00037 return buffer;
00038 }
00039
00040 void
00041 ldns_buffer_new_frm_data(ldns_buffer *buffer, void *data, size_t size)
00042 {
00043 assert(data != NULL);
00044
00045 buffer->_position = 0;
00046 buffer->_limit = buffer->_capacity = size;
00047 buffer->_fixed = 0;
00048 buffer->_data = LDNS_XMALLOC(uint8_t, size);
00049 if(!buffer->_data) {
00050 buffer->_status = LDNS_STATUS_MEM_ERR;
00051 return;
00052 }
00053 memcpy(buffer->_data, data, size);
00054 buffer->_status = LDNS_STATUS_OK;
00055
00056 ldns_buffer_invariant(buffer);
00057 }
00058
00059 bool
00060 ldns_buffer_set_capacity(ldns_buffer *buffer, size_t capacity)
00061 {
00062 void *data;
00063
00064 ldns_buffer_invariant(buffer);
00065 assert(buffer->_position <= capacity);
00066
00067 data = (uint8_t *) LDNS_XREALLOC(buffer->_data, uint8_t, capacity);
00068 if (!data) {
00069 buffer->_status = LDNS_STATUS_MEM_ERR;
00070 return false;
00071 } else {
00072 buffer->_data = data;
00073 buffer->_limit = buffer->_capacity = capacity;
00074 return true;
00075 }
00076 }
00077
00078 bool
00079 ldns_buffer_reserve(ldns_buffer *buffer, size_t amount)
00080 {
00081 ldns_buffer_invariant(buffer);
00082 assert(!buffer->_fixed);
00083 if (buffer->_capacity < buffer->_position + amount) {
00084 size_t new_capacity = buffer->_capacity * 3 / 2;
00085
00086 if (new_capacity < buffer->_position + amount) {
00087 new_capacity = buffer->_position + amount;
00088 }
00089 if (!ldns_buffer_set_capacity(buffer, new_capacity)) {
00090 buffer->_status = LDNS_STATUS_MEM_ERR;
00091 return false;
00092 }
00093 }
00094 buffer->_limit = buffer->_capacity;
00095 return true;
00096 }
00097
00098 int
00099 ldns_buffer_printf(ldns_buffer *buffer, const char *format, ...)
00100 {
00101 va_list args;
00102 int written = 0;
00103 size_t remaining;
00104
00105 if (ldns_buffer_status_ok(buffer)) {
00106 ldns_buffer_invariant(buffer);
00107 assert(buffer->_limit == buffer->_capacity);
00108
00109 remaining = ldns_buffer_remaining(buffer);
00110 va_start(args, format);
00111 written = vsnprintf((char *) ldns_buffer_current(buffer), remaining,
00112 format, args);
00113 va_end(args);
00114 if (written == -1) {
00115 buffer->_status = LDNS_STATUS_INTERNAL_ERR;
00116 return -1;
00117 } else if ((size_t) written >= remaining) {
00118 if (!ldns_buffer_reserve(buffer, (size_t) written + 1)) {
00119 buffer->_status = LDNS_STATUS_MEM_ERR;
00120 return -1;
00121 }
00122 va_start(args, format);
00123 written = vsnprintf((char *) ldns_buffer_current(buffer),
00124 ldns_buffer_remaining(buffer), format, args);
00125 va_end(args);
00126 if (written == -1) {
00127 buffer->_status = LDNS_STATUS_INTERNAL_ERR;
00128 return -1;
00129 }
00130 }
00131 buffer->_position += written;
00132 }
00133 return written;
00134 }
00135
00136 void
00137 ldns_buffer_free(ldns_buffer *buffer)
00138 {
00139 if (!buffer) {
00140 return;
00141 }
00142
00143 if (!buffer->_fixed)
00144 LDNS_FREE(buffer->_data);
00145
00146 LDNS_FREE(buffer);
00147 }
00148
00149 void *
00150 ldns_buffer_export(ldns_buffer *buffer)
00151 {
00152 buffer->_fixed = 1;
00153 return buffer->_data;
00154 }
00155
00156 int
00157 ldns_bgetc(ldns_buffer *buffer)
00158 {
00159 if (!ldns_buffer_available_at(buffer, buffer->_position, sizeof(uint8_t))) {
00160 ldns_buffer_set_position(buffer, ldns_buffer_limit(buffer));
00161
00162 return EOF;
00163 }
00164 return (int)ldns_buffer_read_u8(buffer);
00165 }
00166
00167 void
00168 ldns_buffer_copy(ldns_buffer* result, ldns_buffer* from)
00169 {
00170 size_t tocopy = ldns_buffer_limit(from);
00171
00172 if(tocopy > ldns_buffer_capacity(result))
00173 tocopy = ldns_buffer_capacity(result);
00174 ldns_buffer_clear(result);
00175 ldns_buffer_write(result, ldns_buffer_begin(from), tocopy);
00176 ldns_buffer_flip(result);
00177 }