include Buffer


let add_uint8 b v =
  add_char b (char_of_int (v land 0xFF))

let add_int8 b v =
  add_uint8 b v

let add_uint16_le b v =
  add_uint8 b v;
  add_uint8 b (v lsr 8)

let add_uint16_be b v =
  add_uint8 b (v lsr 8);
  add_uint8 b v

let add_uint16_ne b v =
  if Stdcompat__sys.big_endian then add_uint16_be b v
  else add_uint16_le b v

let add_int16_le = add_uint16_le

let add_int16_be = add_uint16_be

let add_int16_ne = add_uint16_ne

let add_int32_le b v =
  add_uint8 b (Int32.to_int v);
  add_uint8 b (Int32.to_int (Int32.shift_right v 8));
  add_uint8 b (Int32.to_int (Int32.shift_right v 16));
  add_uint8 b (Int32.to_int (Int32.shift_right v 24))

let add_int32_be b v =
  add_uint8 b (Int32.to_int (Int32.shift_right v 24));
  add_uint8 b (Int32.to_int (Int32.shift_right v 16));
  add_uint8 b (Int32.to_int (Int32.shift_right v 8));
  add_uint8 b (Int32.to_int v)

let add_int32_ne b v =
  if Stdcompat__sys.big_endian then add_int32_be b v
  else add_int32_le b v

let add_int64_le b v =
  add_uint8 b (Int64.to_int v);
  add_uint8 b (Int64.to_int (Int64.shift_right v 8));
  add_uint8 b (Int64.to_int (Int64.shift_right v 16));
  add_uint8 b (Int64.to_int (Int64.shift_right v 24));
  add_uint8 b (Int64.to_int (Int64.shift_right v 32));
  add_uint8 b (Int64.to_int (Int64.shift_right v 40));
  add_uint8 b (Int64.to_int (Int64.shift_right v 48));
  add_uint8 b (Int64.to_int (Int64.shift_right v 56))

let add_int64_be b v =
  add_uint8 b (Int64.to_int (Int64.shift_right v 56));
  add_uint8 b (Int64.to_int (Int64.shift_right v 48));
  add_uint8 b (Int64.to_int (Int64.shift_right v 40));
  add_uint8 b (Int64.to_int (Int64.shift_right v 32));
  add_uint8 b (Int64.to_int (Int64.shift_right v 24));
  add_uint8 b (Int64.to_int (Int64.shift_right v 16));
  add_uint8 b (Int64.to_int (Int64.shift_right v 8));
  add_uint8 b (Int64.to_int v)

let add_int64_ne b v =
  if Stdcompat__sys.big_endian then add_int64_be b v
  else add_int64_le b v



let to_bytes = contents

let add_bytes = add_string

let add_subbytes = add_substring



let sub buffer offset length =
  String.sub (contents buffer) offset length

let nth buffer offset =
  (contents buffer).[offset]



let truncate b len =
  let s = sub b 0 len in
  clear b;
  add_string b s



let add_utf_8_uchar b u =
  if Stdcompat__uchar.is_char u then
    add_char b (Stdcompat__uchar.unsafe_to_char u)
  else
    let i = Stdcompat__uchar.to_int u in
    if i <= 0x07FF then
      begin
        add_char b (Char.unsafe_chr (0xC0 lor (i lsr 6)));
        add_char b (Char.unsafe_chr (0x80 lor i land 0x3F));
      end
    else if i <= 0xFFFF then
      begin
        add_char b (Char.unsafe_chr (0xE0 lor (i lsr 12)));
        add_char b (Char.unsafe_chr (0x80 lor (i lsr 6) land 0x3F));
        add_char b (Char.unsafe_chr (0x80 lor i land 0x3F));
      end
    else
      begin
        add_char b (Char.unsafe_chr (0xF0 lor (i lsr 18)));
        add_char b (Char.unsafe_chr (0x80 lor (i lsr 12) land 0x3F));
        add_char b (Char.unsafe_chr (0x80 lor (i lsr 6) land 0x3F));
        add_char b (Char.unsafe_chr (0x80 lor i land 0x3F));
      end

let add_utf_16be_uchar b u =
  let i = Stdcompat__uchar.to_int u in
  if i <= 0xFFFF then
    begin
      add_char b (Char.unsafe_chr (i lsr 8));
      add_char b (Char.unsafe_chr (i land 0xFF));
    end
  else
    let i = i - 0x10000 in
    let hi = 0xD800 lor i lsr 10 in
    let lo = 0xDC00 lor i land 0x3FF in
    add_char b (Char.unsafe_chr (hi lsr 8));
    add_char b (Char.unsafe_chr (hi land 0xFF));
    add_char b (Char.unsafe_chr (lo lsr 8));
    add_char b (Char.unsafe_chr (lo land 0xFF))

let add_utf_16le_uchar b u =
  let i = Stdcompat__uchar.to_int u in
  if i <= 0xFFFF then
    begin
      add_char b (Char.unsafe_chr (i land 0xFF));
      add_char b (Char.unsafe_chr (i lsr 8));
    end
  else
    let i = i - 0x10000 in
    let hi = 0xD800 lor i lsr 10 in
    let lo = 0xDC00 lor i land 0x3FF in
    add_char b (Char.unsafe_chr (hi land 0xFF));
    add_char b (Char.unsafe_chr (hi lsr 8));
    add_char b (Char.unsafe_chr (lo land 0xFF));
    add_char b (Char.unsafe_chr (lo lsr 8))



let add_seq b seq =
  Stdcompat__seq.iter (add_char b) seq

let of_seq g =
  let b = create 32 in
  add_seq b g;
  b

let to_seq b = Stdcompat__tools.vec_to_seq length nth b

let to_seqi b = Stdcompat__tools.vec_to_seqi length nth b



let blit src srcoff dst dstoff len =
  String.blit (contents src) srcoff dst dstoff len


