1 /*
2 NETWIB
3 Network library
4 Copyright(c) 1999-2010 Laurent Constantin
5 -----
6
7 Main server : http://www.laurentconstantin.com/
8 Backup server : http://laurentconstantin.free.fr/
9 [my current email address is on the web servers]
10
11 -----
12 This file is part of Netwib.
13
14 Netwib is free software: you can redistribute it and/or modify
15 it under the terms of the GNU General Public License version 3
16 as published by the Free Software Foundation.
17
18 Netwib is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details (http://www.gnu.org/).
22
23 ------------------------------------------------------------------------
24 */
25
26 #include <netwib/inc/maininc.h>
27
28 /*-------------------------------------------------------------*/
29 #define NETWIB_PRIV_BUF_DEFAULT_APPEND1 1024
30 #define NETWIB_PRIV_BUF_DEFAULT_APPEND2 16384
31
32 /*-------------------------------------------------------------*/
33 #define NETWIB_PRIV_BUF_PTR_CLOSED ((netwib_data)1)
34
35 /*-------------------------------------------------------------*/
36 #if NETWIB_DEBUG_LEAK==1
37 /* MSBs bitfield stores leakid */
38 #define netwib__priv_buf_get_leakid(pbuf) (pbuf->flags>>NETWIB_BUF_FLAGS_USEDBITS)
39 #define netwib__priv_buf_set_leakid(pbuf,leakid) { pbuf->flags = (leakid<<NETWIB_BUF_FLAGS_USEDBITS) | (pbuf->flags&((1<<NETWIB_BUF_FLAGS_USEDBITS)-1)); }
40 #else
41 /* field inittype stores only inittype */
42 #define netwib__priv_buf_get_leakid(pbuf)
43 #define netwib__priv_buf_set_leakid(pbuf,leakid)
44 #endif
45
46 /*-------------------------------------------------------------*/
47 #define netwib__priv_buf_cangrow(pb) ((pb)->flags&(NETWIB_BUF_FLAGS_ALLOC|NETWIB_BUF_FLAGS_CANALLOC))
48
49 /*-------------------------------------------------------------*/
50 #define netwib__priv_buf_canslide(pb) (((pb)->flags&NETWIB_BUF_FLAGS_CANSLIDE) && (pb)->beginoffset!=0 && (!netwib__priv_buf_cangrow(pb) || ((pb)->beginoffset> (pb)->totalsize/2)))
51 #define netwib__priv_buf_slide(pb) {netwib_c_memcpy((pb)->totalptr, netwib__buf_ref_data_ptr(pb), netwib__buf_ref_data_size(pb)); (pb)->endoffset -= (pb)->beginoffset; (pb)->beginoffset = 0;}
52
53 /*-------------------------------------------------------------*/
netwib_priv_buf_realloc(netwib_uint32 neededspace,netwib_buf * pbuf)54 static netwib_err netwib_priv_buf_realloc(netwib_uint32 neededspace,
55 netwib_buf *pbuf)
56 {
57 netwib_data data;
58 netwib_uint32 reallocsize;
59 netwib_uint32 allocstep;
60
61 if (neededspace == 0) {
62 return(NETWIB_ERR_OK);
63 }
64
65 allocstep = NETWIB_PRIV_BUF_DEFAULT_APPEND1;
66 if (pbuf->totalsize > NETWIB_PRIV_BUF_DEFAULT_APPEND2) {
67 allocstep = NETWIB_PRIV_BUF_DEFAULT_APPEND2;
68 }
69 reallocsize = pbuf->totalsize;
70 reallocsize += ((neededspace-1)/allocstep + 1) * allocstep;
71
72 if (pbuf->flags & NETWIB_BUF_FLAGS_ALLOC) {
73 /* realloc */
74 #if NETWIB_DEBUG_LEAK==1
75 netwib_er(netwib_debug_leak_del_buf(pbuf->totalptr,
76 netwib__priv_buf_get_leakid(pbuf)));
77 #endif
78 if (pbuf->flags & NETWIB_BUF_FLAGS_SENSITIVE) {
79 /* slow but safe */
80 netwib_er(netwib_ptr_malloc(reallocsize, (netwib_ptr*)&data));
81 netwib_c_memcpy(data, pbuf->totalptr, pbuf->totalsize);
82 netwib_c_memset(pbuf->totalptr, 0, pbuf->totalsize);
83 netwib_er(netwib_ptr_free((netwib_ptr*)&pbuf->totalptr));
84 pbuf->totalptr = data;
85 } else {
86 netwib_er(netwib_ptr_realloc(reallocsize, (netwib_ptr*)&pbuf->totalptr));
87 }
88 #if NETWIB_DEBUG_LEAK==1
89 netwib_er(netwib_debug_leak_add_buf(pbuf->totalptr,
90 netwib__priv_buf_get_leakid(pbuf)));
91 #endif
92 } else {
93 /* allocate buffer */
94 netwib_er(netwib_ptr_malloc(reallocsize, (netwib_ptr*)&data));
95 if (pbuf->flags & NETWIB_BUF_FLAGS_CANALLOC) {
96 /* convert an array to an allocated memory */
97 netwib_c_memcpy(data, pbuf->totalptr, pbuf->totalsize);
98 if ( (pbuf->flags & NETWIB_BUF_FLAGS_SENSITIVE) &&
99 !(pbuf->flags & NETWIB_BUF_FLAGS_SENSITIVE_READONLY)) {
100 netwib_c_memset(pbuf->totalptr, 0, pbuf->totalsize);
101 }
102 pbuf->totalptr = data;
103 /* we do not need to change beginoffset and endoffset */
104 pbuf->flags &= ~NETWIB_BUF_FLAGS_CANALLOC;
105 pbuf->flags |= NETWIB_BUF_FLAGS_ALLOC;
106 } else {
107 return(NETWIB_ERR_LOINTERNALERROR);
108 }
109 #if NETWIB_DEBUG_LEAK==1
110 {
111 netwib_uint32 leakid;
112 netwib_er(netwib_debug_leak_id_buf(&leakid));
113 netwib__priv_buf_set_leakid(pbuf, leakid);
114 netwib_er(netwib_debug_leak_add_buf(pbuf->totalptr, leakid));
115 }
116 #endif
117 }
118
119 pbuf->totalsize = reallocsize;
120
121 return(NETWIB_ERR_OK);
122 }
123
124 /*-------------------------------------------------------------*/
netwib_buf_init_malloc(netwib_uint32 allocsize,netwib_buf * pbuf)125 netwib_err netwib_buf_init_malloc(netwib_uint32 allocsize,
126 netwib_buf *pbuf)
127 {
128 netwib_data data;
129 netwib_uint32 totalsize;
130
131 /* parameter verification */
132 if (pbuf == NULL) {
133 /* nothing to alloc */
134 return(NETWIB_ERR_OK);
135 }
136
137 /* better to warn user */
138 if (allocsize == 0) {
139 return(NETWIB_ERR_PATOOLOW);
140 }
141
142 /* compute totalsize */
143 totalsize = allocsize;
144
145 /* allocate memory */
146 netwib_er(netwib_ptr_malloc(totalsize, (netwib_ptr*)&data));
147
148 /* set values */
149 pbuf->flags = NETWIB_BUF_FLAGS_ALLOC;
150 pbuf->totalptr = data;
151 pbuf->totalsize = totalsize;
152 pbuf->beginoffset = 0;
153 pbuf->endoffset = 0;
154
155 #if NETWIB_DEBUG_LEAK==1
156 {
157 netwib_uint32 leakid;
158 netwib_er(netwib_debug_leak_id_buf(&leakid));
159 netwib__priv_buf_set_leakid(pbuf, leakid);
160 netwib_er(netwib_debug_leak_add_buf(pbuf->totalptr, leakid));
161 }
162 #endif
163
164 return(NETWIB_ERR_OK);
165 }
166
167 /*-------------------------------------------------------------*/
netwib_buf_init_ext_array(netwib_constptr array,netwib_uint32 arraysize,netwib_uint32 beginoffset,netwib_uint32 endoffset,netwib_bufext * pbuf)168 netwib_err netwib_buf_init_ext_array(netwib_constptr array,
169 netwib_uint32 arraysize,
170 netwib_uint32 beginoffset,
171 netwib_uint32 endoffset,
172 netwib_bufext *pbuf)
173 {
174 /* parameters verification */
175 if (array == NULL && arraysize)
176 return(NETWIB_ERR_PANULLPTRSIZE);
177 if (beginoffset > arraysize)
178 return(NETWIB_ERR_PATOOHIGH);
179 if (endoffset > arraysize)
180 return(NETWIB_ERR_PATOOHIGH);
181 if (pbuf == NULL) {
182 /* nothing to do */
183 return(NETWIB_ERR_OK);
184 }
185
186 /* set values */
187 pbuf->flags = 0;
188 netwib__priv_buf_set_leakid(pbuf, NETWIB_DEBUG_LEAK_ID_BUF_IGNORE);
189 pbuf->totalptr = netwib_priv_castdata(array);
190 pbuf->totalsize = arraysize;
191 pbuf->beginoffset = beginoffset;
192 pbuf->endoffset = endoffset;
193
194 return(NETWIB_ERR_OK);
195 }
196
197 /*-------------------------------------------------------------*/
netwib_buf_init_ext_storagearray(netwib_constptr array,netwib_uint32 arraysize,netwib_bufext * pbuf)198 netwib_err netwib_buf_init_ext_storagearray(netwib_constptr array,
199 netwib_uint32 arraysize,
200 netwib_bufext *pbuf)
201 {
202 /* parameters verification */
203 if (array == NULL && arraysize)
204 return(NETWIB_ERR_PANULLPTRSIZE);
205 if (pbuf == NULL) {
206 /* nothing to do */
207 return(NETWIB_ERR_OK);
208 }
209
210 /* set values */
211 pbuf->flags = NETWIB_BUF_FLAGS_CANALLOC;
212 netwib__priv_buf_set_leakid(pbuf, NETWIB_DEBUG_LEAK_ID_BUF_IGNORE);
213 pbuf->totalptr = netwib_priv_castdata(array);
214 pbuf->totalsize = arraysize;
215 pbuf->beginoffset = 0;
216 pbuf->endoffset = 0;
217
218 return(NETWIB_ERR_OK);
219 }
220
221 /*-------------------------------------------------------------*/
netwib_buf_init_ext_buf(netwib_constbuf * pbufin,netwib_bufext * pbuf)222 netwib_err netwib_buf_init_ext_buf(netwib_constbuf *pbufin,
223 netwib_bufext *pbuf)
224 {
225 if (pbuf == NULL) {
226 /* nothing to do */
227 return(NETWIB_ERR_OK);
228 }
229
230 /* set values */
231 pbuf->flags = 0;
232 netwib__priv_buf_set_leakid(pbuf, NETWIB_DEBUG_LEAK_ID_BUF_IGNORE);
233 pbuf->totalptr = netwib__buf_ref_data_ptr(pbufin);
234 pbuf->totalsize = netwib__buf_ref_data_size(pbufin);
235 pbuf->beginoffset = 0;
236 pbuf->endoffset = netwib__buf_ref_data_size(pbufin);
237 netwib__buf_transfersensitive(pbufin, pbuf);
238
239 return(NETWIB_ERR_OK);
240 }
241
242 /*-------------------------------------------------------------*/
netwib_buf_init_ext_string(netwib_conststring str,netwib_bufext * pbuf)243 netwib_err netwib_buf_init_ext_string(netwib_conststring str,
244 netwib_bufext *pbuf)
245 {
246 /* parameter verification */
247 if (pbuf == NULL) {
248 /* nothing to do */
249 return(NETWIB_ERR_OK);
250 }
251
252 /* set values */
253 pbuf->flags = 0;
254 netwib__priv_buf_set_leakid(pbuf, NETWIB_DEBUG_LEAK_ID_BUF_IGNORE);
255 pbuf->beginoffset = 0;
256 if (str) {
257 pbuf->endoffset = netwib_c_strlen(str);
258 pbuf->totalptr = netwib_priv_castdata(str);
259 pbuf->totalsize = pbuf->endoffset + 1;
260 } else {
261 pbuf->endoffset = 0;
262 pbuf->totalptr = NULL;
263 pbuf->totalsize = 0;
264 }
265
266 return(NETWIB_ERR_OK);
267 }
268
269 /*-------------------------------------------------------------*/
netwib_buf_shift(netwib_buf * pbuf,netwib_int32 offset,netwib_bool truncbegend)270 netwib_err netwib_buf_shift(netwib_buf *pbuf,
271 netwib_int32 offset,
272 netwib_bool truncbegend)
273 {
274 netwib_uint32 offsetpos, datasize;
275
276 /* simple cases */
277 if (pbuf == NULL) {
278 /* shifting an empty buffer does not change it */
279 return(NETWIB_ERR_OK);
280 }
281 if (pbuf->totalptr == NETWIB_PRIV_BUF_PTR_CLOSED)
282 return(NETWIB_ERR_LOOBJUSECLOSED);
283
284 #if NETWIB_DEBUG_LEAK==1
285 netwib_er(netwib_debug_leak_valid_buf(pbuf->totalptr,
286 netwib__priv_buf_get_leakid(pbuf)));
287 #endif
288
289 /* simple case */
290 if (offset == 0) {
291 return(NETWIB_ERR_OK);
292 }
293
294 /* if truncate */
295 if (truncbegend) {
296 datasize = pbuf->endoffset - pbuf->beginoffset;
297 if (offset < 0) {
298 offsetpos = (netwib_uint32)-offset;
299 if (offsetpos >= datasize) {
300 pbuf->endoffset = pbuf->beginoffset;
301 return(NETWIB_ERR_OK);
302 }
303 netwib_c_memcpy(pbuf->totalptr + pbuf->beginoffset,
304 pbuf->totalptr + pbuf->beginoffset + offsetpos,
305 datasize - offsetpos);
306 pbuf->endoffset += offset;
307 return(NETWIB_ERR_OK);
308 }
309 offsetpos = (netwib_uint32)offset;
310 if (offsetpos >= datasize) {
311 pbuf->beginoffset = pbuf->endoffset;
312 return(NETWIB_ERR_OK);
313 }
314 netwib_c_memmove(pbuf->totalptr + pbuf->beginoffset + offset,
315 pbuf->totalptr + pbuf->beginoffset,
316 datasize - offsetpos);
317 pbuf->beginoffset += offset;
318 return(NETWIB_ERR_OK);
319 }
320
321 /* now, do not truncate */
322 if (offset < 0) {
323 offsetpos = (netwib_uint32)-offset;
324
325 /* simple left shift */
326 if (offsetpos <= pbuf->beginoffset) {
327 netwib_c_memcpy(pbuf->totalptr + pbuf->beginoffset + offset,
328 pbuf->totalptr + pbuf->beginoffset,
329 pbuf->endoffset - pbuf->beginoffset);
330 pbuf->beginoffset += offset;
331 pbuf->endoffset += offset;
332 return(NETWIB_ERR_OK);
333 }
334
335 /* full overwrite left shift */
336 if (offsetpos >= pbuf->endoffset) {
337 pbuf->beginoffset = 0;
338 pbuf->endoffset = 0;
339 return(NETWIB_ERR_OK);
340 }
341
342 /* half overwrite left shift */
343 netwib_c_memcpy(pbuf->totalptr,
344 pbuf->totalptr - offset,
345 pbuf->endoffset + offset);
346 pbuf->beginoffset = 0;
347 pbuf->endoffset += offset;
348 return(NETWIB_ERR_OK);
349 }
350
351 offsetpos = (netwib_uint32)offset;
352
353 /* simple right shift */
354 if (offsetpos <= pbuf->totalsize - pbuf->endoffset) {
355 netwib_c_memmove(pbuf->totalptr + pbuf->beginoffset + offset,
356 pbuf->totalptr + pbuf->beginoffset,
357 pbuf->endoffset - pbuf->beginoffset);
358 pbuf->beginoffset += offset;
359 pbuf->endoffset += offset;
360 return(NETWIB_ERR_OK);
361 }
362
363 if (!netwib__priv_buf_cangrow(pbuf)) {
364 /* will truncate */
365 if (offsetpos > pbuf->totalsize - pbuf->beginoffset) {
366 pbuf->beginoffset = pbuf->totalsize;
367 } else {
368 netwib_c_memmove(pbuf->totalptr + pbuf->beginoffset + offset,
369 pbuf->totalptr + pbuf->beginoffset,
370 pbuf->totalsize - pbuf->beginoffset - offset);
371 pbuf->beginoffset += offset;
372 }
373 pbuf->endoffset = pbuf->totalsize;
374 return(NETWIB_ERR_OK);
375 }
376
377 /* right shift with realloc */
378 netwib_er(netwib_priv_buf_realloc(offset - pbuf->totalsize+pbuf->endoffset,
379 pbuf));
380 netwib_c_memmove(pbuf->totalptr + pbuf->beginoffset + offset,
381 pbuf->totalptr + pbuf->beginoffset,
382 pbuf->endoffset - pbuf->beginoffset);
383 pbuf->beginoffset += offset;
384 pbuf->endoffset += offset;
385
386 return(NETWIB_ERR_OK);
387 }
388
389 /*-------------------------------------------------------------*/
netwib_buf_append_data(netwib_constdata data,netwib_uint32 datasize,netwib_buf * pbuf)390 netwib_err netwib_buf_append_data(netwib_constdata data,
391 netwib_uint32 datasize,
392 netwib_buf *pbuf)
393 {
394 netwib_uint32 leftsize;
395
396 /* parameters verification */
397 if (data == NULL && datasize) {
398 return(NETWIB_ERR_PANULLPTRSIZE);
399 }
400
401 /* simple case */
402 if (pbuf == NULL) {
403 /* nothing to append to nothing */
404 return(NETWIB_ERR_OK);
405 }
406 if (pbuf->totalptr == NETWIB_PRIV_BUF_PTR_CLOSED)
407 return(NETWIB_ERR_LOOBJUSECLOSED);
408 #if NETWIB_DEBUG_LEAK==1
409 netwib_er(netwib_debug_leak_valid_buf(pbuf->totalptr,
410 netwib__priv_buf_get_leakid(pbuf)));
411 #endif
412 if (datasize == 0) {
413 return(NETWIB_ERR_OK);
414 }
415
416 /* append */
417 leftsize = pbuf->totalsize - pbuf->endoffset;
418 if (datasize <= leftsize) {
419 /* if sufficient, only append data */
420 netwib_c_memcpy(pbuf->totalptr+pbuf->endoffset, data, datasize);
421 pbuf->endoffset += datasize;
422 return(NETWIB_ERR_OK);
423 }
424
425 /* no space for data : check if we can slide */
426 if (netwib__priv_buf_canslide(pbuf)) {
427 leftsize += pbuf->beginoffset;
428 if (datasize <= leftsize) {
429 netwib__priv_buf_slide(pbuf);
430 netwib_c_memcpy(pbuf->totalptr+pbuf->endoffset, data, datasize);
431 pbuf->endoffset += datasize;
432 return(NETWIB_ERR_OK);
433 }
434 }
435
436 /* no space for data */
437 if (!netwib__priv_buf_cangrow(pbuf)) {
438 return(NETWIB_ERR_DATANOSPACE);
439 }
440
441 /* we need to realloc */
442 if (netwib__priv_buf_canslide(pbuf)) {
443 /* decide to slide even if it is not sufficient : on next call,
444 we will no more slide (it's better to slide when there is a small
445 amount of memory to copy) */
446 netwib__priv_buf_slide(pbuf);
447 }
448 netwib_er(netwib_priv_buf_realloc(datasize - leftsize, pbuf));
449 /* now, copy data */
450 netwib_c_memcpy(pbuf->totalptr+pbuf->endoffset, data, datasize);
451 pbuf->endoffset += datasize;
452 return(NETWIB_ERR_OK);
453 }
454
455 /*-------------------------------------------------------------*/
netwib_buf_append_string(netwib_conststring str,netwib_buf * pbuf)456 netwib_err netwib_buf_append_string(netwib_conststring str,
457 netwib_buf *pbuf)
458 {
459 if (str != NULL && pbuf != NULL) {
460 netwib_er(netwib_buf_append_data((netwib_constdata)str,
461 netwib_c_strlen(str),
462 pbuf));
463 }
464
465 return(NETWIB_ERR_OK);
466 }
467
468 /*-------------------------------------------------------------*/
netwib_buf_append_buf(netwib_constbuf * pbuftoappend,netwib_buf * pbuf)469 netwib_err netwib_buf_append_buf(netwib_constbuf *pbuftoappend,
470 netwib_buf *pbuf)
471 {
472
473 if (pbuftoappend == NULL || pbuf == NULL) {
474 /* nothing to append */
475 return(NETWIB_ERR_OK);
476 }
477
478 if (pbuftoappend->totalptr == NETWIB_PRIV_BUF_PTR_CLOSED) {
479 return(NETWIB_ERR_LOOBJUSECLOSED);
480 }
481 #if NETWIB_DEBUG_LEAK==1
482 netwib_er(netwib_debug_leak_valid_buf(pbuftoappend->totalptr,
483 netwib__priv_buf_get_leakid(pbuftoappend)));
484 #endif
485 netwib__buf_transfersensitive(pbuftoappend, pbuf);
486
487 if (pbuftoappend->beginoffset < pbuftoappend->endoffset) {
488 netwib_er(netwib_buf_append_data(pbuftoappend->totalptr +
489 pbuftoappend->beginoffset,
490 pbuftoappend->endoffset -
491 pbuftoappend->beginoffset,
492 pbuf));
493 }
494
495 return(NETWIB_ERR_OK);
496 }
497
498 /*-------------------------------------------------------------*/
netwib_buf_append_byte(netwib_byte b,netwib_buf * pbuf)499 netwib_err netwib_buf_append_byte(netwib_byte b,
500 netwib_buf *pbuf)
501 {
502 netwib_uint32 leftsize;
503
504 /* simple case */
505 if (pbuf == NULL) {
506 /* nothing to append */
507 return(NETWIB_ERR_OK);
508 }
509 if (pbuf->totalptr == NETWIB_PRIV_BUF_PTR_CLOSED)
510 return(NETWIB_ERR_LOOBJUSECLOSED);
511 #if NETWIB_DEBUG_LEAK==1
512 netwib_er(netwib_debug_leak_valid_buf(pbuf->totalptr,
513 netwib__priv_buf_get_leakid(pbuf)));
514 #endif
515
516 /* append */
517 leftsize = pbuf->totalsize - pbuf->endoffset;
518 if (leftsize > 0) {
519 /* if sufficient, only append data */
520 pbuf->totalptr[pbuf->endoffset] = b;
521 pbuf->endoffset++;
522 return(NETWIB_ERR_OK);
523 }
524
525 /* no space for data : check if we can slide */
526 if (netwib__priv_buf_canslide(pbuf)) {
527 if (pbuf->beginoffset) {
528 netwib__priv_buf_slide(pbuf);
529 pbuf->totalptr[pbuf->endoffset] = b;
530 pbuf->endoffset++;
531 return(NETWIB_ERR_OK);
532 }
533 }
534
535 if (!netwib__priv_buf_cangrow(pbuf)) {
536 /* there is no space */
537 return(NETWIB_ERR_DATANOSPACE);
538 }
539
540 /* we need to realloc */
541 if (netwib__priv_buf_canslide(pbuf)) {
542 netwib__priv_buf_slide(pbuf);
543 }
544 netwib_er(netwib_priv_buf_realloc(1, pbuf));
545
546 /* now, copy data */
547 pbuf->totalptr[pbuf->endoffset] = b;
548 pbuf->endoffset++;
549 return(NETWIB_ERR_OK);
550 }
551
552 /*-------------------------------------------------------------*/
netwib_buf_prepend_buf(netwib_constbuf * pbuftoprepend,netwib_buf * pbuf)553 netwib_err netwib_buf_prepend_buf(netwib_constbuf *pbuftoprepend,
554 netwib_buf *pbuf)
555 {
556 netwib_uint32 buftoprependsize;
557
558 /* simple case */
559 if (pbuftoprepend == NULL || pbuf == NULL) {
560 /* nothing to prepend */
561 return(NETWIB_ERR_OK);
562 }
563
564 if (pbuf->totalptr == NETWIB_PRIV_BUF_PTR_CLOSED)
565 return(NETWIB_ERR_LOOBJUSECLOSED);
566 if (pbuftoprepend->totalptr == NETWIB_PRIV_BUF_PTR_CLOSED)
567 return(NETWIB_ERR_LOOBJUSECLOSED);
568 #if NETWIB_DEBUG_LEAK==1
569 netwib_er(netwib_debug_leak_valid_buf(pbuf->totalptr,
570 netwib__priv_buf_get_leakid(pbuf)));
571 netwib_er(netwib_debug_leak_valid_buf(pbuftoprepend->totalptr,
572 netwib__priv_buf_get_leakid(pbuftoprepend)));
573 #endif
574 netwib__buf_transfersensitive(pbuftoprepend, pbuf);
575
576 buftoprependsize = netwib__buf_ref_data_size(pbuftoprepend);
577 if (buftoprependsize > pbuf->beginoffset) {
578 /* need some shift */
579 netwib_er(netwib_buf_shift(pbuf, buftoprependsize - pbuf->beginoffset,
580 NETWIB_FALSE));
581 }
582 pbuf->beginoffset -= buftoprependsize;
583 netwib_c_memcpy(netwib__buf_ref_data_ptr(pbuf),
584 netwib__buf_ref_data_ptr(pbuftoprepend),
585 buftoprependsize);
586
587 return(NETWIB_ERR_OK);
588 }
589
590 /*-------------------------------------------------------------*/
netwib_buf_ref_string(netwib_buf * pbuf,netwib_string * pstr)591 netwib_err netwib_buf_ref_string(netwib_buf *pbuf,
592 netwib_string *pstr)
593 {
594 netwib_char *pc, *pfirst;
595
596 /* simple case */
597 if (pbuf == NULL) {
598 /* it's not possible to obtain info if this pointer is NULL */
599 return(NETWIB_ERR_DATANOSPACE);
600 }
601 if (pbuf->totalptr == NETWIB_PRIV_BUF_PTR_CLOSED) {
602 return(NETWIB_ERR_LOOBJUSECLOSED);
603 }
604 #if NETWIB_DEBUG_LEAK==1
605 netwib_er(netwib_debug_leak_valid_buf(pbuf->totalptr,
606 netwib__priv_buf_get_leakid(pbuf)));
607 #endif
608
609 /* eventually add a '\0' */
610 if (pbuf->endoffset < pbuf->totalsize) {
611 /* there is room to add a '\0' */
612 if (pbuf->totalptr[pbuf->endoffset] != '\0') {
613 /* we do this check because external array might be constant string
614 (so it cannot be set) */
615 pbuf->totalptr[pbuf->endoffset] = '\0';
616 }
617 } else if (netwib__priv_buf_canslide(pbuf)) {
618 /* buffer can be slided, slide it to add a '\0' */
619 netwib__priv_buf_slide(pbuf);
620 pbuf->totalptr[pbuf->endoffset] = '\0';
621 } else if (netwib__priv_buf_cangrow(pbuf)) {
622 /* buffer can be reallocated */
623 netwib_er(netwib_priv_buf_realloc(1, pbuf));
624 /* now, set zero */
625 pbuf->totalptr[pbuf->endoffset] = '\0';
626 } else if (netwib__buf_ref_data_size(pbuf)) {
627 /* our last chance is to find a zero in the middle of the buffer */
628 pfirst = (netwib_string)pbuf->totalptr + pbuf->beginoffset;
629 pc = (netwib_string)pbuf->totalptr + pbuf->endoffset - 1;
630 while (NETWIB_TRUE) {
631 if (*pc == '\0') {
632 /* we are lucky, there is one */
633 break;
634 }
635 if (pc == pfirst) {
636 break;
637 }
638 pc--;
639 }
640 if (*pc != '\0') {
641 return(NETWIB_ERR_DATANOSPACE);
642 }
643 } else {
644 /* we didn't found a zero, and there is no room to put it */
645 return(NETWIB_ERR_DATANOSPACE);
646 }
647
648 if (pstr != NULL) {
649 /* set output */
650 *pstr = (netwib_string)netwib__buf_ref_data_ptr(pbuf);
651 }
652
653 return(NETWIB_ERR_OK);
654 }
655
656 /*-------------------------------------------------------------*/
netwib_constbuf_ref_string(netwib_constbuf * pbuf,netwib_string * pstr)657 netwib_err netwib_constbuf_ref_string(netwib_constbuf *pbuf,
658 netwib_string *pstr)
659 {
660 netwib_char *pc, *pfirst;
661
662 /* simple case */
663 if (pbuf == NULL) {
664 /* it's not possible to obtain info if this pointer is NULL */
665 return(NETWIB_ERR_DATANOSPACE);
666 }
667 if (pbuf->totalptr == NETWIB_PRIV_BUF_PTR_CLOSED) {
668 return(NETWIB_ERR_LOOBJUSECLOSED);
669 }
670 #if NETWIB_DEBUG_LEAK==1
671 netwib_er(netwib_debug_leak_valid_buf(pbuf->totalptr,
672 netwib__priv_buf_get_leakid(pbuf)));
673 #endif
674
675 /* check if there is already a '\0' */
676 if (pbuf->endoffset < pbuf->totalsize &&
677 pbuf->totalptr[pbuf->endoffset] == '\0') {
678 /* ok */
679 } else if (netwib__buf_ref_data_size(pbuf)) {
680 /* our last chance is to find a zero in the middle of the buffer */
681 pfirst = (netwib_string)pbuf->totalptr + pbuf->beginoffset;
682 pc = (netwib_string)pbuf->totalptr + pbuf->endoffset - 1;
683 while (NETWIB_TRUE) {
684 if (*pc == '\0') {
685 /* we are lucky, there is one */
686 break;
687 }
688 if (pc == pfirst) {
689 break;
690 }
691 pc--;
692 }
693 if (*pc != '\0') {
694 return(NETWIB_ERR_DATANOSPACE);
695 }
696 } else {
697 /* we didn't found a zero, and there is no room to put it */
698 return(NETWIB_ERR_DATANOSPACE);
699 }
700
701 if (pstr != NULL) {
702 /* set output */
703 *pstr = (netwib_string)netwib__buf_ref_data_ptr(pbuf);
704 }
705
706 return(NETWIB_ERR_OK);
707 }
708
709 /*-------------------------------------------------------------*/
netwib_buf_wantspace(netwib_buf * pbuf,netwib_uint32 wantedspace,netwib_data * pdata)710 netwib_err netwib_buf_wantspace(netwib_buf *pbuf,
711 netwib_uint32 wantedspace,
712 netwib_data *pdata)
713 {
714 netwib_uint32 leftsize;
715
716 /* simple case */
717 if (pbuf == NULL) {
718 /* it's not possible to obtain info if this pointer is NULL */
719 return(NETWIB_ERR_PANULLPTR);
720 }
721 if (pbuf->totalptr == NETWIB_PRIV_BUF_PTR_CLOSED) {
722 return(NETWIB_ERR_LOOBJUSECLOSED);
723 }
724 #if NETWIB_DEBUG_LEAK==1
725 netwib_er(netwib_debug_leak_valid_buf(pbuf->totalptr,
726 netwib__priv_buf_get_leakid(pbuf)));
727 #endif
728
729 leftsize = pbuf->totalsize - pbuf->endoffset;
730 if (wantedspace <= leftsize) {
731 /* sufficient space */
732 if (pdata != NULL) {
733 *pdata = pbuf->totalptr + pbuf->endoffset;
734 }
735 return(NETWIB_ERR_OK);
736 }
737
738 /* no space for data : check if we can slide */
739 if (netwib__priv_buf_canslide(pbuf)) {
740 leftsize += pbuf->beginoffset;
741 if (wantedspace <= leftsize) {
742 netwib__priv_buf_slide(pbuf);
743 if (pdata != NULL) {
744 *pdata = pbuf->totalptr + pbuf->endoffset;
745 }
746 return(NETWIB_ERR_OK);
747 }
748 }
749
750 if (!netwib__priv_buf_cangrow(pbuf)) {
751 /* cannot realloc */
752 return(NETWIB_ERR_DATANOSPACE);
753 }
754
755 /* realloc */
756 if (netwib__priv_buf_canslide(pbuf)) {
757 netwib__priv_buf_slide(pbuf);
758 }
759 netwib_er(netwib_priv_buf_realloc(wantedspace - leftsize, pbuf));
760
761 if (pdata != NULL) {
762 *pdata = pbuf->totalptr + pbuf->endoffset;
763 }
764
765 return(NETWIB_ERR_OK);
766 }
767
768 /*-------------------------------------------------------------*/
netwib_buf_wishspace(netwib_buf * pbuf,netwib_uint32 wantedspace,netwib_data * pdata,netwib_uint32 * pobtainedspace)769 netwib_err netwib_buf_wishspace(netwib_buf *pbuf,
770 netwib_uint32 wantedspace,
771 netwib_data *pdata,
772 netwib_uint32 *pobtainedspace)
773 {
774 netwib_uint32 leftsize;
775
776 /* simple case */
777 if (pbuf == NULL) {
778 /* it's not possible to obtain info if this pointer is NULL */
779 return(NETWIB_ERR_PANULLPTR);
780 }
781 if (pbuf->totalptr == NETWIB_PRIV_BUF_PTR_CLOSED) {
782 return(NETWIB_ERR_LOOBJUSECLOSED);
783 }
784 #if NETWIB_DEBUG_LEAK==1
785 netwib_er(netwib_debug_leak_valid_buf(pbuf->totalptr,
786 netwib__priv_buf_get_leakid(pbuf)));
787 #endif
788
789 leftsize = pbuf->totalsize - pbuf->endoffset;
790 if (wantedspace <= leftsize) {
791 /* sufficient space */
792 if (pdata != NULL) {
793 *pdata = pbuf->totalptr + pbuf->endoffset;
794 }
795 if (pobtainedspace != NULL) *pobtainedspace = leftsize;
796 return(NETWIB_ERR_OK);
797 }
798
799 /* slide if possible */
800 if (netwib__priv_buf_canslide(pbuf)) {
801 netwib__priv_buf_slide(pbuf);
802 }
803
804 if (!netwib__priv_buf_cangrow(pbuf)) {
805 /* cannot realloc, so return current size */
806 if (pdata != NULL) {
807 *pdata = pbuf->totalptr + pbuf->endoffset;
808 }
809 if (pobtainedspace != NULL) *pobtainedspace = leftsize;
810 return(NETWIB_ERR_OK);
811 }
812
813 /* realloc */
814 netwib_er(netwib_priv_buf_realloc(wantedspace - leftsize, pbuf));
815
816 if (pdata != NULL) {
817 *pdata = pbuf->totalptr + pbuf->endoffset;
818 }
819 if (pobtainedspace != NULL) {
820 *pobtainedspace = pbuf->totalsize - pbuf->endoffset;
821 }
822
823 return(NETWIB_ERR_OK);
824 }
825
826 /*-------------------------------------------------------------*/
netwib_buf_cmp(netwib_constbuf * pbuf1,netwib_constbuf * pbuf2,netwib_cmp * pcmp)827 netwib_err netwib_buf_cmp(netwib_constbuf *pbuf1,
828 netwib_constbuf *pbuf2,
829 netwib_cmp *pcmp)
830 {
831 netwib_uint32 data1size, data2size, commonsize;
832 netwib_cmp cmp=NETWIB_CMP_LT;
833 int reti;
834
835 /* parameter verification */
836 if (pbuf1 != NULL) {
837 if (pbuf1->totalptr == NETWIB_PRIV_BUF_PTR_CLOSED) {
838 return(NETWIB_ERR_LOOBJUSECLOSED);
839 }
840 #if NETWIB_DEBUG_LEAK==1
841 netwib_er(netwib_debug_leak_valid_buf(pbuf1->totalptr,
842 netwib__priv_buf_get_leakid(pbuf1)));
843 #endif
844 }
845 if (pbuf2 != NULL) {
846 if (pbuf2->totalptr == NETWIB_PRIV_BUF_PTR_CLOSED) {
847 return(NETWIB_ERR_LOOBJUSECLOSED);
848 }
849 #if NETWIB_DEBUG_LEAK==1
850 netwib_er(netwib_debug_leak_valid_buf(pbuf2->totalptr,
851 netwib__priv_buf_get_leakid(pbuf2)));
852 #endif
853 }
854
855 data1size = netwib__buf_ref_data_sizenull(pbuf1);
856 data2size = netwib__buf_ref_data_sizenull(pbuf2);
857 if (data1size == 0 && data2size == 0) {
858 cmp = NETWIB_CMP_EQ;
859 } else if (data1size == 0) {
860 cmp = NETWIB_CMP_LT;
861 } else if (data2size == 0) {
862 cmp = NETWIB_CMP_GT;
863 } else {
864 commonsize = (data1size<data2size)?data1size:data2size;
865 reti = netwib_c_memcmp(pbuf1->totalptr+pbuf1->beginoffset,
866 pbuf2->totalptr+pbuf2->beginoffset, commonsize);
867 if (reti == 0) {
868 if (data1size == data2size) {
869 cmp = NETWIB_CMP_EQ;
870 } else {
871 cmp = (data1size<data2size)?NETWIB_CMP_LT:NETWIB_CMP_GT;
872 }
873 } else if (reti < 0) {
874 cmp = NETWIB_CMP_LT;
875 } else {
876 cmp = NETWIB_CMP_GT;
877 }
878 }
879
880 if (pcmp != NULL) *pcmp = cmp;
881 return(NETWIB_ERR_OK);
882 }
883
884 /*-------------------------------------------------------------*/
netwib_buf_casecmp(netwib_constbuf * pbuf1,netwib_constbuf * pbuf2,netwib_cmp * pcmp)885 netwib_err netwib_buf_casecmp(netwib_constbuf *pbuf1,
886 netwib_constbuf *pbuf2,
887 netwib_cmp *pcmp)
888 {
889 netwib_uint32 data1size, data2size, commonsize;
890 netwib_cmp cmp=NETWIB_CMP_LT;
891 int reti;
892
893 /* parameter verification */
894 if (pbuf1 != NULL) {
895 if (pbuf1->totalptr == NETWIB_PRIV_BUF_PTR_CLOSED) {
896 return(NETWIB_ERR_LOOBJUSECLOSED);
897 }
898 #if NETWIB_DEBUG_LEAK==1
899 netwib_er(netwib_debug_leak_valid_buf(pbuf1->totalptr,
900 netwib__priv_buf_get_leakid(pbuf1)));
901 #endif
902 }
903 if (pbuf2 != NULL) {
904 if (pbuf2->totalptr == NETWIB_PRIV_BUF_PTR_CLOSED) {
905 return(NETWIB_ERR_LOOBJUSECLOSED);
906 }
907 #if NETWIB_DEBUG_LEAK==1
908 netwib_er(netwib_debug_leak_valid_buf(pbuf2->totalptr,
909 netwib__priv_buf_get_leakid(pbuf2)));
910 #endif
911 }
912
913 data1size = netwib__buf_ref_data_sizenull(pbuf1);
914 data2size = netwib__buf_ref_data_sizenull(pbuf2);
915 if (data1size == 0 && data2size == 0) {
916 cmp = NETWIB_CMP_EQ;
917 } else if (data1size == 0) {
918 cmp = NETWIB_CMP_LT;
919 } else if (data2size == 0) {
920 cmp = NETWIB_CMP_GT;
921 } else {
922 commonsize = (data1size<data2size)?data1size:data2size;
923 reti = netwib_c_memcasecmp(pbuf1->totalptr+pbuf1->beginoffset,
924 pbuf2->totalptr+pbuf2->beginoffset, commonsize);
925 if (reti == 0) {
926 if (data1size == data2size) {
927 cmp = NETWIB_CMP_EQ;
928 } else {
929 cmp = (data1size<data2size)?NETWIB_CMP_LT:NETWIB_CMP_GT;
930 }
931 } else if (reti < 0) {
932 cmp = NETWIB_CMP_LT;
933 } else {
934 cmp = NETWIB_CMP_GT;
935 }
936 }
937
938 if (pcmp != NULL) *pcmp = cmp;
939 return(NETWIB_ERR_OK);
940 }
941
942 /*-------------------------------------------------------------*/
netwib_buf_cmp_string(netwib_constbuf * pbuf1,netwib_conststring string2,netwib_cmp * pcmp)943 netwib_err netwib_buf_cmp_string(netwib_constbuf *pbuf1,
944 netwib_conststring string2,
945 netwib_cmp *pcmp)
946 {
947 netwib_conststring ps;
948 netwib_data data;
949 netwib_uint32 datasize;
950 netwib_char c1, c2=0;
951 netwib_cmp cmp=NETWIB_CMP_LT;
952
953 /* parameter verification */
954 if (pbuf1 != NULL) {
955 if (pbuf1->totalptr == NETWIB_PRIV_BUF_PTR_CLOSED) {
956 return(NETWIB_ERR_LOOBJUSECLOSED);
957 }
958 #if NETWIB_DEBUG_LEAK==1
959 netwib_er(netwib_debug_leak_valid_buf(pbuf1->totalptr,
960 netwib__priv_buf_get_leakid(pbuf1)));
961 #endif
962 }
963
964 datasize = netwib__buf_ref_data_sizenull(pbuf1);
965 data = datasize?netwib__buf_ref_data_ptr(pbuf1):NULL;
966 ps = string2;
967
968 while (NETWIB_TRUE) {
969 if (string2 == NULL) {
970 c2 = '\0';
971 } else {
972 c2 = *ps++;
973 }
974 if (c2 == '\0') {
975 if (datasize == 0) {
976 cmp = NETWIB_CMP_EQ;
977 } else {
978 cmp = NETWIB_CMP_GT;
979 }
980 break;
981 }
982 if (datasize == 0) {
983 cmp = NETWIB_CMP_LT;
984 break;
985 }
986 c1 = *data++;
987 datasize--;
988 if (c1 > c2) {
989 cmp = NETWIB_CMP_GT;
990 break;
991 } else if (c1 < c2) {
992 cmp = NETWIB_CMP_LT;
993 break;
994 }
995 }
996
997 if (pcmp != NULL) *pcmp = cmp;
998 return(NETWIB_ERR_OK);
999 }
1000
1001 /*-------------------------------------------------------------*/
netwib_buf_casecmp_string(netwib_constbuf * pbuf1,netwib_conststring string2,netwib_cmp * pcmp)1002 netwib_err netwib_buf_casecmp_string(netwib_constbuf *pbuf1,
1003 netwib_conststring string2,
1004 netwib_cmp *pcmp)
1005 {
1006 netwib_conststring ps;
1007 netwib_data data;
1008 netwib_uint32 datasize;
1009 netwib_char c1, c2=0;
1010 netwib_cmp cmp=NETWIB_CMP_LT;
1011
1012 /* parameter verification */
1013 if (pbuf1 != NULL) {
1014 if (pbuf1->totalptr == NETWIB_PRIV_BUF_PTR_CLOSED) {
1015 return(NETWIB_ERR_LOOBJUSECLOSED);
1016 }
1017 #if NETWIB_DEBUG_LEAK==1
1018 netwib_er(netwib_debug_leak_valid_buf(pbuf1->totalptr,
1019 netwib__priv_buf_get_leakid(pbuf1)));
1020 #endif
1021 }
1022
1023 datasize = netwib__buf_ref_data_sizenull(pbuf1);
1024 data = datasize?netwib__buf_ref_data_ptr(pbuf1):NULL;
1025 ps = string2;
1026
1027 while (NETWIB_TRUE) {
1028 if (string2 == NULL) {
1029 c2 = '\0';
1030 } else {
1031 c2 = *ps++;
1032 }
1033 if (c2 == '\0') {
1034 if (datasize == 0) {
1035 cmp = NETWIB_CMP_EQ;
1036 } else {
1037 cmp = NETWIB_CMP_GT;
1038 }
1039 break;
1040 }
1041 if (datasize == 0) {
1042 cmp = NETWIB_CMP_LT;
1043 break;
1044 }
1045 c1 = *data++;
1046 datasize--;
1047 netwib_c2_lower(c2);
1048 netwib_c2_lower(c1);
1049 if (c1 > c2) {
1050 cmp = NETWIB_CMP_GT;
1051 break;
1052 } else if (c1 < c2) {
1053 cmp = NETWIB_CMP_LT;
1054 break;
1055 }
1056 }
1057
1058 if (pcmp != NULL) *pcmp = cmp;
1059 return(NETWIB_ERR_OK);
1060 }
1061
1062 /*-------------------------------------------------------------*/
netwib_buf_close(netwib_buf * pbuf)1063 netwib_err netwib_buf_close(netwib_buf *pbuf)
1064 {
1065 /* simple case */
1066 if (pbuf == NULL) {
1067 /* nothing to close */
1068 return(NETWIB_ERR_OK);
1069 }
1070
1071 if (pbuf->totalptr == NETWIB_PRIV_BUF_PTR_CLOSED) {
1072 return(NETWIB_ERR_LOOBJCLOSEALREADYCLOSED);
1073 }
1074
1075 netwib_er(netwib_priv_buf_wipe(pbuf));
1076
1077 if (pbuf->flags&NETWIB_BUF_FLAGS_ALLOC) {
1078 #if NETWIB_DEBUG_LEAK==1
1079 netwib_er(netwib_debug_leak_del_buf(pbuf->totalptr,
1080 netwib__priv_buf_get_leakid(pbuf)));
1081 #endif
1082 netwib_er(netwib_ptr_free((netwib_ptr*)&pbuf->totalptr));
1083 }
1084
1085 pbuf->totalptr = NETWIB_PRIV_BUF_PTR_CLOSED;
1086
1087 return(NETWIB_ERR_OK);
1088 }
1089
1090