Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 194 lines (149 sloc) 6.691 kB
fccc685 Initial open-source release
MLstate authored
1 (*
2 Copyright © 2011 MLstate
3
4 This file is part of OPA.
5
6 OPA is free software: you can redistribute it and/or modify it under the
7 terms of the GNU Affero General Public License, version 3, as published by
8 the Free Software Foundation.
9
10 OPA is distributed in the hope that it will be useful, but WITHOUT ANY
11 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
13 more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with OPA. If not, see <http://www.gnu.org/licenses/>.
17 *)
18
19 (**
20 Functionnal structure for efficient string production.
21
22 @author Unknown previous author
23 @author Mathieu Barbin
24 @author Rudy Sicard
25 @author Valentin Gatien-Baron
26 *)
27
28 (**
29 This module is for producing big strings in a functionnal way
30 with view allocations, e.g. for code generation.
31
32 If you need to have a better complexity for the [concat] operation,
33 you can use [SRope] instead, which implement the same interface, but
34 with a [concat] in constant time. However, if you need to use the [FBuffer.add]
35 function with small strings, [FBuffer] is quicker.
36
37 <!> See the function [diverge], the implementation is not fully functionnal.
38 Previous values of [t] are persistent but if you diverge from a point
39 of your functionnal historic, you should absolutelly use [diverge] to
40 avoid to compromise an other [t] value.
41
42 Note that every function of this Module is tail recursive.
43
44 <!> If you need to add a function to this module, respect this constraint.
45 (this module manipulate hudge structures)
46
47 *)
48
49 (** The abstract type of a FBuffer. Almost Functionnal (see [diverge] function) *)
50 type t
51
52 (** The empty value. The int is just a hint for the first memory allocation.
53 The name is ignored and will be removed soon. not used, not implemented,
54 weird. (if you create a Stack, do you need to name it ??)
55 *)
56 val create : ?name:string -> int -> t
57
58 (** {6 Basic operations} *)
59
60 (** [add] operations on not too big strings is effecienter
61 using [FBuffer] rather than [SRope] *)
62 val add : t -> string -> t
63
64 (** like [add] but add a new line at end *)
65 val addln : t -> string -> t
66
67 (** [concat a b] does not affect [a] or [b] (functionnal) *)
68 val concat : t -> t -> t
69
70 (** [add_substring t s start len] append to [t] the substring of s
71 startgin from [start] from length [len] *)
72 val add_substring : t -> string -> int -> int -> t
73
74 (** diverge is used whenever you need to start from a point of your history
75 and to diverge. (implementation is not fully functionnal, but by using
76 this function, you are sure not to erase anything in memory *)
77 val diverge : t -> t
78
79 (** {6 Accessing Contents} *)
80 (** *)
81 val contents : t -> string
82 val output : out_channel -> t -> unit
83 val length : t -> int
84 val sub : t -> int -> int -> string
85
86 (** {6 Interactive accessors} *)
87
88 (**
89 Interactive accessors are called with a string [s],
90 a start position [p], and a number of characters [n];
91 it is supposed to output characters [p] to [p + n - 1] of [s].
92
93 The split in several strings depends on the internal representation.
94
95 If for any reason you need to interactivelly access sub string,
96 you can use function [iter_sub] and [fold_sub] applied to
97 a function [f] of your choice, which is stricly equivalent
98 to
99 {[iter (fun s start len -> f (String.sub s start len))]}
100 and respectively
101 {[fold (fun acc s start len -> f acc (String.sub s start len))]}
102 (one more string allocation with [String.sub])
103
104 [rev_iter] and [rev_fold] have better performance than [iter] and [fold].
105 They are all tail rec.
106
107 @see "Format" of the ocaml standard library
108 @see "Pervasives" of the ocaml standard library
109 *)
110
111 (** *)
112 val iter : (string -> int -> int -> unit) -> t -> unit
113 val fold : ('a -> string -> int -> int -> 'a) -> 'a -> t -> 'a
114
115 val rev_iter : (string -> int -> int -> unit) -> t -> unit
116 val rev_fold : ('a -> string -> int -> int -> 'a) -> 'a -> t -> 'a
117
118 val iter_sub : (string -> unit) -> t -> unit
119 val fold_sub : ('a -> string -> 'a) -> 'a -> t -> 'a
120
121 (** {6 Format Support} *)
122
123 (**
124 For outputting a type [t] using format, you can use :
125 [Format.printf "%a" FBuffer.fmt t]
126 it will be more optimized than
127 [Format.printf "%s" (FBuffer.contents t)]
128 *)
129 val fmt : Format.formatter -> t -> unit
130
131 (**
132 [FBuffer.printf t "I add %s" "this"]
133
134 Using the two function combined will give you a quite powerfull
135 concatenation possibility :
136
137 if [a], [b], [c] be [3] value of type [FBuffer.t],
138 you can do things like :
139 [FBuffer.printf t "%a foo %a bar %a" fmt a fmt b fmt c]
140 *)
141 val printf : t -> ('params, Format.formatter, unit, t) format4 -> 'params
142
143 (**
144 Very usefull to replace [Format.sprintf] using a FBuffer implementation.
145 *)
146 val sprintf : ('params, Format.formatter, unit, string) format4 -> 'params
147
148 (** {6 Dynamic choice of implementation} *)
149
150 (**
151 You may want to use this structure for having dynamic choice of implementation.
152 Modules are not value in caml, this is a defun feature.
153 *)
154 type 'fbuffer implementation =
155 {
156 create : int -> 'fbuffer ;
157 add : 'fbuffer -> string -> 'fbuffer ;
158 addln : 'fbuffer -> string -> 'fbuffer ;
159 concat : 'fbuffer -> 'fbuffer -> 'fbuffer ;
160 add_substring : 'fbuffer -> string -> int -> int -> 'fbuffer ;
161 diverge : 'fbuffer -> 'fbuffer ;
162 contents : 'fbuffer -> string ;
163 output : out_channel -> 'fbuffer -> unit ;
164 length : 'fbuffer -> int ;
165 sub : 'fbuffer -> int -> int -> string ;
166 iter : (string -> int -> int -> unit) -> 'fbuffer -> unit ;
167 fold : 'a. ('a -> string -> int -> int -> 'a) -> 'a -> 'fbuffer -> 'a ;
168 rev_iter : (string -> int -> int -> unit) -> 'fbuffer -> unit ;
169 rev_fold : 'a. ('a -> string -> int -> int -> 'a) -> 'a -> 'fbuffer -> 'a ;
170 iter_sub : (string -> unit) -> 'fbuffer -> unit ;
171 fold_sub : 'a. ('a -> string -> 'a) -> 'a -> 'fbuffer -> 'a ;
172 fmt : Format.formatter -> 'fbuffer -> unit ;
173 printf : 'params. 'fbuffer -> ('params, Format.formatter, unit, 'fbuffer) format4 -> 'params ;
174 sprintf : 'params. ('params, Format.formatter, unit, string) format4 -> 'params ;
175 }
176
177 val implementation : t implementation
178
179 (** {6 Backward Compatibility} *)
180
181 (**
182 For historical reason, some allias may result in old code.
183 Please do not use in new code.
184 *)
185
186 (** @deprecated use [union] instead *)
187 val make : ?name:string -> int -> t
188
189 (** @deprecated use [union] instead *)
190 val union : t -> t -> t
191
192 (** @deprecated use [output] instead *)
193 val write : t -> out_channel -> unit
Something went wrong with that request. Please try again.