ucx/buffer.c

changeset 124
80609f9675f1
parent 0
1f419bd32da1
child 152
62921b370c60
equal deleted inserted replaced
123:55adc92e7c09 124:80609f9675f1
1 /* 1 /*
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3 * 3 *
4 * Copyright 2013 Olaf Wintermann. All rights reserved. 4 * Copyright 2015 Olaf Wintermann. All rights reserved.
5 * 5 *
6 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met: 7 * modification, are permitted provided that the following conditions are met:
8 * 8 *
9 * 1. Redistributions of source code must retain the above copyright 9 * 1. Redistributions of source code must retain the above copyright
29 #include "buffer.h" 29 #include "buffer.h"
30 #include <stdarg.h> 30 #include <stdarg.h>
31 #include <stdlib.h> 31 #include <stdlib.h>
32 #include <string.h> 32 #include <string.h>
33 33
34 UcxBuffer *ucx_buffer_new(void *space, size_t size, int flags) { 34 UcxBuffer *ucx_buffer_new(void *space, size_t capacity, int flags) {
35 UcxBuffer *buffer = (UcxBuffer*) malloc(sizeof(UcxBuffer)); 35 UcxBuffer *buffer = (UcxBuffer*) malloc(sizeof(UcxBuffer));
36 if (buffer) { 36 if (buffer) {
37 buffer->flags = flags; 37 buffer->flags = flags;
38 if (!space) { 38 if (!space) {
39 buffer->space = (char*)malloc(size); 39 buffer->space = (char*)malloc(capacity);
40 if (!buffer->space) { 40 if (!buffer->space) {
41 free(buffer); 41 free(buffer);
42 return NULL; 42 return NULL;
43 } 43 }
44 memset(buffer->space, 0, size); 44 memset(buffer->space, 0, capacity);
45 buffer->flags |= UCX_BUFFER_AUTOFREE; 45 buffer->flags |= UCX_BUFFER_AUTOFREE;
46 } else { 46 } else {
47 buffer->space = (char*)space; 47 buffer->space = (char*)space;
48 } 48 }
49 buffer->capacity = size; 49 buffer->capacity = capacity;
50 buffer->size = 0; 50 buffer->size = 0;
51 51
52 buffer->pos = 0; 52 buffer->pos = 0;
53 } 53 }
54 54
62 free(buffer); 62 free(buffer);
63 } 63 }
64 64
65 UcxBuffer* ucx_buffer_extract( 65 UcxBuffer* ucx_buffer_extract(
66 UcxBuffer *src, size_t start, size_t length, int flags) { 66 UcxBuffer *src, size_t start, size_t length, int flags) {
67 if(src->size == 0) { 67
68 return NULL; 68 if (src->size == 0 || length == 0 || start+length > src->capacity) {
69 }
70 if (length == 0) {
71 length = src->size - start;
72 }
73 if (start+length > src->size) {
74 return NULL; 69 return NULL;
75 } 70 }
76 71
77 UcxBuffer *dst = (UcxBuffer*) malloc(sizeof(UcxBuffer)); 72 UcxBuffer *dst = (UcxBuffer*) malloc(sizeof(UcxBuffer));
78 if (dst) { 73 if (dst) {
97 npos = buffer->pos; 92 npos = buffer->pos;
98 break; 93 break;
99 case SEEK_END: 94 case SEEK_END:
100 npos = buffer->size; 95 npos = buffer->size;
101 break; 96 break;
97 case SEEK_SET:
98 npos = 0;
99 break;
102 default: 100 default:
103 npos = 0; 101 return -1;
104 } 102 }
105 103
104 size_t opos = npos;
106 npos += offset; 105 npos += offset;
107 106
108 if (npos > buffer->size) { 107 if ((offset > 0 && npos < opos) || (offset < 0 && npos > opos)) {
108 return -1;
109 }
110
111 if (npos >= buffer->size) {
109 return -1; 112 return -1;
110 } else { 113 } else {
111 buffer->pos = npos; 114 buffer->pos = npos;
112 return 0; 115 return 0;
113 } 116 }
118 return buffer->pos >= buffer->size; 121 return buffer->pos >= buffer->size;
119 } 122 }
120 123
121 int ucx_buffer_extend(UcxBuffer *buffer, size_t len) { 124 int ucx_buffer_extend(UcxBuffer *buffer, size_t len) {
122 size_t newcap = buffer->capacity; 125 size_t newcap = buffer->capacity;
123 while (buffer->pos + len > newcap) newcap <<= 1; 126
127 if (buffer->capacity + len < buffer->capacity) {
128 return -1;
129 }
130
131 while (buffer->capacity + len > newcap) {
132 newcap <<= 1;
133 if (newcap < buffer->capacity) {
134 return -1;
135 }
136 }
124 137
125 char *newspace = (char*)realloc(buffer->space, newcap); 138 char *newspace = (char*)realloc(buffer->space, newcap);
126 if (newspace) { 139 if (newspace) {
127 memset(newspace+buffer->size, 0, newcap-buffer->size); 140 memset(newspace+buffer->size, 0, newcap-buffer->size);
128 buffer->space = newspace; 141 buffer->space = newspace;
135 } 148 }
136 149
137 size_t ucx_buffer_write(const void *ptr, size_t size, size_t nitems, 150 size_t ucx_buffer_write(const void *ptr, size_t size, size_t nitems,
138 UcxBuffer *buffer) { 151 UcxBuffer *buffer) {
139 size_t len = size * nitems; 152 size_t len = size * nitems;
140 if (buffer->pos + len > buffer->capacity) { 153 size_t required = buffer->pos + len;
154 if (buffer->pos > required) {
155 return 0;
156 }
157
158 if (required > buffer->capacity) {
141 if ((buffer->flags & UCX_BUFFER_AUTOEXTEND) == UCX_BUFFER_AUTOEXTEND) { 159 if ((buffer->flags & UCX_BUFFER_AUTOEXTEND) == UCX_BUFFER_AUTOEXTEND) {
142 if(ucx_buffer_extend(buffer, len)) { 160 if (ucx_buffer_extend(buffer, required - buffer->capacity)) {
143 return -1; 161 return 0;
144 } 162 }
145 } else { 163 } else {
146 len = buffer->capacity - buffer->pos; 164 len = buffer->capacity - buffer->pos;
147 if (size > 1) len -= len%size; 165 if (size > 1) {
148 } 166 len -= len%size;
149 } 167 }
150 168 }
151 if (len <= 0) { 169 }
170
171 if (len == 0) {
152 return len; 172 return len;
153 } 173 }
154 174
155 memcpy(buffer->space + buffer->pos, ptr, len); 175 memcpy(buffer->space + buffer->pos, ptr, len);
156 buffer->pos += len; 176 buffer->pos += len;

mercurial