Skip to content
This repository
tag: v1559
Fetching contributors…

Cannot retrieve contributors at this time

file 193 lines (149 sloc) 6.691 kb
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
(*
Copyright © 2011 MLstate

This file is part of OPA.

OPA is free software: you can redistribute it and/or modify it under the
terms of the GNU Affero General Public License, version 3, as published by
the Free Software Foundation.

OPA is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
more details.

You should have received a copy of the GNU Affero General Public License
along with OPA. If not, see <http://www.gnu.org/licenses/>.
*)

(**
Functionnal structure for efficient string production.

@author Unknown previous author
@author Mathieu Barbin
@author Rudy Sicard
@author Valentin Gatien-Baron
*)

(**
This module is for producing big strings in a functionnal way
with view allocations, e.g. for code generation.

If you need to have a better complexity for the [concat] operation,
you can use [SRope] instead, which implement the same interface, but
with a [concat] in constant time. However, if you need to use the [FBuffer.add]
function with small strings, [FBuffer] is quicker.

<!> See the function [diverge], the implementation is not fully functionnal.
Previous values of [t] are persistent but if you diverge from a point
of your functionnal historic, you should absolutelly use [diverge] to
avoid to compromise an other [t] value.

Note that every function of this Module is tail recursive.

<!> If you need to add a function to this module, respect this constraint.
(this module manipulate hudge structures)

*)

(** The abstract type of a FBuffer. Almost Functionnal (see [diverge] function) *)
type t

(** The empty value. The int is just a hint for the first memory allocation.
The name is ignored and will be removed soon. not used, not implemented,
weird. (if you create a Stack, do you need to name it ??)
*)
val create : ?name:string -> int -> t

(** {6 Basic operations} *)

(** [add] operations on not too big strings is effecienter
using [FBuffer] rather than [SRope] *)
val add : t -> string -> t

(** like [add] but add a new line at end *)
val addln : t -> string -> t

(** [concat a b] does not affect [a] or [b] (functionnal) *)
val concat : t -> t -> t

(** [add_substring t s start len] append to [t] the substring of s
startgin from [start] from length [len] *)
val add_substring : t -> string -> int -> int -> t

(** diverge is used whenever you need to start from a point of your history
and to diverge. (implementation is not fully functionnal, but by using
this function, you are sure not to erase anything in memory *)
val diverge : t -> t

(** {6 Accessing Contents} *)
(** *)
val contents : t -> string
val output : out_channel -> t -> unit
val length : t -> int
val sub : t -> int -> int -> string

(** {6 Interactive accessors} *)

(**
Interactive accessors are called with a string [s],
a start position [p], and a number of characters [n];
it is supposed to output characters [p] to [p + n - 1] of [s].

The split in several strings depends on the internal representation.

If for any reason you need to interactivelly access sub string,
you can use function [iter_sub] and [fold_sub] applied to
a function [f] of your choice, which is stricly equivalent
to
{[iter (fun s start len -> f (String.sub s start len))]}
and respectively
{[fold (fun acc s start len -> f acc (String.sub s start len))]}
(one more string allocation with [String.sub])

[rev_iter] and [rev_fold] have better performance than [iter] and [fold].
They are all tail rec.

@see "Format" of the ocaml standard library
@see "Pervasives" of the ocaml standard library
*)

(** *)
val iter : (string -> int -> int -> unit) -> t -> unit
val fold : ('a -> string -> int -> int -> 'a) -> 'a -> t -> 'a

val rev_iter : (string -> int -> int -> unit) -> t -> unit
val rev_fold : ('a -> string -> int -> int -> 'a) -> 'a -> t -> 'a

val iter_sub : (string -> unit) -> t -> unit
val fold_sub : ('a -> string -> 'a) -> 'a -> t -> 'a

(** {6 Format Support} *)

(**
For outputting a type [t] using format, you can use :
[Format.printf "%a" FBuffer.fmt t]
it will be more optimized than
[Format.printf "%s" (FBuffer.contents t)]
*)
val fmt : Format.formatter -> t -> unit

(**
[FBuffer.printf t "I add %s" "this"]

Using the two function combined will give you a quite powerfull
concatenation possibility :

if [a], [b], [c] be [3] value of type [FBuffer.t],
you can do things like :
[FBuffer.printf t "%a foo %a bar %a" fmt a fmt b fmt c]
*)
val printf : t -> ('params, Format.formatter, unit, t) format4 -> 'params

(**
Very usefull to replace [Format.sprintf] using a FBuffer implementation.
*)
val sprintf : ('params, Format.formatter, unit, string) format4 -> 'params

(** {6 Dynamic choice of implementation} *)

(**
You may want to use this structure for having dynamic choice of implementation.
Modules are not value in caml, this is a defun feature.
*)
type 'fbuffer implementation =
    {
      create : int -> 'fbuffer ;
      add : 'fbuffer -> string -> 'fbuffer ;
      addln : 'fbuffer -> string -> 'fbuffer ;
      concat : 'fbuffer -> 'fbuffer -> 'fbuffer ;
      add_substring : 'fbuffer -> string -> int -> int -> 'fbuffer ;
      diverge : 'fbuffer -> 'fbuffer ;
      contents : 'fbuffer -> string ;
      output : out_channel -> 'fbuffer -> unit ;
      length : 'fbuffer -> int ;
      sub : 'fbuffer -> int -> int -> string ;
      iter : (string -> int -> int -> unit) -> 'fbuffer -> unit ;
      fold : 'a. ('a -> string -> int -> int -> 'a) -> 'a -> 'fbuffer -> 'a ;
      rev_iter : (string -> int -> int -> unit) -> 'fbuffer -> unit ;
      rev_fold : 'a. ('a -> string -> int -> int -> 'a) -> 'a -> 'fbuffer -> 'a ;
      iter_sub : (string -> unit) -> 'fbuffer -> unit ;
      fold_sub : 'a. ('a -> string -> 'a) -> 'a -> 'fbuffer -> 'a ;
      fmt : Format.formatter -> 'fbuffer -> unit ;
      printf : 'params. 'fbuffer -> ('params, Format.formatter, unit, 'fbuffer) format4 -> 'params ;
      sprintf : 'params. ('params, Format.formatter, unit, string) format4 -> 'params ;
    }

val implementation : t implementation

(** {6 Backward Compatibility} *)

(**
For historical reason, some allias may result in old code.
Please do not use in new code.
*)

(** @deprecated use [union] instead *)
val make : ?name:string -> int -> t

(** @deprecated use [union] instead *)
val union : t -> t -> t

(** @deprecated use [output] instead *)
val write : t -> out_channel -> unit
Something went wrong with that request. Please try again.