1 /* ncbibs.c
2 * ===========================================================================
3 *
4 * PUBLIC DOMAIN NOTICE
5 * National Center for Biotechnology Information
6 *
7 * This software/database is a "United States Government Work" under the
8 * terms of the United States Copyright Act. It was written as part of
9 * the author's official duties as a United States Government employee and
10 * thus cannot be copyrighted. This software/database is freely available
11 * to the public for use. The National Library of Medicine and the U.S.
12 * Government have not placed any restriction on its use or reproduction.
13 *
14 * Although all reasonable efforts have been taken to ensure the accuracy
15 * and reliability of the software and data, the NLM and the U.S.
16 * Government do not and cannot warrant the performance or results that
17 * may be obtained by using this software or data. The NLM and the U.S.
18 * Government disclaim all warranties, express or implied, including
19 * warranties of performance, merchantability or fitness for any particular
20 * purpose.
21 *
22 * Please cite the author in any work or product based on this material.
23 *
24 * ===========================================================================
25 *
26 * File Name: ncbibs.c
27 *
28 * Author: Jim Ostell
29 *
30 * Version Creation Date: 3/4/91
31 *
32 * $Revision: 6.8 $
33 *
34 * File Description:
35 * ByteStore functions
36 * NOTE: increasing BS_MAXALLOC will require changing len, and
37 * len_avail to Int4 (ncbibs.h)
38 *
39 * This version needs the following enhancements:
40 * 1) a BSCompact function to pack a fragmented ByteStore
41 * 2) use made of MIN_BSALLOC to make all allocated space at
42 * least MIN_BSALLOC long, so it would be possible to have len_avail
43 * bigger than len at internal BSUnits as well as at the end. This
44 * will make insertion and appending of small amounts much more
45 * efficient.
46 *
47 * Modifications:
48 * --------------------------------------------------------------------------
49 * Date Name Description of modification
50 * ------- ---------- -----------------------------------------------------
51 *
52 * ==========================================================================
53 */
54
55 #include <ncbi.h>
56 #include <ncbiwin.h>
57
58 /* maximum size allocated for BSUnit.str */
59 #define MAX_BSALLOC 32700
60 /* minimum size block to allocate except on new */
61 #define MIN_BSALLOC 1024
62
63 #ifdef MSC_VIRT
64 extern Nlm_Boolean wrote_to_handle; /* needed by Microsoft DOS Virtual mem */
65 #undef MAX_BSALLOC /* bad with big blocks */
66 #define MAX_BSALLOC 10000
67 #endif
68
69 /*****************************************************************************
70 *
71 * Pointer Nlm_BSMerge(bsp, dest)
72 * if dest == NULL, allocates storage for merge and returns pointer to it
73 *
74 *****************************************************************************/
Nlm_BSMerge(Nlm_ByteStorePtr bsp,Nlm_VoidPtr dest)75 NLM_EXTERN Nlm_VoidPtr LIBCALL Nlm_BSMerge (Nlm_ByteStorePtr bsp, Nlm_VoidPtr dest)
76
77 {
78 Nlm_BytePtr tmp, from;
79 Nlm_BSUnitPtr bsup;
80 size_t size;
81
82 if (bsp == NULL)
83 return NULL;
84
85 size = Nlm_BSLen(bsp) + 1;
86 if (size > SIZE_MAX) {
87 ErrPostEx(SEV_ERROR, 0, 0, "size[%u] is bigger then SIZE_MAX[%u]",
88 size, SIZE_MAX);
89 /* should post an error here */
90 return NULL;
91 }
92
93 if (dest == NULL) /* allocate storage with room for null at end */
94 {
95 dest = Nlm_MemNew(size);
96 if (dest == NULL) return dest;
97 }
98
99 tmp = (Nlm_BytePtr) dest;
100 bsup = bsp->chain;
101
102 while (bsup != NULL)
103 {
104 from = (Nlm_BytePtr) Nlm_HandLock(bsup->str);
105 Nlm_MemCopy(tmp, from, bsup->len);
106 Nlm_HandUnlock(bsup->str);
107 tmp += bsup->len;
108 bsup = bsup->next;
109 }
110
111 return dest;
112 }
113
114 /*****************************************************************************
115 *
116 * ByteStorePtr Nlm_BSNew(len)
117 * creates a big enough bytestore for len
118 *
119 *****************************************************************************/
Nlm_BSNew(Nlm_Int4 len)120 NLM_EXTERN Nlm_ByteStorePtr LIBCALL Nlm_BSNew (Nlm_Int4 len)
121
122 {
123 Nlm_ByteStorePtr bsp;
124 Nlm_Int4 added;
125
126 bsp = (Nlm_ByteStorePtr) Nlm_MemNew(sizeof(ByteStore));
127 if (bsp == NULL)
128 return NULL;
129
130 added = Nlm_BSAdd(bsp, len, FALSE);
131 if (added < len)
132 bsp = Nlm_BSFree(bsp);
133 return bsp;
134 }
135
136 /*****************************************************************************
137 *
138 * Int4 BSAdd(bsp, len, use_min_size)
139 * adds len bytes BEFORE current bsp->seekptr
140 * bsp->seekptr returned pointing at first added byte
141 * returns bytes added
142 * if (use_min_size) then does not add anything smaller than MIN_BSALLOC
143 *
144 *****************************************************************************/
Nlm_BSAdd(Nlm_ByteStorePtr bsp,Nlm_Int4 len,Nlm_Boolean use_min_size)145 NLM_EXTERN Nlm_Int4 LIBCALL Nlm_BSAdd (Nlm_ByteStorePtr bsp, Nlm_Int4 len, Nlm_Boolean use_min_size)
146
147 {
148 Nlm_BSUnitPtr bsup, /* current bsunit */
149 ccbsup, /* bsp->curchain */
150 lastbsup, /* bsunit after added section */
151 prevbsup; /* bsunit before added section */
152 Nlm_BytePtr to, from;
153 Nlm_Int4 added = 0,
154 tlen;
155 Nlm_Handle thand;
156
157 if ((bsp == NULL) || (len == 0))
158 return added;
159
160 lastbsup = NULL;
161 prevbsup = NULL;
162 ccbsup = bsp->curchain;
163
164 if (bsp->chain != NULL) /* add or insert in exisiting chain */
165 {
166 if (bsp->seekptr == bsp->chain_offset) /* before start of block */
167 {
168 lastbsup = ccbsup; /* it comes after */
169 if (bsp->seekptr != 0) /* something before it */
170 {
171 prevbsup = bsp->chain;
172 while (prevbsup->next != ccbsup)
173 prevbsup = prevbsup->next;
174 }
175 } /* at very end of data */
176 else if (bsp->seekptr == (bsp->chain_offset + ccbsup->len))
177 {
178 prevbsup = ccbsup; /* JK */
179 } /* after all blocks */
180 else if (bsp->seekptr >= (bsp->chain_offset + ccbsup->len_avail))
181 {
182 prevbsup = ccbsup;
183 }
184 else /* split a bsunit */
185 {
186 bsup = (Nlm_BSUnitPtr) Nlm_MemNew(sizeof(Nlm_BSUnit));
187 if (bsup == NULL) return added;
188 if (bsp->chain_offset != 0) /* not first BSUnit */
189 {
190 prevbsup = bsp->chain;
191 while (prevbsup->next != ccbsup)
192 prevbsup = prevbsup->next;
193 prevbsup->next = bsup; /* insert new bsunit */
194 }
195 else
196 bsp->chain = bsup;
197 bsup->next = ccbsup;
198 tlen = bsp->seekptr - bsp->chain_offset; /* len of first half */
199 bsup->str = Nlm_HandNew((size_t) tlen);
200 if (bsup->str == NULL) return added;
201 bsup->len = (Nlm_Int2) tlen;
202 bsup->len_avail = (Nlm_Int2) tlen;
203 to = (Nlm_BytePtr) Nlm_HandLock(bsup->str);
204 thand = ccbsup->str;
205 from = (Nlm_BytePtr) Nlm_HandLock(thand);
206 Nlm_MemCopy(to, from, (size_t) tlen);
207 #ifdef MSC_VIRT
208 wrote_to_handle = TRUE;
209 #endif
210 Nlm_HandUnlock(bsup->str);
211 from += tlen; /* point past copied region */
212 tlen = ccbsup->len - tlen; /* the last half */
213 ccbsup->len = (Nlm_Int2) tlen;
214 ccbsup->len_avail = (Nlm_Int2) tlen;
215 ccbsup->str = Nlm_HandNew((size_t) tlen);
216 if (ccbsup->str == NULL) return added;
217 to = (Nlm_BytePtr) Nlm_HandLock(ccbsup->str);
218 Nlm_MemCopy(to, from, (size_t) tlen);
219 #ifdef MSC_VIRT
220 wrote_to_handle = TRUE;
221 #endif
222 Nlm_HandUnlock(ccbsup->str);
223 Nlm_HandUnlock(thand);
224 Nlm_HandFree(thand);
225 prevbsup = bsup;
226 lastbsup = ccbsup;
227 }
228 }
229
230 ccbsup = NULL;
231 bsup = NULL;
232 while (len)
233 {
234 bsup = (Nlm_BSUnitPtr) Nlm_MemNew(sizeof(Nlm_BSUnit));
235 if (bsup == NULL)
236 return added;
237 if (len < MAX_BSALLOC)
238
239 {
240 if ((use_min_size) && (len < MIN_BSALLOC))
241 len = MIN_BSALLOC;
242 tlen = len;
243 }
244 else
245 tlen = MAX_BSALLOC;
246 bsup->str = Nlm_HandNew((size_t)tlen);
247 if (bsup->str == NULL)
248 {
249 Nlm_MemFree(bsup);
250 return added;
251 }
252 bsup->len_avail = (Nlm_Int2) tlen;
253 if (prevbsup == NULL)
254 bsp->chain = bsup;
255 else
256 prevbsup->next = bsup;
257 if (ccbsup == NULL)
258 ccbsup = bsup; /* current position */
259 prevbsup = bsup;
260 len -= tlen;
261 added += tlen;
262 }
263 if (bsup != NULL)
264 bsup->next = lastbsup;
265 bsp->curchain = ccbsup;
266 bsp->chain_offset = bsp->seekptr; /* added block starts at seekptr */
267 return added;
268 }
269
270 /*****************************************************************************
271 *
272 * Int4 BSDelete(bsp, len)
273 * deletes len bytes starting at current bsp->seekptr
274 * returns bytes deleted
275 *
276 *****************************************************************************/
Nlm_BSDelete(Nlm_ByteStorePtr bsp,Nlm_Int4 len)277 NLM_EXTERN Nlm_Int4 LIBCALL Nlm_BSDelete (Nlm_ByteStorePtr bsp, Nlm_Int4 len)
278
279 {
280 Nlm_BSUnitPtr bsup, /* current bsunit */
281 ccbsup, /* bsp->curchain */
282 nextbsup, /* bsunit after added section */
283 prevbsup; /* bsunit before added section */
284 Nlm_BytePtr to, from;
285 Nlm_Int4 added = 0,
286 offset,
287 tlen,
288 start,
289 save;
290 Nlm_Handle thand;
291
292 if ((bsp == NULL) || (len == 0) || (bsp->chain == NULL) ||
293 (bsp->seekptr >= bsp->totlen))
294 return added;
295
296 if ((bsp->seekptr + len) > bsp->totlen) /* deleting too much */
297 len = bsp->totlen - bsp->seekptr;
298
299 nextbsup = NULL;
300 ccbsup = bsp->curchain;
301 start = bsp->chain_offset;
302 offset = bsp->seekptr - bsp->chain_offset;
303 if (offset) /* will leave part of first bsunit */
304 prevbsup = ccbsup;
305 else if (bsp->chain_offset != 0) /* something before this bsunit */
306 {
307 prevbsup = bsp->chain;
308 while (prevbsup->next != ccbsup)
309 prevbsup = prevbsup->next;
310 }
311 else
312 prevbsup = NULL; /* will remove beginning of first bsunit */
313
314 bsup = ccbsup;
315 while (len)
316 {
317 nextbsup = bsup->next;
318 tlen = bsup->len - offset;
319 if (tlen > len)
320 tlen = len; /* will remove tlen bytes from this BSUnit*/
321 save = bsup->len - tlen;
322 if (save) /* some bytes left after delete */
323 {
324 thand = bsup->str;
325 bsup->str = Nlm_HandNew((size_t) save);
326 if (bsup->str == NULL) return added;
327 bsup->len = (Nlm_Int2) save;
328 bsup->len_avail = (Nlm_Int2) save;
329 to = (Nlm_BytePtr) Nlm_HandLock(bsup->str);
330 from = (Nlm_BytePtr) Nlm_HandLock(thand);
331 if (offset) /* get the beginning */
332 Nlm_MemCopy(to, from, (size_t) offset);
333 save -= offset;
334 if (save) /* save end */
335 Nlm_MemCopy((to + offset), (from + (offset + tlen)), (size_t)save);
336 Nlm_HandUnlock(thand);
337 Nlm_HandFree(thand);
338 #ifdef MSC_VIRT
339 wrote_to_handle = TRUE;
340 #endif
341 Nlm_HandUnlock(bsup->str);
342 if (tlen < len)
343 bsup = nextbsup;
344 }
345 else /* delete the whole thing */
346 {
347 Nlm_HandFree(bsup->str);
348 Nlm_MemFree(bsup);
349 bsup = nextbsup;
350 }
351 offset = 0;
352 len -= tlen;
353 added += tlen;
354 }
355 if ((bsup != prevbsup) || /* break in chain, rejoin it */
356 ((bsup == NULL) && (prevbsup == NULL))) /* chain gone */
357 {
358 if (prevbsup == NULL)
359 bsp->chain = bsup;
360 else
361 prevbsup->next = bsup;
362 }
363 bsp->curchain = bsup;
364 bsp->totlen -= added;
365 if (bsp->totlen)
366 {
367 offset = bsp->seekptr;
368 start = 0;
369 bsup = bsp->chain;
370 while (offset >= (start + bsup->len_avail))
371 {
372 if (bsup->next == NULL) /* EOF */
373 offset = 0; /* stop loop */
374 else
375 {
376 start += bsup->len;
377 bsup = bsup->next;
378 }
379 }
380 bsp->curchain = bsup;
381 bsp->chain_offset = start;
382 }
383 else
384 {
385 bsp->chain_offset = 0;
386 bsp->curchain = bsp->chain;
387 }
388 return added;
389 }
390
391 /*****************************************************************************
392 *
393 * Nlm_Int4 Nlm_BSTell(bsp)
394 *
395 *****************************************************************************/
Nlm_BSTell(Nlm_ByteStorePtr bsp)396 NLM_EXTERN Nlm_Int4 LIBCALL Nlm_BSTell (Nlm_ByteStorePtr bsp)
397
398 {
399 if (bsp == NULL)
400 return 0L;
401
402 return bsp->seekptr;
403 }
404
405 /*****************************************************************************
406 *
407 * Int2 Nlm_BSSeek(bsp, offset, origin)
408 * seeks as fseek()
409 * trys to lock a BSUnit at that seek position
410 *
411 *****************************************************************************/
Nlm_BSSeek(Nlm_ByteStorePtr bsp,Nlm_Int4 offset,Nlm_Int2 origin)412 NLM_EXTERN Nlm_Int2 LIBCALL Nlm_BSSeek (Nlm_ByteStorePtr bsp, Nlm_Int4 offset, Nlm_Int2 origin)
413
414 {
415 Nlm_Int4 sp, start = 0;
416 Nlm_BSUnitPtr bsup;
417 Nlm_Boolean done;
418
419 if (bsp == NULL)
420 return 1;
421 if (bsp->chain == NULL)
422 return 1;
423
424 sp = bsp->seekptr;
425
426 switch (origin)
427 {
428 case SEEK_SET:
429 if ((offset > bsp->totlen) || (offset < 0))
430 return 1;
431 sp = offset;
432 break;
433 case SEEK_CUR:
434 if (((sp + offset) > bsp->totlen) ||
435 ((sp + offset) < 0 ))
436 return 1;
437 sp += offset;
438 break;
439 case SEEK_END:
440 if ((ABS(offset) > bsp->totlen) || (offset > 0))
441 return 1;
442 sp = bsp->totlen + offset;
443 break;
444 default:
445 return 1;
446 }
447
448 if (sp == bsp->seekptr) /* already in right position */
449 return 0;
450
451 bsp->seekptr = sp;
452 /* if a valid seek, lock the right BSUnit */
453 bsup = bsp->curchain;
454
455 if (sp == bsp->totlen) /* seek to EOF */
456 {
457 if (sp > (bsp->chain_offset + bsup->len_avail))
458 {
459 start = bsp->chain_offset;
460 while (sp > (start + bsup->len_avail))
461 {
462 start += bsup->len;
463 bsup = bsup->next;
464 }
465 }
466 }
467 else if ((sp < bsp->chain_offset) ||
468 (sp >= (bsp->chain_offset + bsup->len)))
469 {
470 if (sp < bsp->chain_offset)
471 {
472 bsup = bsp->chain;
473 start = 0;
474 }
475 else
476 {
477 start = bsp->chain_offset + bsup->len;
478 bsup = bsup->next;
479 }
480 done = FALSE;
481 while (! done)
482 {
483 if ((start + bsup->len) > sp)
484 done = TRUE;
485 else
486 {
487 start += bsup->len;
488 bsup = bsup->next;
489 }
490 }
491 }
492 if (bsup != bsp->curchain)
493 {
494 bsp->chain_offset = start;
495 bsp->curchain = bsup;
496 }
497 return 0;
498 }
499 /*****************************************************************************
500 *
501 * Int4 Nlm_BSLen(bsp)
502 * gives cumulative length of strings in store (not counting \0)
503 *
504 *****************************************************************************/
Nlm_BSLen(Nlm_ByteStorePtr bsp)505 NLM_EXTERN Nlm_Int4 LIBCALL Nlm_BSLen (Nlm_ByteStorePtr bsp)
506
507 {
508 if (bsp == NULL)
509 return 0L;
510
511 return bsp->totlen;
512 }
513
514 /*****************************************************************************
515 *
516 * Int2 BSPutByte(bsp, value)
517 * - returns value on success, EOF on failure
518 * - BSPutByte(bsp, EOF) truncates at seekptr
519 *
520 *****************************************************************************/
Nlm_BSPutByte(Nlm_ByteStorePtr bsp,Nlm_Int2 value)521 NLM_EXTERN Nlm_Int2 LIBCALL Nlm_BSPutByte (Nlm_ByteStorePtr bsp, Nlm_Int2 value)
522
523 {
524 Nlm_Uint1 b;
525 if (value == EOF)
526 Nlm_BSDelete(bsp, INT4_MAX);
527 else {
528 b = (Nlm_Uint1) value;
529 if (Nlm_BSWrite(bsp, (Nlm_VoidPtr)&b, 1) == 0)
530 return EOF;
531 }
532 return value;
533 }
534
535 /*****************************************************************************
536 *
537 * Int4 BSWrite(bsp, ptr, len)
538 * returns bytes written from ptr to bsp
539 * writes from current seekptr position
540 * seekptr left pointing after last byte written
541 * allocates storage if needed
542 * writes over any data already there
543 *
544 *****************************************************************************/
Nlm_BSWrite(Nlm_ByteStorePtr bsp,Nlm_VoidPtr ptr,Nlm_Int4 len)545 NLM_EXTERN Nlm_Int4 LIBCALL Nlm_BSWrite (Nlm_ByteStorePtr bsp, Nlm_VoidPtr ptr, Nlm_Int4 len)
546
547 {
548 Nlm_BytePtr from, to;
549 Nlm_BSUnitPtr bsup;
550 Nlm_Int4 tlen, added = 0, offset, start, diff;
551
552 if ((bsp == NULL) || (len <= 0))
553 return added;
554
555 bsup = bsp->curchain;
556 from = (Nlm_BytePtr) ptr;
557 offset = bsp->seekptr - bsp->chain_offset;
558 start = bsp->chain_offset;
559
560
561
562 while (len)
563 {
564
565 if (bsup == NULL)
566 tlen = 0;
567 else
568 tlen = bsup->len_avail - offset;
569 if (len < tlen)
570 tlen = len;
571 if (! tlen) /* out of space */
572 {
573
574 if (Nlm_BSAdd(bsp, len, TRUE) < len)
575 return added;
576 bsup = bsp->curchain;
577 offset = bsp->seekptr - bsp->chain_offset;
578 tlen = bsup->len_avail;
579
580 if (len < tlen)
581
582 tlen = len;
583 }
584 else
585 {
586 bsp->chain_offset = start;
587 bsp->curchain = bsup;
588 }
589 to = (Nlm_BytePtr)Nlm_HandLock(bsup->str) + offset;
590 Nlm_MemCopy(to, from, (size_t) tlen);
591 #ifdef MSC_VIRT
592 wrote_to_handle = TRUE;
593 #endif
594 Nlm_HandUnlock(bsup->str);
595 if (bsup->len < (Nlm_Int2)(tlen + offset)) /* added more to this bsunit */
596 {
597 diff = (tlen + offset) - bsup->len;
598 bsp->totlen += diff;
599 bsup->len += (Nlm_Int2) diff;
600
601 }
602 offset = 0; /* only offset on first one */
603 len -= tlen;
604 bsp->seekptr += tlen;
605 start += bsup->len;
606 added += tlen;
607 from += tlen;
608 if (len)
609 bsup = bsup->next;
610 }
611 /* pointing past end of this BSunit */
612
613 if ((bsp->seekptr - bsp->chain_offset) >= bsup->len_avail)
614 {
615 if (bsup->next != NULL) /* not end of space */
616 {
617 bsp->curchain = bsup->next;
618 bsp->chain_offset += bsup->len; /* should = len_avail */
619 }
620 }
621 return added;
622 }
623 /*****************************************************************************
624 *
625 * Int4 BSRead(bsp, ptr, len)
626 * returns bytes read from bsp to ptr
627 * reads from current seekptr position
628 * seekptr left pointing after last byte read
629 *
630 *****************************************************************************/
Nlm_BSRead(Nlm_ByteStorePtr bsp,Nlm_VoidPtr ptr,Nlm_Int4 len)631 NLM_EXTERN Nlm_Int4 LIBCALL Nlm_BSRead (Nlm_ByteStorePtr bsp, Nlm_VoidPtr ptr, Nlm_Int4 len)
632
633 {
634 Nlm_BytePtr from, to;
635 Nlm_BSUnitPtr bsup;
636 Nlm_Int4 tlen, added = 0, offset, start;
637
638 if ((bsp == NULL) || (len <= 0))
639 return added;
640
641 bsup = bsp->curchain;
642 to = (Nlm_BytePtr) ptr;
643 offset = bsp->seekptr - bsp->chain_offset;
644 start = bsp->chain_offset;
645
646 while (len)
647 {
648 if (bsup == NULL)
649 return added;
650 tlen = bsup->len - offset;
651 if (len < tlen)
652 tlen = len;
653 if (! tlen) /* out of data */
654 return added;
655 bsp->chain_offset = start;
656 from = (Nlm_BytePtr)Nlm_HandLock(bsup->str) + offset;
657 Nlm_MemCopy(to, from, (size_t) tlen);
658 Nlm_HandUnlock(bsup->str);
659 offset = 0; /* only offset on first one */
660 len -= tlen;
661 bsp->seekptr += tlen;
662 bsp->curchain = bsup;
663 start += bsup->len;
664 added += tlen;
665 to += tlen;
666 if (len)
667 bsup = bsup->next;
668 } /*** end of this bsunit? **/
669 if ((bsp->seekptr - bsp->chain_offset) == bsup->len)
670 {
671 if (bsup->next != NULL) /* not EOF */
672 {
673 bsp->curchain = bsup->next;
674 bsp->chain_offset += bsup->len;
675 }
676 }
677 return added;
678 }
679
680 /*****************************************************************************
681 *
682 * Int2 BSGetByte(bsp)
683 * reads a byte and increments the seekptr
684 * returns EOF on End-Of-BS or error
685 *
686 *****************************************************************************/
Nlm_BSGetByte(Nlm_ByteStorePtr bsp)687 NLM_EXTERN Nlm_Int2 LIBCALL Nlm_BSGetByte (Nlm_ByteStorePtr bsp)
688
689 {
690 Nlm_Int2 retval;
691 Nlm_BytePtr ptr;
692 Nlm_Int4 diff;
693 Nlm_BSUnitPtr bsup;
694
695 if ((bsp == NULL) || (bsp->totlen == 0) || (bsp->seekptr == bsp->totlen))
696 return EOF; /* EOF */
697
698 diff = bsp->seekptr - bsp->chain_offset;
699 bsup = bsp->curchain;
700 ptr = (Nlm_BytePtr) Nlm_HandLock(bsup->str);
701 retval = (Nlm_Int2) *(ptr + diff);
702 Nlm_HandUnlock(bsup->str);
703
704 bsp->seekptr++;
705 diff++;
706 if (diff == bsup->len)
707 {
708 if (bsp->seekptr != bsp->totlen) /* not EOF */
709 {
710 bsp->curchain = bsup->next;
711 bsp->chain_offset += bsup->len;
712 }
713 }
714 return retval;
715 }
716
717 /*****************************************************************************
718 *
719 * Int4 BSInsert(bsp, ptr, len)
720 * returns bytes written from ptr into bsp
721 * writes from current seekptr position
722 * seekptr left pointing after last byte written
723 * allocates storage if needed
724 * inserts data BEFORE seekptr
725 *
726 *****************************************************************************/
Nlm_BSInsert(Nlm_ByteStorePtr bsp,Nlm_VoidPtr ptr,Nlm_Int4 len)727 NLM_EXTERN Nlm_Int4 LIBCALL Nlm_BSInsert (Nlm_ByteStorePtr bsp, Nlm_VoidPtr ptr, Nlm_Int4 len)
728
729 {
730 Nlm_Int4 added;
731
732 added = Nlm_BSAdd(bsp, len, FALSE);
733 if (added != len)
734 {
735 Nlm_BSDelete(bsp, added);
736 return 0;
737 }
738 added = Nlm_BSWrite(bsp, ptr, len);
739 return added;
740 }
741
742 /*****************************************************************************
743 *
744 * Int4 BSInsertFromBS(bsp, bsp2, len)
745 * returns bytes written from bsp2 into bsp
746 * reads from bsp2 starting from current seek position
747 * writes from current seekptr position
748 * seekptr left pointing after last byte written
749 * allocates storage if needed
750 * inserts data BEFORE seekptr
751 *
752 *****************************************************************************/
Nlm_BSInsertFromBS(Nlm_ByteStorePtr bsp,Nlm_ByteStorePtr bsp2,Nlm_Int4 len)753 NLM_EXTERN Nlm_Int4 LIBCALL Nlm_BSInsertFromBS (Nlm_ByteStorePtr bsp, Nlm_ByteStorePtr bsp2, Nlm_Int4 len)
754 {
755 Nlm_Int4 added;
756 Nlm_Int2 x;
757
758 added = Nlm_BSAdd(bsp, len, FALSE);
759 if (added != len)
760 {
761 Nlm_BSDelete(bsp, added);
762 return 0;
763 }
764
765 for (added = 0; added < len; added++)
766 {
767 x = Nlm_BSGetByte(bsp2);
768 Nlm_BSPutByte(bsp, x);
769 }
770 return added;
771 }
772
773 /*****************************************************************************
774 *
775 * ByteStorePtr Nlm_BSFree(bsp)
776 *
777 *****************************************************************************/
Nlm_BSFree(Nlm_ByteStorePtr bsp)778 NLM_EXTERN Nlm_ByteStorePtr LIBCALL Nlm_BSFree (Nlm_ByteStorePtr bsp)
779
780 {
781 Nlm_BSUnitPtr bsup, tmp;
782
783 if (bsp == NULL)
784 return NULL;
785
786 bsup = bsp->chain;
787 while (bsup != NULL)
788 {
789 tmp = bsup;
790 bsup = bsup->next;
791 Nlm_HandFree(tmp->str);
792 Nlm_MemFree(tmp);
793 }
794 return (Nlm_ByteStorePtr) Nlm_MemFree(bsp);
795 }
796
797 /*****************************************************************************
798 *
799 * ByteStorePtr Nlm_BSDup(bsp)
800 *
801 *****************************************************************************/
802
803 #define BUFSIZE 256
804
Nlm_BSDup(Nlm_ByteStorePtr source)805 NLM_EXTERN Nlm_ByteStorePtr LIBCALL Nlm_BSDup (Nlm_ByteStorePtr source)
806
807 {
808 Nlm_Byte buf [BUFSIZE + 4];
809 Nlm_Int4 count;
810 Nlm_ByteStorePtr dest;
811 Nlm_Int4 sourceLen;
812 Nlm_Int4 sourceLoc;
813
814 dest = NULL;
815 if (source != NULL) {
816 sourceLen = Nlm_BSLen (source);
817 dest = Nlm_BSNew (sourceLen);
818 /* read the original location */
819 sourceLoc = Nlm_BSTell(source);
820 Nlm_BSSeek(source, 0L, SEEK_SET);
821 if (dest != NULL) {
822 count = MIN (sourceLen, (Nlm_Int4) BUFSIZE);
823 while (count > 0 && sourceLen > 0) {
824 Nlm_BSRead (source, buf, count);
825 Nlm_BSWrite (dest, buf, count);
826 sourceLen -= count;
827 count = MIN (sourceLen, (Nlm_Int4) BUFSIZE);
828 }
829 /* for neatness, make the duplicate point to the
830 same location as the old one */
831 Nlm_BSSeek(dest, sourceLoc, SEEK_SET);
832 }
833 /* restore original location */
834 Nlm_BSSeek(source, sourceLoc, SEEK_SET);
835 }
836 return dest;
837 }
838
839 /*****************************************************************************
840 *
841 * Boolean Nlm_BSEqual (bs1, bs2)
842 *
843 *****************************************************************************/
844
Nlm_BSEqual(Nlm_ByteStorePtr bs1,Nlm_ByteStorePtr bs2)845 NLM_EXTERN Nlm_Boolean LIBCALL Nlm_BSEqual (Nlm_ByteStorePtr bs1, Nlm_ByteStorePtr bs2)
846
847 {
848 Nlm_Byte buf1 [256], buf2 [256];
849 Nlm_Int4 count1, count2, idx;
850
851 if (bs1 == NULL || bs2 == NULL) {
852 if (bs1 == NULL && bs2 == NULL) return TRUE;
853 if (Nlm_BSLen (bs1) == 0 && Nlm_BSLen (bs2) == 0) return TRUE;
854 return FALSE;
855 }
856
857 Nlm_BSSeek (bs1, 0, SEEK_SET);
858 Nlm_BSSeek (bs2, 0, SEEK_SET);
859
860 count1 = Nlm_BSRead (bs1, buf1, sizeof (buf1));
861 count2 = Nlm_BSRead (bs2, buf2, sizeof (buf2));
862
863 while (count1 == count2 && count2 > 0) {
864 for (idx = 0; idx < count1; idx++) {
865 if (buf1 [idx] != buf2 [idx]) return FALSE;
866 }
867
868 count1 = Nlm_BSRead (bs1, buf1, sizeof (buf1));
869 count2 = Nlm_BSRead (bs2, buf2, sizeof (buf2));
870 }
871
872 if (count1 != count2) return FALSE;
873
874 return TRUE;
875 }
876
877
878 /* for copying and swapping of UID lists passed over network to BIG_ENDIAN server */
879
Nlm_BSDupAndSwapUint4(Nlm_ByteStorePtr source)880 NLM_EXTERN Nlm_ByteStorePtr LIBCALL Nlm_BSDupAndSwapUint4 (Nlm_ByteStorePtr source)
881
882 {
883 Nlm_Byte buf [BUFSIZE + 4];
884 Nlm_Int4 count;
885 Nlm_ByteStorePtr dest;
886 Nlm_Int4 sourceLen;
887 Nlm_Int4 sourceLoc;
888 Nlm_Int4 swapLen;
889
890 dest = NULL;
891 if (source != NULL) {
892 sourceLen = Nlm_BSLen (source);
893 dest = Nlm_BSNew (sourceLen);
894 /* read the original location */
895 sourceLoc = Nlm_BSTell(source);
896 Nlm_BSSeek(source, 0L, SEEK_SET);
897 if (dest != NULL) {
898 count = MIN (sourceLen, (Nlm_Int4) BUFSIZE);
899 while (count > 0 && sourceLen > 0) {
900 swapLen = Nlm_BSRead (source, buf, count);
901 swapLen /= 4;
902 /* swap Uint4 if IS_LITTLE_ENDIAN */
903 Nlm_SwapUint4Buff ((Nlm_Uint4Ptr) buf, swapLen);
904 Nlm_BSWrite (dest, buf, count);
905 sourceLen -= count;
906 count = MIN (sourceLen, (Nlm_Int4) BUFSIZE);
907 }
908 /* for neatness, make the duplicate point to the
909 same location as the old one */
910 Nlm_BSSeek(dest, sourceLoc, SEEK_SET);
911 }
912 /* restore original location */
913 Nlm_BSSeek(source, sourceLoc, SEEK_SET);
914 }
915 return dest;
916 }
917
918 /****************************************************************************
919 *
920 * Integer storage utilities
921 * These assume integers are store in BIG_ENDIAN order in the ByteStore
922 * They read and write Uint2 or Uint4 in the NATIVE endian order
923 * All work with UNSIGNED 2 or 4 byte integers
924 * (you should cast to make them signed)
925 * These are just helper functions. They do no internal consistency
926 * checking.
927 * They are primarily to facilitate encoding SEQUENCE OF INTEGER as
928 * OCTET STRING for ASN.1
929 *
930 ****************************************************************************/
931
Nlm_BSGetUint2(Nlm_ByteStorePtr bsp)932 NLM_EXTERN Nlm_Uint2 LIBCALL Nlm_BSGetUint2 (Nlm_ByteStorePtr bsp)
933 {
934 Nlm_Uint2 retval = 0;
935
936 Nlm_BSRead(bsp, (Nlm_VoidPtr)(&retval), (Nlm_Int4)2);
937 Nlm_SwapUint2(retval);
938
939 return retval;
940 }
941
Nlm_BSGetUint4(Nlm_ByteStorePtr bsp)942 NLM_EXTERN Nlm_Uint4 LIBCALL Nlm_BSGetUint4 (Nlm_ByteStorePtr bsp)
943 {
944 Nlm_Uint4 retval = 0;
945
946 Nlm_BSRead(bsp, (Nlm_VoidPtr)(&retval), (Nlm_Int4)4);
947 Nlm_SwapUint4(retval);
948
949 return retval;
950 }
951
Nlm_BSPutUint2(Nlm_ByteStorePtr bsp,Nlm_Uint2 value)952 NLM_EXTERN Nlm_Int2 LIBCALL Nlm_BSPutUint2 (Nlm_ByteStorePtr bsp, Nlm_Uint2 value)
953 {
954 #ifdef IS_LITTLE_ENDIAN
955 Nlm_SwitchUint2(value);
956 #endif
957 if (Nlm_BSWrite(bsp, (Nlm_VoidPtr)(&value), (Nlm_Int4)2) == (Nlm_Int2)2)
958 return (Nlm_Int2)1;
959 else
960 return (Nlm_Int2)0;
961 }
962
Nlm_BSPutUint4(Nlm_ByteStorePtr bsp,Nlm_Uint4 value)963 NLM_EXTERN Nlm_Int2 LIBCALL Nlm_BSPutUint4 (Nlm_ByteStorePtr bsp, Nlm_Uint4 value)
964 {
965 #ifdef IS_LITTLE_ENDIAN
966 Nlm_SwitchUint4(value);
967 #endif
968 if (Nlm_BSWrite(bsp, (Nlm_VoidPtr)(&value), (Nlm_Int4)4) == (Nlm_Int2)4)
969 return (Nlm_Int2)1;
970 else
971 return (Nlm_Int2)0;
972 }
973
974 /* In functions below, size is 2 or 4 */
975 /* Integers are converted from ByteStore to native endian (BSUintXRead) */
976 /* or from native endian to ByteStore (BSUintXWrite) */
977 /* len is number of INTEGERS, not number of bytes */
978 /* returns count of integers put in ptr */
979 /* WARNING: On LITTLE_ENDIAN machines the data in ptr is changed to BIG_ENDIAN in the */
980 /* XXWrite functions and LEFT THAT WAY */
Nlm_BSUint4Read(Nlm_ByteStorePtr bsp,Nlm_Uint4Ptr ptr,Nlm_Int4 len)981 NLM_EXTERN Nlm_Int4 LIBCALL Nlm_BSUint4Read (Nlm_ByteStorePtr bsp, Nlm_Uint4Ptr ptr, Nlm_Int4 len)
982 {
983 Nlm_Int4 len2;
984
985 len2 = Nlm_BSRead(bsp, (Nlm_VoidPtr)ptr, (len * 4));
986 len2 /= 4;
987 Nlm_SwapUint4Buff(ptr, len2);
988 return len2;
989 }
990
Nlm_BSUint4Write(Nlm_ByteStorePtr bsp,Nlm_Uint4Ptr ptr,Nlm_Int4 len)991 NLM_EXTERN Nlm_Int4 LIBCALL Nlm_BSUint4Write (Nlm_ByteStorePtr bsp, Nlm_Uint4Ptr ptr, Nlm_Int4 len)
992 {
993 Nlm_Int4 len2;
994
995 #ifdef IS_LITTLE_ENDIAN
996 Nlm_SwitchUint4Buff(ptr, len);
997 #endif
998 len2 = Nlm_BSWrite(bsp, (Nlm_VoidPtr)ptr, (len * 4));
999 return (len2 / 4);
1000 }
1001
Nlm_BSUint2Read(Nlm_ByteStorePtr bsp,Nlm_Uint2Ptr ptr,Nlm_Int4 len)1002 NLM_EXTERN Nlm_Int4 LIBCALL Nlm_BSUint2Read (Nlm_ByteStorePtr bsp, Nlm_Uint2Ptr ptr, Nlm_Int4 len)
1003 {
1004 Nlm_Int4 len2;
1005
1006 len2 = Nlm_BSRead(bsp, (Nlm_VoidPtr)ptr, (len * 2));
1007 len2 /= 2;
1008 Nlm_SwapUint2Buff(ptr, len2);
1009 return len2;
1010 }
1011
Nlm_BSUint2Write(Nlm_ByteStorePtr bsp,Nlm_Uint2Ptr ptr,Nlm_Int4 len)1012 NLM_EXTERN Nlm_Int4 LIBCALL Nlm_BSUint2Write (Nlm_ByteStorePtr bsp, Nlm_Uint2Ptr ptr, Nlm_Int4 len)
1013 {
1014 Nlm_Int4 len2;
1015
1016 #ifdef IS_LITTLE_ENDIAN
1017 Nlm_SwitchUint2Buff(ptr, len);
1018 #endif
1019 len2 = Nlm_BSWrite(bsp, (Nlm_VoidPtr)ptr, (len * 2));
1020 return (len2 / 2);
1021 }
1022
1023