Mantis Bug Tracker

View Issue Details Jump to Notes ] Issue History ] Print ]
IDProjectCategoryView StatusDate SubmittedLast Update
0006975OCamlstandard librarypublic2015-08-30 19:322016-12-06 16:26
Reporteromion 
Assigned Tofrisch 
PrioritylowSeverityfeatureReproducibilityalways
StatusresolvedResolutionfixed 
PlatformOSOS Version
Product Version4.02.0 
Target VersionFixed in Version4.05.0 +dev/beta1/beta2/beta3/rc1 
Summary0006975: Truncating buffers could come in handy
DescriptionI've been writing some code that incrementally adds data to a buffer, but will fail if it gets too long. However, exactly how long the data will be would be difficult to know in advance, so I just have to start writing and give up if it gets too long. I'd like to be able to clear out my half-written data when that happens, but it looks like the Buffer module doesn't really allow that.

Essentially, I'm doing:

let try_write buf data max_chars =
  let start_len = Buffer.length buf in
  write_lots_of_stuff buf data;
  if Buffer.length buf > start_len + max_chars then (
    (* Too long *)
    Buffer.truncate buf start_len;
    false
  ) else (
    (* OK length *)
    true
  )

Buffer.truncate would be trivial to implement in O(1) with access to the Buffer.t internals, but would be difficult and inefficient without.

I was thinking of something like this:

let truncate b len =
  if len < 0 || len > b.position
    then invalid_arg "Buffer.truncate"
    else b.position <- len
Tagsjunior_job
Attached Files

- Relationships
related to 0006538feedback Allowing to modify Buffers in place 
related to 0003774closed function to remove tail chars from a Buffer 

-  Notes
(0014415)
frisch (developer)
2015-08-30 19:57
edited on: 2015-08-31 12:51

I'm in favor of the change: it's useful, easy to implement (and impossible outside the implementation with the same performance profile) and doesn't break invariants of the data structure (one could already reset the buffer and re-inject a prefix of the previous content).

Another useful addition would be to allow extracting a substring of the buffer's content.

As a matter of fact, it would be worth turning Buffer into a full-fledged implementation of "mutable and extensible strings". This would include blitting (from strings, bytes, Buffers) into arbitrary segments of a Buffer.t.

(0014864)
doligez (administrator)
2015-11-27 16:06

I'm also in favor for truncate and substring extraction.

Blitting into buffers is more tricky.
(0016225)
maro (reporter)
2016-08-22 18:03

I would also really like truncate.

I see however at least two things that could lead to further discussions:

1. Should truncate accept arguments larger than the current buffer length? I'd say yes to that, to avoid having to check before calling truncate, e.g.:

let safe_append_stuff buf s =
  Buffer.add_string buf s;
  Buffer.truncate buf max_len

Instead of having to do something as:

let safe_append_stuff buf s =
  Buffer.add_string buf s;
  if Buffer.length buf > max_len then Buffer.truncate buf max_len

But that's a minor detail, honestly both would be fine for me.


2. Should the internal length of the Bytes buffer be modified? I'd say no; that may waste some space, but it would slow down truncate. However, I don't know if this has unintended consequences.

Considering these aspects, one implementation of truncate might be as simple as:

(** [truncate b n] truncates the length of [b] to be no larger than [n].
    Does nothing if the length of [b] is already smaller than or equal to [n].
    Note that it does not change the size of the underlying buffer.
    Raise [Invalid_argument] if [n < 0]. *)
let truncate b n =
  if n < 0 then invalid_arg "Buffer.truncate"
  else if b.position > n then b.position <- n

Is it worth creating a Github PR for that, or is it too small of a change?
(0016646)
frisch (developer)
2016-12-06 16:25

https://github.com/ocaml/ocaml/pull/902 [^]

- Issue History
Date Modified Username Field Change
2015-08-30 19:32 omion New Issue
2015-08-30 19:57 frisch Note Added: 0014415
2015-08-31 12:51 frisch Note Edited: 0014415 View Revisions
2015-09-11 16:32 frisch Relationship added related to 0006538
2015-11-27 16:06 doligez Note Added: 0014864
2015-11-27 16:06 doligez Status new => confirmed
2015-11-27 16:06 doligez Tag Attached: junior_job
2016-08-22 18:03 maro Note Added: 0016225
2016-12-02 15:29 doligez Relationship added related to 0003774
2016-12-06 16:25 frisch Note Added: 0016646
2016-12-06 16:26 frisch Status confirmed => resolved
2016-12-06 16:26 frisch Fixed in Version => 4.05.0 +dev/beta1/beta2/beta3/rc1
2016-12-06 16:26 frisch Resolution open => fixed
2016-12-06 16:26 frisch Assigned To => frisch
2017-02-23 16:43 doligez Category OCaml standard library => standard library


Copyright © 2000 - 2011 MantisBT Group
Powered by Mantis Bugtracker