2 * ----------------------------------------------------------------------
7 { mutable buffer : string;
11 (* To help the garbage collector:
12 * The 'buffer' has a minimum length of 31 bytes. This minimum can still
13 * be stored in the minor heap.
14 * The 'buffer' has a length which is always near a multiple of two. This
15 * limits the number of different bucket sizes, and simplifies reallocation
19 (* Optimal string length:
20 * Every string takes: 1 word for the header, enough words for the
21 * contents + 1 Null byte (for C compatibility).
22 * If the buffer grows, it is best to use a new string length such
23 * that the number of words is exactly twice as large as for the previous
25 * n: length of the previous string in bytes
26 * w: storage size of the previous string in words
27 * n': length of the new string in bytes
28 * w' = 2*w: storage size of the new string in words
30 * w = (n+1) / word_length + 1
31 * [it is assumed that (n+1) is always a multiple of word_length]
33 * n' = (2*w - 1) * word_length - 1
35 * n' = [2 * ( [n+1] / word_length + 1) - 1] * word_length - 1
37 * = (2*n + 2) + word_length - 1
38 * = 2 * n + word_length + 1
40 * n'+1 is again a multiple of word_length:
41 * n'+1 = 2*n + 2 + word_length
42 * = 2*(n+1) + word_length
43 * = a multiple of word_length because n+1 is a multiple of word_length
46 let word_length = Sys.word_size / 8 (* in bytes *)
49 { buffer = String.create (max n 31); length = 0; }
52 String.sub b.buffer 0 b.length
54 let sub b ~pos:k ~len:n =
55 if k+n > b.length then
56 raise (Invalid_argument "Netbuffer.sub");
57 String.sub b.buffer k n
66 let l = String.length s in
67 if l + b.length > String.length b.buffer then begin
68 let l' = l + b.length in
70 if s >= l' then s else new_size(2*s + word_length + 1)
72 let buffer' = String.create (new_size (String.length b.buffer)) in
73 String.blit b.buffer 0 buffer' 0 b.length;
76 String.blit s 0 b.buffer b.length l;
77 b.length <- b.length + l
79 let add_sub_string b s ~pos:k ~len:l =
80 if l + b.length > String.length b.buffer then begin
81 let l' = l + b.length in
83 if s >= l' then s else new_size(2*s + word_length + 1)
85 let buffer' = String.create (new_size (String.length b.buffer)) in
86 String.blit b.buffer 0 buffer' 0 b.length;
89 String.blit s k b.buffer b.length l;
90 b.length <- b.length + l
92 let delete b ~pos:k ~len:l =
93 (* deletes l bytes at position k in b *)
94 let n = String.length b.buffer in
95 if k+l <> n & k <> n then
96 String.blit b.buffer (k+l) b.buffer k (n-l-k);
97 b.length <- b.length - l;
100 let try_shrinking b =
101 (* If the buffer size decreases drastically, reallocate the buffer *)
102 if b.length < (String.length b.buffer / 2) then begin
104 if s >= b.length then s else new_size(2*s + word_length + 1)
106 let buffer' = String.create (new_size 31) in
107 String.blit b.buffer 0 buffer' 0 b.length;
112 delete b 0 (b.length)
114 let index_from b k c =
116 raise (Invalid_argument "Netbuffer.index_from");
117 let p = String.index_from b.buffer k c in
118 if p >= b.length then raise Not_found;
125 (String.length b.buffer)
128 (* ======================================================================
132 * Revision 1.1 2000/11/17 09:57:27 lpadovan
135 * Revision 1.3 2000/06/25 22:34:43 gerd
136 * Added labels to arguments.
138 * Revision 1.2 2000/06/24 20:20:33 gerd
139 * Added the toploop printer.
141 * Revision 1.1 2000/04/15 13:07:48 gerd