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->_data = LDNS_XMALLOC(uint8_t, size);
00048 memcpy(buffer->_data, data, size);
00049 buffer->_fixed = 0;
00050 buffer->_status = LDNS_STATUS_OK;
00051
00052 ldns_buffer_invariant(buffer);
00053 }
00054
00055 void
00056 ldns_buffer_clear(ldns_buffer *buffer)
00057 {
00058 ldns_buffer_invariant(buffer);
00059
00060
00061
00062 buffer->_position = 0;
00063 buffer->_limit = buffer->_capacity;
00064 }
00065
00066 void
00067 ldns_buffer_flip(ldns_buffer *buffer)
00068 {
00069 ldns_buffer_invariant(buffer);
00070
00071 buffer->_limit = buffer->_position;
00072 buffer->_position = 0;
00073 }
00074
00075 void
00076 ldns_buffer_rewind(ldns_buffer *buffer)
00077 {
00078 ldns_buffer_invariant(buffer);
00079
00080 buffer->_position = 0;
00081 }
00082
00083 bool
00084 ldns_buffer_set_capacity(ldns_buffer *buffer, size_t capacity)
00085 {
00086 void *data;
00087
00088 ldns_buffer_invariant(buffer);
00089 assert(buffer->_position <= capacity);
00090
00091 data = (uint8_t *) LDNS_XREALLOC(buffer->_data, uint8_t, capacity);
00092 if (!data) {
00093 buffer->_status = LDNS_STATUS_MEM_ERR;
00094 return false;
00095 } else {
00096 buffer->_data = data;
00097 buffer->_limit = buffer->_capacity = capacity;
00098 return true;
00099 }
00100 }
00101
00102 bool
00103 ldns_buffer_reserve(ldns_buffer *buffer, size_t amount)
00104 {
00105 ldns_buffer_invariant(buffer);
00106 assert(!buffer->_fixed);
00107 if (buffer->_capacity < buffer->_position + amount) {
00108 size_t new_capacity = buffer->_capacity * 3 / 2;
00109
00110 if (new_capacity < buffer->_position + amount) {
00111 new_capacity = buffer->_position + amount;
00112 }
00113 if (!ldns_buffer_set_capacity(buffer, new_capacity)) {
00114 buffer->_status = LDNS_STATUS_MEM_ERR;
00115 return false;
00116 }
00117 }
00118 buffer->_limit = buffer->_capacity;
00119 return true;
00120 }
00121
00122 int
00123 ldns_buffer_printf(ldns_buffer *buffer, const char *format, ...)
00124 {
00125 va_list args;
00126 int written = 0;
00127 size_t remaining;
00128
00129 if (ldns_buffer_status_ok(buffer)) {
00130 ldns_buffer_invariant(buffer);
00131 assert(buffer->_limit == buffer->_capacity);
00132
00133 remaining = ldns_buffer_remaining(buffer);
00134 va_start(args, format);
00135 written = vsnprintf((char *) ldns_buffer_current(buffer), remaining,
00136 format, args);
00137 va_end(args);
00138 if (written == -1) {
00139 buffer->_status = LDNS_STATUS_INTERNAL_ERR;
00140 return -1;
00141 } else if ((size_t) written >= remaining) {
00142 if (!ldns_buffer_reserve(buffer, (size_t) written + 1)) {
00143 buffer->_status = LDNS_STATUS_MEM_ERR;
00144 return -1;
00145 }
00146 va_start(args, format);
00147 written = vsnprintf((char *) ldns_buffer_current(buffer),
00148 ldns_buffer_remaining(buffer), format, args);
00149 va_end(args);
00150 if (written == -1) {
00151 buffer->_status = LDNS_STATUS_INTERNAL_ERR;
00152 return -1;
00153 }
00154 }
00155 buffer->_position += written;
00156 }
00157 return written;
00158 }
00159
00160 void
00161 ldns_buffer_free(ldns_buffer *buffer)
00162 {
00163 if (!buffer) {
00164 return;
00165 }
00166
00167 LDNS_FREE(buffer->_data);
00168
00169 LDNS_FREE(buffer);
00170 }
00171
00172 void *
00173 ldns_buffer_export(ldns_buffer *buffer)
00174 {
00175 buffer->_fixed = 1;
00176 return buffer->_data;
00177 }
00178
00179 int
00180 ldns_bgetc(ldns_buffer *buffer)
00181 {
00182 if (!ldns_buffer_available_at(buffer, buffer->_position, sizeof(uint8_t))) {
00183 ldns_buffer_set_position(buffer, ldns_buffer_limit(buffer));
00184
00185 return EOF;
00186 }
00187 return (int)ldns_buffer_read_u8(buffer);
00188 }