1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258
|
(* TEST
*)
open Printf
;;
(* Set up*)
let n = 10
;;
let buf = Buffer.create n
;;
let () =
for i = 1 to 10 do
Buffer.add_char buf 'a'
done
;;
assert (Buffer.length buf = n)
;;
(* Helpers *)
let output result str =
print_string ("Buffer " ^ str ^ " " ^ result ^ "\n")
;;
let passed = output "passed"
;;
let failed = output "failed"
;;
let buffer_truncate = "Buffer.truncate"
let unexpected str =
Printf.sprintf "The Invalid_argument exception has been raised with an \
invalid value as argument \"%s\". Expecting \"%s\"."
str buffer_truncate
let validate f str msg =
if str=buffer_truncate then f msg
else failed (unexpected str)
(* Tests *)
let () = print_string "Standard Library: Module Buffer\n"
;;
let truncate_neg : unit =
let msg = "truncate: negative" in
try
Buffer.truncate buf (-1);
failed msg
with
Invalid_argument str -> validate passed str msg
;;
let truncate_large : unit =
let msg = "truncate: large" in
try
Buffer.truncate buf (n+1);
failed msg
with
Invalid_argument str -> validate passed str msg
;;
let truncate_correct : unit =
let n' = n - 1
and msg = "truncate: in-range" in
try
Buffer.truncate buf n';
if Buffer.length buf = n' then
passed msg
else
failed msg
with
Invalid_argument str -> validate failed str msg
;;
let reset_non_zero : unit =
let msg = "reset: non-zero" in
Buffer.reset buf;
if Buffer.length buf = 0 then
passed msg
else
failed msg
;;
let reset_zero : unit =
let msg = "reset: zero" in
Buffer.reset buf;
if Buffer.length buf = 0 then
passed msg
else
failed msg
;;
let utf_8_spec =
(* UTF-8 byte sequences, cf. table 3.7 Unicode 9. *)
[(0x0000,0x007F), [|(0x00,0x7F)|];
(0x0080,0x07FF), [|(0xC2,0xDF); (0x80,0xBF)|];
(0x0800,0x0FFF), [|(0xE0,0xE0); (0xA0,0xBF); (0x80,0xBF)|];
(0x1000,0xCFFF), [|(0xE1,0xEC); (0x80,0xBF); (0x80,0xBF)|];
(0xD000,0xD7FF), [|(0xED,0xED); (0x80,0x9F); (0x80,0xBF)|];
(0xE000,0xFFFF), [|(0xEE,0xEF); (0x80,0xBF); (0x80,0xBF)|];
(0x10000,0x3FFFF), [|(0xF0,0xF0); (0x90,0xBF); (0x80,0xBF); (0x80,0xBF)|];
(0x40000,0xFFFFF), [|(0xF1,0xF3); (0x80,0xBF); (0x80,0xBF); (0x80,0xBF)|];
(0x100000,0x10FFFF), [|(0xF4,0xF4); (0x80,0x8F); (0x80,0xBF); (0x80,0xBF)|]]
;;
let utf_16be_spec =
(* UTF-16BE byte sequences, derived from table 3.5 Unicode 9. *)
[(0x0000,0xD7FF), [|(0x00,0xD7); (0x00,0xFF)|];
(0xE000,0xFFFF), [|(0xE0,0xFF); (0x00,0xFF)|];
(0x10000,0x10FFFF), [|(0xD8,0xDB); (0x00,0xFF); (0xDC,0xDF); (0x00,0xFF)|]]
;;
let uchar_map_of_spec spec =
(* array mapping Uchar.t as ints to byte sequences according to [spec]. *)
let map = Array.make ((Uchar.to_int Uchar.max) + 1) "" in
let add_range ((umin, umax), bytes) =
let len = Array.length bytes in
let bmin i = if i < len then fst bytes.(i) else max_int in
let bmax i = if i < len then snd bytes.(i) else min_int in
let uchar = ref umin in
let buf = Bytes.create len in
let add len' =
if len <> len' then () else
begin
let bytes = Bytes.to_string buf in
map.(!uchar) <- bytes;
incr uchar;
end
in
for b0 = bmin 0 to bmax 0 do
Bytes.unsafe_set buf 0 (Char.chr b0);
for b1 = bmin 1 to bmax 1 do
Bytes.unsafe_set buf 1 (Char.chr b1);
for b2 = bmin 2 to bmax 2 do
Bytes.unsafe_set buf 2 (Char.chr b2);
for b3 = bmin 3 to bmax 3 do
Bytes.unsafe_set buf 3 (Char.chr b3);
add 4;
done;
add 3;
done;
add 2;
done;
add 1;
done;
assert (!uchar - 1 = umax)
in
List.iter add_range spec;
map
;;
let test_spec_map msg utf_x_map buffer_add_utf_x_uchar =
let b = Buffer.create 4 in
let rec loop u =
Buffer.clear b; buffer_add_utf_x_uchar b u;
match Buffer.contents b = utf_x_map.(Uchar.to_int u) with
| false -> failed (sprintf "%s of U+%04X" msg (Uchar.to_int u))
| true ->
if Uchar.equal u Uchar.max then passed msg else loop (Uchar.succ u)
in
loop Uchar.min
;;
let add_utf_8_uchar : unit =
let map = uchar_map_of_spec utf_8_spec in
test_spec_map
"add_utf_8_uchar: test against spec" map Buffer.add_utf_8_uchar
;;
let add_utf_16be_uchar : unit =
let map = uchar_map_of_spec utf_16be_spec in
test_spec_map
"add_utf_16be_uchar: test against spec" map Buffer.add_utf_16be_uchar
;;
let add_utf_16le_uchar : unit =
(* The uchar_map_of_spec generation function doesn't work on a LE spec since
uchars and byte seqs have to increase and map together; simply swap
the map obtained with utf_16be_spec. *)
let map =
let swap bytes =
let swap i = match i with
| 0 -> 1 | 1 -> 0 | 2 -> 3 | 3 -> 2 | _ -> assert false
in
String.init (String.length bytes) (fun i -> bytes.[swap i])
in
Array.map swap (uchar_map_of_spec utf_16be_spec)
in
test_spec_map
"add_utf_16le_uchar: test against spec" map Buffer.add_utf_16le_uchar
;;
let () =
let b = Buffer.create 64 in
Buffer.add_int8 b 0xff;
Buffer.add_int8 b 0x01;
Buffer.add_int16_be b 0x0123;
Buffer.add_int16_le b 0x0123;
Buffer.add_int32_be b 0x01234567l;
Buffer.add_int32_le b 0x01234567l;
Buffer.add_int64_be b 0x0123456789abcdefL;
Buffer.add_int64_le b 0x0123456789abcdefL;
assert (Buffer.contents b =
"\xff\x01" ^
"\x01\x23\x23\x01" ^
"\x01\x23\x45\x67" ^
"\x67\x45\x23\x01" ^
"\x01\x23\x45\x67\x89\xab\xcd\xef" ^
"\xef\xcd\xab\x89\x67\x45\x23\x01"
);
Buffer.clear b;
Buffer.add_int16_ne b 0x0123;
Buffer.add_int32_ne b 0x01234567l;
Buffer.add_int64_ne b 0x0123456789abcdefL;
let s = Buffer.contents b in
if Sys.big_endian then
assert (s = "\x01\x23\x01\x23\x45\x67\x01\x23\x45\x67\x89\xab\xcd\xef")
else
assert (s = "\x23\x01\x67\x45\x23\x01\xef\xcd\xab\x89\x67\x45\x23\x01");
for i = 1 to 20 do
let b = Buffer.create i in
for j = 1 to 100 do
Buffer.add_int8 b 1
done;
assert(Buffer.length b = 100);
done;
for i = 1 to 20 do
let b = Buffer.create i in
for j = 1 to 100 do
Buffer.add_int16_ne b 1
done;
assert(Buffer.length b = 200);
done;
for i = 1 to 20 do
let b = Buffer.create i in
for j = 1 to 100 do
Buffer.add_int32_ne b 1l
done;
assert(Buffer.length b = 400);
done;
for i = 1 to 20 do
let b = Buffer.create i in
for j = 1 to 100 do
Buffer.add_int64_ne b 1L
done;
assert(Buffer.length b = 800);
done
;;
|