/usr/share/doc/libghc-blaze-builder-doc/html/src/Blaze-ByteString-Builder-Internal.html is in libghc-blaze-builder-doc 0.3.3.2-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
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 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 | <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<!-- Generated by HsColour, http://code.haskell.org/~malcolm/hscolour/ -->
<title>Blaze/ByteString/Builder/Internal.hs</title>
<link type='text/css' rel='stylesheet' href='hscolour.css' />
</head>
<body>
<pre><a name="line-1"></a><span class='hs-comment'>{-# LANGUAGE CPP, BangPatterns, Rank2Types #-}</span>
<a name="line-2"></a>
<a name="line-3"></a><span class='hs-cpp'>#ifdef USE_MONO_PAT_BINDS</span>
<a name="line-4"></a><span class='hs-comment'>{-# LANGUAGE MonoPatBinds #-}</span>
<a name="line-5"></a><span class='hs-cpp'>#endif</span>
<a name="line-6"></a>
<a name="line-7"></a><span class='hs-comment'>-- |</span>
<a name="line-8"></a><span class='hs-comment'>-- Module : Blaze.ByteString.Builder.Internal</span>
<a name="line-9"></a><span class='hs-comment'>-- Copyright : (c) 2010 Simon Meier</span>
<a name="line-10"></a><span class='hs-comment'>-- License : BSD3-style (see LICENSE)</span>
<a name="line-11"></a><span class='hs-comment'>--</span>
<a name="line-12"></a><span class='hs-comment'>-- Maintainer : Simon Meier <iridcode@gmail.com></span>
<a name="line-13"></a><span class='hs-comment'>-- Stability : experimental</span>
<a name="line-14"></a><span class='hs-comment'>-- Portability : tested on GHC only</span>
<a name="line-15"></a><span class='hs-comment'>--</span>
<a name="line-16"></a><span class='hs-comment'>-- Core types and functions for the 'Builder' monoid and the 'Put' monad.</span>
<a name="line-17"></a><span class='hs-comment'>--</span>
<a name="line-18"></a><span class='hs-keyword'>module</span> <span class='hs-conid'>Blaze</span><span class='hs-varop'>.</span><span class='hs-conid'>ByteString</span><span class='hs-varop'>.</span><span class='hs-conid'>Builder</span><span class='hs-varop'>.</span><span class='hs-conid'>Internal</span> <span class='hs-layout'>(</span>
<a name="line-19"></a>
<a name="line-20"></a> <span class='hs-comment'>-- * Build Steps</span>
<a name="line-21"></a> <span class='hs-conid'>BufRange</span><span class='hs-layout'>(</span><span class='hs-keyglyph'>..</span><span class='hs-layout'>)</span>
<a name="line-22"></a> <span class='hs-layout'>,</span> <span class='hs-conid'>BuildSignal</span>
<a name="line-23"></a> <span class='hs-layout'>,</span> <span class='hs-conid'>BuildStep</span>
<a name="line-24"></a> <span class='hs-layout'>,</span> <span class='hs-varid'>done</span>
<a name="line-25"></a> <span class='hs-layout'>,</span> <span class='hs-varid'>bufferFull</span>
<a name="line-26"></a> <span class='hs-layout'>,</span> <span class='hs-varid'>insertByteString</span>
<a name="line-27"></a>
<a name="line-28"></a> <span class='hs-comment'>-- * Builder</span>
<a name="line-29"></a> <span class='hs-layout'>,</span> <span class='hs-conid'>Builder</span>
<a name="line-30"></a> <span class='hs-layout'>,</span> <span class='hs-varid'>fromBuildStepCont</span>
<a name="line-31"></a> <span class='hs-layout'>,</span> <span class='hs-varid'>fromPut</span>
<a name="line-32"></a> <span class='hs-layout'>,</span> <span class='hs-varid'>flush</span>
<a name="line-33"></a>
<a name="line-34"></a> <span class='hs-comment'>-- * Put</span>
<a name="line-35"></a> <span class='hs-layout'>,</span> <span class='hs-conid'>Put</span>
<a name="line-36"></a> <span class='hs-layout'>,</span> <span class='hs-varid'>putBuilder</span>
<a name="line-37"></a> <span class='hs-layout'>,</span> <span class='hs-varid'>putBuildStepCont</span>
<a name="line-38"></a> <span class='hs-layout'>,</span> <span class='hs-varid'>putLiftIO</span>
<a name="line-39"></a>
<a name="line-40"></a> <span class='hs-comment'>-- * Writes</span>
<a name="line-41"></a> <span class='hs-layout'>,</span> <span class='hs-keyword'>module</span> <span class='hs-conid'>Blaze</span><span class='hs-varop'>.</span><span class='hs-conid'>ByteString</span><span class='hs-varop'>.</span><span class='hs-conid'>Builder</span><span class='hs-varop'>.</span><span class='hs-conid'>Internal</span><span class='hs-varop'>.</span><span class='hs-conid'>Write</span>
<a name="line-42"></a> <span class='hs-layout'>,</span> <span class='hs-varid'>writeToByteString</span>
<a name="line-43"></a>
<a name="line-44"></a> <span class='hs-comment'>-- * Execution</span>
<a name="line-45"></a> <span class='hs-layout'>,</span> <span class='hs-varid'>toLazyByteString</span>
<a name="line-46"></a> <span class='hs-layout'>,</span> <span class='hs-varid'>toLazyByteStringWith</span>
<a name="line-47"></a> <span class='hs-layout'>,</span> <span class='hs-varid'>toByteString</span>
<a name="line-48"></a> <span class='hs-layout'>,</span> <span class='hs-varid'>toByteStringIO</span>
<a name="line-49"></a> <span class='hs-layout'>,</span> <span class='hs-varid'>toByteStringIOWith</span>
<a name="line-50"></a>
<a name="line-51"></a> <span class='hs-comment'>-- * Deafult Sizes</span>
<a name="line-52"></a> <span class='hs-layout'>,</span> <span class='hs-varid'>defaultFirstBufferSize</span>
<a name="line-53"></a> <span class='hs-layout'>,</span> <span class='hs-varid'>defaultMinimalBufferSize</span>
<a name="line-54"></a> <span class='hs-layout'>,</span> <span class='hs-varid'>defaultBufferSize</span>
<a name="line-55"></a> <span class='hs-layout'>,</span> <span class='hs-varid'>defaultMaximalCopySize</span>
<a name="line-56"></a><span class='hs-layout'>)</span> <span class='hs-keyword'>where</span>
<a name="line-57"></a>
<a name="line-58"></a><span class='hs-cpp'>#ifdef HAS_FOREIGN_UNSAFE_MODULE</span>
<a name="line-59"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Foreign</span> <span class='hs-layout'>(</span><span class='hs-varid'>withForeignPtr</span><span class='hs-layout'>,</span> <span class='hs-varid'>sizeOf</span><span class='hs-layout'>,</span> <span class='hs-varid'>copyBytes</span><span class='hs-layout'>,</span> <span class='hs-varid'>plusPtr</span><span class='hs-layout'>,</span> <span class='hs-varid'>minusPtr</span><span class='hs-layout'>)</span>
<a name="line-60"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Foreign</span><span class='hs-varop'>.</span><span class='hs-conid'>ForeignPtr</span><span class='hs-varop'>.</span><span class='hs-conid'>Unsafe</span> <span class='hs-layout'>(</span><span class='hs-varid'>unsafeForeignPtrToPtr</span><span class='hs-layout'>)</span>
<a name="line-61"></a><span class='hs-cpp'>#else</span>
<a name="line-62"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Foreign</span> <span class='hs-layout'>(</span><span class='hs-varid'>unsafeForeignPtrToPtr</span><span class='hs-layout'>,</span> <span class='hs-varid'>withForeignPtr</span><span class='hs-layout'>,</span> <span class='hs-varid'>sizeOf</span><span class='hs-layout'>,</span> <span class='hs-varid'>copyBytes</span><span class='hs-layout'>,</span> <span class='hs-varid'>plusPtr</span><span class='hs-layout'>,</span> <span class='hs-varid'>minusPtr</span><span class='hs-layout'>)</span>
<a name="line-63"></a><span class='hs-cpp'>#endif</span>
<a name="line-64"></a>
<a name="line-65"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Control</span><span class='hs-varop'>.</span><span class='hs-conid'>Monad</span> <span class='hs-layout'>(</span><span class='hs-varid'>unless</span><span class='hs-layout'>)</span>
<a name="line-66"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>System</span><span class='hs-varop'>.</span><span class='hs-conid'>IO</span><span class='hs-varop'>.</span><span class='hs-conid'>Unsafe</span> <span class='hs-layout'>(</span><span class='hs-varid'>unsafeDupablePerformIO</span><span class='hs-layout'>)</span>
<a name="line-67"></a>
<a name="line-68"></a><span class='hs-keyword'>import</span> <span class='hs-keyword'>qualified</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>ByteString</span> <span class='hs-keyword'>as</span> <span class='hs-conid'>S</span>
<a name="line-69"></a><span class='hs-keyword'>import</span> <span class='hs-keyword'>qualified</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>ByteString</span><span class='hs-varop'>.</span><span class='hs-conid'>Internal</span> <span class='hs-keyword'>as</span> <span class='hs-conid'>S</span>
<a name="line-70"></a><span class='hs-keyword'>import</span> <span class='hs-keyword'>qualified</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>ByteString</span><span class='hs-varop'>.</span><span class='hs-conid'>Lazy</span> <span class='hs-keyword'>as</span> <span class='hs-conid'>L</span>
<a name="line-71"></a><span class='hs-keyword'>import</span> <span class='hs-keyword'>qualified</span> <span class='hs-conid'>Data</span><span class='hs-varop'>.</span><span class='hs-conid'>ByteString</span><span class='hs-varop'>.</span><span class='hs-conid'>Lazy</span><span class='hs-varop'>.</span><span class='hs-conid'>Internal</span> <span class='hs-keyword'>as</span> <span class='hs-conid'>L</span>
<a name="line-72"></a>
<a name="line-73"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Blaze</span><span class='hs-varop'>.</span><span class='hs-conid'>ByteString</span><span class='hs-varop'>.</span><span class='hs-conid'>Builder</span><span class='hs-varop'>.</span><span class='hs-conid'>Internal</span><span class='hs-varop'>.</span><span class='hs-conid'>Types</span>
<a name="line-74"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Blaze</span><span class='hs-varop'>.</span><span class='hs-conid'>ByteString</span><span class='hs-varop'>.</span><span class='hs-conid'>Builder</span><span class='hs-varop'>.</span><span class='hs-conid'>Internal</span><span class='hs-varop'>.</span><span class='hs-conid'>Write</span>
<a name="line-75"></a>
<a name="line-76"></a><span class='hs-comment'>------------------------------------------------------------------------------</span>
<a name="line-77"></a><span class='hs-comment'>-- Internal global constants.</span>
<a name="line-78"></a><span class='hs-comment'>------------------------------------------------------------------------------</span>
<a name="line-79"></a>
<a name="line-80"></a><a name="defaultBufferSize"></a><span class='hs-comment'>-- | Default size (~32kb) for the buffer that becomes a chunk of the output</span>
<a name="line-81"></a><span class='hs-comment'>-- stream once it is filled.</span>
<a name="line-82"></a><span class='hs-comment'>--</span>
<a name="line-83"></a><span class='hs-definition'>defaultBufferSize</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Int</span>
<a name="line-84"></a><span class='hs-definition'>defaultBufferSize</span> <span class='hs-keyglyph'>=</span> <span class='hs-num'>32</span> <span class='hs-varop'>*</span> <span class='hs-num'>1024</span> <span class='hs-comment'>-</span> <span class='hs-varid'>overhead</span> <span class='hs-comment'>-- Copied from Data.ByteString.Lazy.</span>
<a name="line-85"></a> <span class='hs-keyword'>where</span> <span class='hs-varid'>overhead</span> <span class='hs-keyglyph'>=</span> <span class='hs-num'>2</span> <span class='hs-varop'>*</span> <span class='hs-varid'>sizeOf</span> <span class='hs-layout'>(</span><span class='hs-varid'>undefined</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Int</span><span class='hs-layout'>)</span>
<a name="line-86"></a>
<a name="line-87"></a><a name="defaultMinimalBufferSize"></a><span class='hs-comment'>-- | The minimal length (~4kb) a buffer must have before filling it and</span>
<a name="line-88"></a><span class='hs-comment'>-- outputting it as a chunk of the output stream.</span>
<a name="line-89"></a><span class='hs-comment'>--</span>
<a name="line-90"></a><span class='hs-comment'>-- This size determines when a buffer is spilled after a 'flush' or a direct</span>
<a name="line-91"></a><span class='hs-comment'>-- bytestring insertion. It is also the size of the first chunk generated by</span>
<a name="line-92"></a><span class='hs-comment'>-- 'toLazyByteString'.</span>
<a name="line-93"></a><span class='hs-definition'>defaultMinimalBufferSize</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Int</span>
<a name="line-94"></a><span class='hs-definition'>defaultMinimalBufferSize</span> <span class='hs-keyglyph'>=</span> <span class='hs-num'>4</span> <span class='hs-varop'>*</span> <span class='hs-num'>1024</span> <span class='hs-comment'>-</span> <span class='hs-varid'>overhead</span>
<a name="line-95"></a> <span class='hs-keyword'>where</span> <span class='hs-varid'>overhead</span> <span class='hs-keyglyph'>=</span> <span class='hs-num'>2</span> <span class='hs-varop'>*</span> <span class='hs-varid'>sizeOf</span> <span class='hs-layout'>(</span><span class='hs-varid'>undefined</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Int</span><span class='hs-layout'>)</span>
<a name="line-96"></a>
<a name="line-97"></a><a name="defaultFirstBufferSize"></a><span class='hs-comment'>-- | The default length (64) for the first buffer to be allocated when</span>
<a name="line-98"></a><span class='hs-comment'>-- converting a 'Builder' to a lazy bytestring.</span>
<a name="line-99"></a><span class='hs-comment'>--</span>
<a name="line-100"></a><span class='hs-comment'>-- See 'toLazyByteStringWith' for further explanation.</span>
<a name="line-101"></a><span class='hs-definition'>defaultFirstBufferSize</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Int</span>
<a name="line-102"></a><span class='hs-definition'>defaultFirstBufferSize</span> <span class='hs-keyglyph'>=</span> <span class='hs-num'>64</span>
<a name="line-103"></a>
<a name="line-104"></a><a name="defaultMaximalCopySize"></a><span class='hs-comment'>-- | The maximal number of bytes for that copying is cheaper than direct</span>
<a name="line-105"></a><span class='hs-comment'>-- insertion into the output stream. This takes into account the fragmentation</span>
<a name="line-106"></a><span class='hs-comment'>-- that may occur in the output buffer due to the early 'flush' implied by the</span>
<a name="line-107"></a><span class='hs-comment'>-- direct bytestring insertion.</span>
<a name="line-108"></a><span class='hs-comment'>--</span>
<a name="line-109"></a><span class='hs-comment'>-- @'defaultMaximalCopySize' = 2 * 'defaultMinimalBufferSize'@</span>
<a name="line-110"></a><span class='hs-comment'>--</span>
<a name="line-111"></a><span class='hs-definition'>defaultMaximalCopySize</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Int</span>
<a name="line-112"></a><span class='hs-definition'>defaultMaximalCopySize</span> <span class='hs-keyglyph'>=</span> <span class='hs-num'>2</span> <span class='hs-varop'>*</span> <span class='hs-varid'>defaultMinimalBufferSize</span>
<a name="line-113"></a>
<a name="line-114"></a><span class='hs-comment'>------------------------------------------------------------------------------</span>
<a name="line-115"></a><span class='hs-comment'>-- Flushing and running a Builder</span>
<a name="line-116"></a><span class='hs-comment'>------------------------------------------------------------------------------</span>
<a name="line-117"></a>
<a name="line-118"></a><a name="nonEmptyChunk"></a><span class='hs-comment'>-- | Prepend the chunk if it is non-empty.</span>
<a name="line-119"></a><span class='hs-comment'>{-# INLINE nonEmptyChunk #-}</span>
<a name="line-120"></a><span class='hs-definition'>nonEmptyChunk</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>S</span><span class='hs-varop'>.</span><span class='hs-conid'>ByteString</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>L</span><span class='hs-varop'>.</span><span class='hs-conid'>ByteString</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>L</span><span class='hs-varop'>.</span><span class='hs-conid'>ByteString</span>
<a name="line-121"></a><span class='hs-definition'>nonEmptyChunk</span> <span class='hs-varid'>bs</span> <span class='hs-varid'>lbs</span> <span class='hs-keyglyph'>|</span> <span class='hs-conid'>S</span><span class='hs-varop'>.</span><span class='hs-varid'>null</span> <span class='hs-varid'>bs</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>lbs</span>
<a name="line-122"></a> <span class='hs-keyglyph'>|</span> <span class='hs-varid'>otherwise</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>L</span><span class='hs-varop'>.</span><span class='hs-conid'>Chunk</span> <span class='hs-varid'>bs</span> <span class='hs-varid'>lbs</span>
<a name="line-123"></a>
<a name="line-124"></a>
<a name="line-125"></a><a name="flush"></a><span class='hs-comment'>-- | Output all data written in the current buffer and start a new chunk.</span>
<a name="line-126"></a><span class='hs-comment'>--</span>
<a name="line-127"></a><span class='hs-comment'>-- The use of this function depends on how the resulting bytestrings are</span>
<a name="line-128"></a><span class='hs-comment'>-- consumed. 'flush' is possibly not very useful in non-interactive scenarios.</span>
<a name="line-129"></a><span class='hs-comment'>-- However, it is kept for compatibility with the builder provided by</span>
<a name="line-130"></a><span class='hs-comment'>-- Data.Binary.Builder.</span>
<a name="line-131"></a><span class='hs-comment'>--</span>
<a name="line-132"></a><span class='hs-comment'>-- When using 'toLazyByteString' to extract a lazy 'L.ByteString' from a</span>
<a name="line-133"></a><span class='hs-comment'>-- 'Builder', this means that a new chunk will be started in the resulting lazy</span>
<a name="line-134"></a><span class='hs-comment'>-- 'L.ByteString'. The remaining part of the buffer is spilled, if the</span>
<a name="line-135"></a><span class='hs-comment'>-- reamining free space is smaller than the minimal desired buffer size.</span>
<a name="line-136"></a><span class='hs-comment'>--</span>
<a name="line-137"></a><span class='hs-comment'>{-# INLINE flush #-}</span>
<a name="line-138"></a><span class='hs-definition'>flush</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Builder</span>
<a name="line-139"></a><span class='hs-definition'>flush</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>fromBuildStepCont</span> <span class='hs-varid'>step</span>
<a name="line-140"></a> <span class='hs-keyword'>where</span>
<a name="line-141"></a> <span class='hs-varid'>step</span> <span class='hs-varid'>k</span> <span class='hs-varop'>!</span><span class='hs-layout'>(</span><span class='hs-conid'>BufRange</span> <span class='hs-varid'>op</span> <span class='hs-keyword'>_</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>return</span> <span class='hs-varop'>$</span> <span class='hs-varid'>insertByteString</span> <span class='hs-varid'>op</span> <span class='hs-conid'>S</span><span class='hs-varop'>.</span><span class='hs-varid'>empty</span> <span class='hs-varid'>k</span>
<a name="line-142"></a>
<a name="line-143"></a><a name="toLazyByteStringWith"></a><span class='hs-comment'>-- | Run a 'Builder' with the given buffer sizes.</span>
<a name="line-144"></a><span class='hs-comment'>--</span>
<a name="line-145"></a><span class='hs-comment'>-- Use this function for integrating the 'Builder' type with other libraries</span>
<a name="line-146"></a><span class='hs-comment'>-- that generate lazy bytestrings.</span>
<a name="line-147"></a><span class='hs-comment'>--</span>
<a name="line-148"></a><span class='hs-comment'>-- Note that the builders should guarantee that on average the desired chunk</span>
<a name="line-149"></a><span class='hs-comment'>-- size is attained. Builders may decide to start a new buffer and not</span>
<a name="line-150"></a><span class='hs-comment'>-- completely fill the existing buffer, if this is faster. However, they should</span>
<a name="line-151"></a><span class='hs-comment'>-- not spill too much of the buffer, if they cannot compensate for it.</span>
<a name="line-152"></a><span class='hs-comment'>--</span>
<a name="line-153"></a><span class='hs-comment'>-- A call @toLazyByteStringWith bufSize minBufSize firstBufSize@ will generate</span>
<a name="line-154"></a><span class='hs-comment'>-- a lazy bytestring according to the following strategy. First, we allocate</span>
<a name="line-155"></a><span class='hs-comment'>-- a buffer of size @firstBufSize@ and start filling it. If it overflows, we</span>
<a name="line-156"></a><span class='hs-comment'>-- allocate a buffer of size @minBufSize@ and copy the first buffer to it in</span>
<a name="line-157"></a><span class='hs-comment'>-- order to avoid generating a too small chunk. Finally, every next buffer will</span>
<a name="line-158"></a><span class='hs-comment'>-- be of size @bufSize@. This, slow startup strategy is required to achieve</span>
<a name="line-159"></a><span class='hs-comment'>-- good speed for short (<200 bytes) resulting bytestrings, as for them the</span>
<a name="line-160"></a><span class='hs-comment'>-- allocation cost is of a large buffer cannot be compensated. Moreover, this</span>
<a name="line-161"></a><span class='hs-comment'>-- strategy also allows us to avoid spilling too much memory for short</span>
<a name="line-162"></a><span class='hs-comment'>-- resulting bytestrings.</span>
<a name="line-163"></a><span class='hs-comment'>--</span>
<a name="line-164"></a><span class='hs-comment'>-- Note that setting @firstBufSize >= minBufSize@ implies that the first buffer</span>
<a name="line-165"></a><span class='hs-comment'>-- is no longer copied but allocated and filled directly. Hence, setting</span>
<a name="line-166"></a><span class='hs-comment'>-- @firstBufSize = bufSize@ means that all chunks will use an underlying buffer</span>
<a name="line-167"></a><span class='hs-comment'>-- of size @bufSize@. This is recommended, if you know that you always output</span>
<a name="line-168"></a><span class='hs-comment'>-- more than @minBufSize@ bytes.</span>
<a name="line-169"></a><span class='hs-definition'>toLazyByteStringWith</span>
<a name="line-170"></a> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Int</span> <span class='hs-comment'>-- ^ Buffer size (upper-bounds the resulting chunk size).</span>
<a name="line-171"></a> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>Int</span> <span class='hs-comment'>-- ^ Minimal free buffer space for continuing filling</span>
<a name="line-172"></a> <span class='hs-comment'>-- the same buffer after a 'flush' or a direct bytestring</span>
<a name="line-173"></a> <span class='hs-comment'>-- insertion. This corresponds to the minimal desired</span>
<a name="line-174"></a> <span class='hs-comment'>-- chunk size.</span>
<a name="line-175"></a> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>Int</span> <span class='hs-comment'>-- ^ Size of the first buffer to be used and copied for</span>
<a name="line-176"></a> <span class='hs-comment'>-- larger resulting sequences</span>
<a name="line-177"></a> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>Builder</span> <span class='hs-comment'>-- ^ Builder to run.</span>
<a name="line-178"></a> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>L</span><span class='hs-varop'>.</span><span class='hs-conid'>ByteString</span> <span class='hs-comment'>-- ^ Lazy bytestring to output after the builder is</span>
<a name="line-179"></a> <span class='hs-comment'>-- finished.</span>
<a name="line-180"></a> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>L</span><span class='hs-varop'>.</span><span class='hs-conid'>ByteString</span> <span class='hs-comment'>-- ^ Resulting lazy bytestring</span>
<a name="line-181"></a><span class='hs-definition'>toLazyByteStringWith</span> <span class='hs-varid'>bufSize</span> <span class='hs-varid'>minBufSize</span> <span class='hs-varid'>firstBufSize</span> <span class='hs-layout'>(</span><span class='hs-conid'>Builder</span> <span class='hs-varid'>b</span><span class='hs-layout'>)</span> <span class='hs-varid'>k</span> <span class='hs-keyglyph'>=</span>
<a name="line-182"></a> <span class='hs-conid'>S</span><span class='hs-varop'>.</span><span class='hs-varid'>inlinePerformIO</span> <span class='hs-varop'>$</span> <span class='hs-varid'>fillFirstBuffer</span> <span class='hs-layout'>(</span><span class='hs-varid'>b</span> <span class='hs-layout'>(</span><span class='hs-varid'>buildStep</span> <span class='hs-varid'>finalStep</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<a name="line-183"></a> <span class='hs-keyword'>where</span>
<a name="line-184"></a> <span class='hs-varid'>finalStep</span> <span class='hs-layout'>(</span><span class='hs-conid'>BufRange</span> <span class='hs-varid'>pf</span> <span class='hs-keyword'>_</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>return</span> <span class='hs-varop'>$</span> <span class='hs-conid'>Done</span> <span class='hs-varid'>pf</span> <span class='hs-conid'>()</span>
<a name="line-185"></a> <span class='hs-comment'>-- fill a first very small buffer, if we need more space then copy it</span>
<a name="line-186"></a> <span class='hs-comment'>-- to the new buffer of size 'minBufSize'. This way we don't pay the</span>
<a name="line-187"></a> <span class='hs-comment'>-- allocation cost of the big 'bufSize' buffer, when outputting only</span>
<a name="line-188"></a> <span class='hs-comment'>-- small sequences.</span>
<a name="line-189"></a> <span class='hs-varid'>fillFirstBuffer</span> <span class='hs-varop'>!</span><span class='hs-varid'>step0</span>
<a name="line-190"></a> <span class='hs-keyglyph'>|</span> <span class='hs-varid'>minBufSize</span> <span class='hs-varop'><=</span> <span class='hs-varid'>firstBufSize</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>fillNewBuffer</span> <span class='hs-varid'>firstBufSize</span> <span class='hs-varid'>step0</span>
<a name="line-191"></a> <span class='hs-keyglyph'>|</span> <span class='hs-varid'>otherwise</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
<a name="line-192"></a> <span class='hs-varid'>fpbuf</span> <span class='hs-keyglyph'><-</span> <span class='hs-conid'>S</span><span class='hs-varop'>.</span><span class='hs-varid'>mallocByteString</span> <span class='hs-varid'>firstBufSize</span>
<a name="line-193"></a> <span class='hs-varid'>withForeignPtr</span> <span class='hs-varid'>fpbuf</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>pf</span> <span class='hs-keyglyph'>-></span> <span class='hs-keyword'>do</span>
<a name="line-194"></a> <span class='hs-keyword'>let</span> <span class='hs-varop'>!</span><span class='hs-varid'>pe</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>pf</span> <span class='hs-varop'>`plusPtr`</span> <span class='hs-varid'>firstBufSize</span>
<a name="line-195"></a> <span class='hs-varid'>mkbs</span> <span class='hs-varid'>pf'</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>S</span><span class='hs-varop'>.</span><span class='hs-conid'>PS</span> <span class='hs-varid'>fpbuf</span> <span class='hs-num'>0</span> <span class='hs-layout'>(</span><span class='hs-varid'>pf'</span> <span class='hs-varop'>`minusPtr`</span> <span class='hs-varid'>pf</span><span class='hs-layout'>)</span>
<a name="line-196"></a> <span class='hs-comment'>{-# INLINE mkbs #-}</span>
<a name="line-197"></a> <span class='hs-varid'>next</span> <span class='hs-keyglyph'><-</span> <span class='hs-varid'>runBuildStep</span> <span class='hs-varid'>step0</span> <span class='hs-layout'>(</span><span class='hs-conid'>BufRange</span> <span class='hs-varid'>pf</span> <span class='hs-varid'>pe</span><span class='hs-layout'>)</span>
<a name="line-198"></a> <span class='hs-keyword'>case</span> <span class='hs-varid'>next</span> <span class='hs-keyword'>of</span>
<a name="line-199"></a> <span class='hs-conid'>Done</span> <span class='hs-varid'>pf'</span> <span class='hs-keyword'>_</span>
<a name="line-200"></a> <span class='hs-keyglyph'>|</span> <span class='hs-varid'>pf'</span> <span class='hs-varop'>==</span> <span class='hs-varid'>pf</span> <span class='hs-keyglyph'>-></span> <span class='hs-varid'>return</span> <span class='hs-varid'>k</span>
<a name="line-201"></a> <span class='hs-keyglyph'>|</span> <span class='hs-varid'>otherwise</span> <span class='hs-keyglyph'>-></span> <span class='hs-varid'>return</span> <span class='hs-varop'>$</span> <span class='hs-conid'>L</span><span class='hs-varop'>.</span><span class='hs-conid'>Chunk</span> <span class='hs-layout'>(</span><span class='hs-varid'>mkbs</span> <span class='hs-varid'>pf'</span><span class='hs-layout'>)</span> <span class='hs-varid'>k</span>
<a name="line-202"></a>
<a name="line-203"></a> <span class='hs-conid'>BufferFull</span> <span class='hs-varid'>newSize</span> <span class='hs-varid'>pf'</span> <span class='hs-varid'>nextStep</span> <span class='hs-keyglyph'>-></span> <span class='hs-keyword'>do</span>
<a name="line-204"></a> <span class='hs-keyword'>let</span> <span class='hs-varop'>!</span><span class='hs-varid'>l</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>pf'</span> <span class='hs-varop'>`minusPtr`</span> <span class='hs-varid'>pf</span>
<a name="line-205"></a> <span class='hs-varid'>fillNewBuffer</span> <span class='hs-layout'>(</span><span class='hs-varid'>max</span> <span class='hs-layout'>(</span><span class='hs-varid'>l</span> <span class='hs-varop'>+</span> <span class='hs-varid'>newSize</span><span class='hs-layout'>)</span> <span class='hs-varid'>minBufSize</span><span class='hs-layout'>)</span> <span class='hs-varop'>$</span> <span class='hs-varid'>buildStep</span> <span class='hs-varop'>$</span>
<a name="line-206"></a> <span class='hs-keyglyph'>\</span><span class='hs-layout'>(</span><span class='hs-conid'>BufRange</span> <span class='hs-varid'>pfNew</span> <span class='hs-varid'>peNew</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-></span> <span class='hs-keyword'>do</span>
<a name="line-207"></a> <span class='hs-varid'>copyBytes</span> <span class='hs-varid'>pfNew</span> <span class='hs-varid'>pf</span> <span class='hs-varid'>l</span>
<a name="line-208"></a> <span class='hs-keyword'>let</span> <span class='hs-varop'>!</span><span class='hs-varid'>br'</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>BufRange</span> <span class='hs-layout'>(</span><span class='hs-varid'>pfNew</span> <span class='hs-varop'>`plusPtr`</span> <span class='hs-varid'>l</span><span class='hs-layout'>)</span> <span class='hs-varid'>peNew</span>
<a name="line-209"></a> <span class='hs-varid'>runBuildStep</span> <span class='hs-varid'>nextStep</span> <span class='hs-varid'>br'</span>
<a name="line-210"></a>
<a name="line-211"></a> <span class='hs-conid'>InsertByteString</span> <span class='hs-varid'>pf'</span> <span class='hs-varid'>bs</span> <span class='hs-varid'>nextStep</span>
<a name="line-212"></a> <span class='hs-keyglyph'>|</span> <span class='hs-varid'>pf'</span> <span class='hs-varop'>==</span> <span class='hs-varid'>pf</span> <span class='hs-keyglyph'>-></span>
<a name="line-213"></a> <span class='hs-varid'>return</span> <span class='hs-varop'>$</span> <span class='hs-varid'>nonEmptyChunk</span> <span class='hs-varid'>bs</span> <span class='hs-layout'>(</span><span class='hs-conid'>S</span><span class='hs-varop'>.</span><span class='hs-varid'>inlinePerformIO</span> <span class='hs-varop'>$</span> <span class='hs-varid'>fillNewBuffer</span> <span class='hs-varid'>bufSize</span> <span class='hs-varid'>nextStep</span><span class='hs-layout'>)</span>
<a name="line-214"></a> <span class='hs-keyglyph'>|</span> <span class='hs-varid'>otherwise</span> <span class='hs-keyglyph'>-></span>
<a name="line-215"></a> <span class='hs-varid'>return</span> <span class='hs-varop'>$</span> <span class='hs-conid'>L</span><span class='hs-varop'>.</span><span class='hs-conid'>Chunk</span> <span class='hs-layout'>(</span><span class='hs-varid'>mkbs</span> <span class='hs-varid'>pf'</span><span class='hs-layout'>)</span>
<a name="line-216"></a> <span class='hs-layout'>(</span><span class='hs-varid'>nonEmptyChunk</span> <span class='hs-varid'>bs</span> <span class='hs-layout'>(</span><span class='hs-conid'>S</span><span class='hs-varop'>.</span><span class='hs-varid'>inlinePerformIO</span> <span class='hs-varop'>$</span> <span class='hs-varid'>fillNewBuffer</span> <span class='hs-varid'>bufSize</span> <span class='hs-varid'>nextStep</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<a name="line-217"></a>
<a name="line-218"></a> <span class='hs-comment'>-- allocate and fill a new buffer</span>
<a name="line-219"></a> <span class='hs-varid'>fillNewBuffer</span> <span class='hs-varop'>!</span><span class='hs-varid'>size</span> <span class='hs-varop'>!</span><span class='hs-varid'>step0</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
<a name="line-220"></a> <span class='hs-varid'>fpbuf</span> <span class='hs-keyglyph'><-</span> <span class='hs-conid'>S</span><span class='hs-varop'>.</span><span class='hs-varid'>mallocByteString</span> <span class='hs-varid'>size</span>
<a name="line-221"></a> <span class='hs-varid'>withForeignPtr</span> <span class='hs-varid'>fpbuf</span> <span class='hs-varop'>$</span> <span class='hs-varid'>fillBuffer</span> <span class='hs-varid'>fpbuf</span>
<a name="line-222"></a> <span class='hs-keyword'>where</span>
<a name="line-223"></a> <span class='hs-varid'>fillBuffer</span> <span class='hs-varid'>fpbuf</span> <span class='hs-varop'>!</span><span class='hs-varid'>pbuf</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>fill</span> <span class='hs-varid'>pbuf</span> <span class='hs-varid'>step0</span>
<a name="line-224"></a> <span class='hs-keyword'>where</span>
<a name="line-225"></a> <span class='hs-varop'>!</span><span class='hs-varid'>pe</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>pbuf</span> <span class='hs-varop'>`plusPtr`</span> <span class='hs-varid'>size</span>
<a name="line-226"></a> <span class='hs-varid'>fill</span> <span class='hs-varop'>!</span><span class='hs-varid'>pf</span> <span class='hs-varop'>!</span><span class='hs-varid'>step</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
<a name="line-227"></a> <span class='hs-varid'>next</span> <span class='hs-keyglyph'><-</span> <span class='hs-varid'>runBuildStep</span> <span class='hs-varid'>step</span> <span class='hs-layout'>(</span><span class='hs-conid'>BufRange</span> <span class='hs-varid'>pf</span> <span class='hs-varid'>pe</span><span class='hs-layout'>)</span>
<a name="line-228"></a> <span class='hs-keyword'>let</span> <span class='hs-varid'>mkbs</span> <span class='hs-varid'>pf'</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>S</span><span class='hs-varop'>.</span><span class='hs-conid'>PS</span> <span class='hs-varid'>fpbuf</span> <span class='hs-layout'>(</span><span class='hs-varid'>pf</span> <span class='hs-varop'>`minusPtr`</span> <span class='hs-varid'>pbuf</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>pf'</span> <span class='hs-varop'>`minusPtr`</span> <span class='hs-varid'>pf</span><span class='hs-layout'>)</span>
<a name="line-229"></a> <span class='hs-comment'>{-# INLINE mkbs #-}</span>
<a name="line-230"></a> <span class='hs-keyword'>case</span> <span class='hs-varid'>next</span> <span class='hs-keyword'>of</span>
<a name="line-231"></a> <span class='hs-conid'>Done</span> <span class='hs-varid'>pf'</span> <span class='hs-keyword'>_</span>
<a name="line-232"></a> <span class='hs-keyglyph'>|</span> <span class='hs-varid'>pf'</span> <span class='hs-varop'>==</span> <span class='hs-varid'>pf</span> <span class='hs-keyglyph'>-></span> <span class='hs-varid'>return</span> <span class='hs-varid'>k</span>
<a name="line-233"></a> <span class='hs-keyglyph'>|</span> <span class='hs-varid'>otherwise</span> <span class='hs-keyglyph'>-></span> <span class='hs-varid'>return</span> <span class='hs-varop'>$</span> <span class='hs-conid'>L</span><span class='hs-varop'>.</span><span class='hs-conid'>Chunk</span> <span class='hs-layout'>(</span><span class='hs-varid'>mkbs</span> <span class='hs-varid'>pf'</span><span class='hs-layout'>)</span> <span class='hs-varid'>k</span>
<a name="line-234"></a>
<a name="line-235"></a> <span class='hs-conid'>BufferFull</span> <span class='hs-varid'>newSize</span> <span class='hs-varid'>pf'</span> <span class='hs-varid'>nextStep</span>
<a name="line-236"></a> <span class='hs-keyglyph'>|</span> <span class='hs-varid'>pf'</span> <span class='hs-varop'>==</span> <span class='hs-varid'>pf</span> <span class='hs-keyglyph'>-></span>
<a name="line-237"></a> <span class='hs-varid'>fillNewBuffer</span> <span class='hs-layout'>(</span><span class='hs-varid'>max</span> <span class='hs-varid'>newSize</span> <span class='hs-varid'>bufSize</span><span class='hs-layout'>)</span> <span class='hs-varid'>nextStep</span>
<a name="line-238"></a> <span class='hs-keyglyph'>|</span> <span class='hs-varid'>otherwise</span> <span class='hs-keyglyph'>-></span>
<a name="line-239"></a> <span class='hs-varid'>return</span> <span class='hs-varop'>$</span> <span class='hs-conid'>L</span><span class='hs-varop'>.</span><span class='hs-conid'>Chunk</span> <span class='hs-layout'>(</span><span class='hs-varid'>mkbs</span> <span class='hs-varid'>pf'</span><span class='hs-layout'>)</span>
<a name="line-240"></a> <span class='hs-layout'>(</span><span class='hs-conid'>S</span><span class='hs-varop'>.</span><span class='hs-varid'>inlinePerformIO</span> <span class='hs-varop'>$</span>
<a name="line-241"></a> <span class='hs-varid'>fillNewBuffer</span> <span class='hs-layout'>(</span><span class='hs-varid'>max</span> <span class='hs-varid'>newSize</span> <span class='hs-varid'>bufSize</span><span class='hs-layout'>)</span> <span class='hs-varid'>nextStep</span><span class='hs-layout'>)</span>
<a name="line-242"></a>
<a name="line-243"></a> <span class='hs-conid'>InsertByteString</span> <span class='hs-varid'>pf'</span> <span class='hs-varid'>bs</span> <span class='hs-varid'>nextStep</span>
<a name="line-244"></a> <span class='hs-keyglyph'>|</span> <span class='hs-varid'>pf'</span> <span class='hs-varop'>==</span> <span class='hs-varid'>pf</span> <span class='hs-keyglyph'>-></span>
<a name="line-245"></a> <span class='hs-varid'>return</span> <span class='hs-varop'>$</span> <span class='hs-varid'>nonEmptyChunk</span> <span class='hs-varid'>bs</span> <span class='hs-layout'>(</span><span class='hs-conid'>S</span><span class='hs-varop'>.</span><span class='hs-varid'>inlinePerformIO</span> <span class='hs-varop'>$</span> <span class='hs-varid'>fill</span> <span class='hs-varid'>pf'</span> <span class='hs-varid'>nextStep</span><span class='hs-layout'>)</span>
<a name="line-246"></a> <span class='hs-keyglyph'>|</span> <span class='hs-varid'>minBufSize</span> <span class='hs-varop'><</span> <span class='hs-varid'>pe</span> <span class='hs-varop'>`minusPtr`</span> <span class='hs-varid'>pf'</span> <span class='hs-keyglyph'>-></span>
<a name="line-247"></a> <span class='hs-varid'>return</span> <span class='hs-varop'>$</span> <span class='hs-conid'>L</span><span class='hs-varop'>.</span><span class='hs-conid'>Chunk</span> <span class='hs-layout'>(</span><span class='hs-varid'>mkbs</span> <span class='hs-varid'>pf'</span><span class='hs-layout'>)</span>
<a name="line-248"></a> <span class='hs-layout'>(</span><span class='hs-varid'>nonEmptyChunk</span> <span class='hs-varid'>bs</span> <span class='hs-layout'>(</span><span class='hs-conid'>S</span><span class='hs-varop'>.</span><span class='hs-varid'>inlinePerformIO</span> <span class='hs-varop'>$</span> <span class='hs-varid'>fill</span> <span class='hs-varid'>pf'</span> <span class='hs-varid'>nextStep</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<a name="line-249"></a> <span class='hs-keyglyph'>|</span> <span class='hs-varid'>otherwise</span> <span class='hs-keyglyph'>-></span>
<a name="line-250"></a> <span class='hs-varid'>return</span> <span class='hs-varop'>$</span> <span class='hs-conid'>L</span><span class='hs-varop'>.</span><span class='hs-conid'>Chunk</span> <span class='hs-layout'>(</span><span class='hs-varid'>mkbs</span> <span class='hs-varid'>pf'</span><span class='hs-layout'>)</span>
<a name="line-251"></a> <span class='hs-layout'>(</span><span class='hs-varid'>nonEmptyChunk</span> <span class='hs-varid'>bs</span> <span class='hs-layout'>(</span><span class='hs-conid'>S</span><span class='hs-varop'>.</span><span class='hs-varid'>inlinePerformIO</span> <span class='hs-varop'>$</span> <span class='hs-varid'>fillNewBuffer</span> <span class='hs-varid'>bufSize</span> <span class='hs-varid'>nextStep</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<a name="line-252"></a>
<a name="line-253"></a>
<a name="line-254"></a><a name="toLazyByteString"></a><span class='hs-comment'>-- | Extract the lazy 'L.ByteString' from the builder by running it with default</span>
<a name="line-255"></a><span class='hs-comment'>-- buffer sizes. Use this function, if you do not have any special</span>
<a name="line-256"></a><span class='hs-comment'>-- considerations with respect to buffer sizes.</span>
<a name="line-257"></a><span class='hs-comment'>--</span>
<a name="line-258"></a><span class='hs-comment'>-- @ 'toLazyByteString' b = 'toLazyByteStringWith' 'defaultBufferSize' 'defaultMinimalBufferSize' 'defaultFirstBufferSize' b L.empty@</span>
<a name="line-259"></a><span class='hs-comment'>--</span>
<a name="line-260"></a><span class='hs-comment'>-- Note that @'toLazyByteString'@ is a 'Monoid' homomorphism.</span>
<a name="line-261"></a><span class='hs-comment'>--</span>
<a name="line-262"></a><span class='hs-comment'>-- > toLazyByteString mempty == mempty</span>
<a name="line-263"></a><span class='hs-comment'>-- > toLazyByteString (x `mappend` y) == toLazyByteString x `mappend` toLazyByteString y</span>
<a name="line-264"></a><span class='hs-comment'>--</span>
<a name="line-265"></a><span class='hs-comment'>-- However, in the second equation, the left-hand-side is generally faster to</span>
<a name="line-266"></a><span class='hs-comment'>-- execute.</span>
<a name="line-267"></a><span class='hs-comment'>--</span>
<a name="line-268"></a><span class='hs-definition'>toLazyByteString</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Builder</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>L</span><span class='hs-varop'>.</span><span class='hs-conid'>ByteString</span>
<a name="line-269"></a><span class='hs-definition'>toLazyByteString</span> <span class='hs-varid'>b</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>toLazyByteStringWith</span>
<a name="line-270"></a> <span class='hs-varid'>defaultBufferSize</span> <span class='hs-varid'>defaultMinimalBufferSize</span> <span class='hs-varid'>defaultFirstBufferSize</span> <span class='hs-varid'>b</span> <span class='hs-conid'>L</span><span class='hs-varop'>.</span><span class='hs-varid'>empty</span>
<a name="line-271"></a><span class='hs-comment'>{-# INLINE toLazyByteString #-}</span>
<a name="line-272"></a>
<a name="line-273"></a><a name="packChunks"></a><span class='hs-comment'>-- | Pack the chunks of a lazy bytestring into a single strict bytestring.</span>
<a name="line-274"></a><span class='hs-definition'>packChunks</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>L</span><span class='hs-varop'>.</span><span class='hs-conid'>ByteString</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>S</span><span class='hs-varop'>.</span><span class='hs-conid'>ByteString</span>
<a name="line-275"></a><span class='hs-definition'>packChunks</span> <span class='hs-varid'>lbs</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
<a name="line-276"></a> <span class='hs-conid'>S</span><span class='hs-varop'>.</span><span class='hs-varid'>unsafeCreate</span> <span class='hs-layout'>(</span><span class='hs-varid'>fromIntegral</span> <span class='hs-varop'>$</span> <span class='hs-conid'>L</span><span class='hs-varop'>.</span><span class='hs-varid'>length</span> <span class='hs-varid'>lbs</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>copyChunks</span> <span class='hs-varid'>lbs</span><span class='hs-layout'>)</span>
<a name="line-277"></a> <span class='hs-keyword'>where</span>
<a name="line-278"></a> <span class='hs-varid'>copyChunks</span> <span class='hs-varop'>!</span><span class='hs-conid'>L</span><span class='hs-varop'>.</span><span class='hs-conid'>Empty</span> <span class='hs-varop'>!</span><span class='hs-sel'>_pf</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>return</span> <span class='hs-conid'>()</span>
<a name="line-279"></a> <span class='hs-varid'>copyChunks</span> <span class='hs-varop'>!</span><span class='hs-layout'>(</span><span class='hs-conid'>L</span><span class='hs-varop'>.</span><span class='hs-conid'>Chunk</span> <span class='hs-layout'>(</span><span class='hs-conid'>S</span><span class='hs-varop'>.</span><span class='hs-conid'>PS</span> <span class='hs-varid'>fpbuf</span> <span class='hs-varid'>o</span> <span class='hs-varid'>l</span><span class='hs-layout'>)</span> <span class='hs-varid'>lbs'</span><span class='hs-layout'>)</span> <span class='hs-varop'>!</span><span class='hs-varid'>pf</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
<a name="line-280"></a> <span class='hs-varid'>withForeignPtr</span> <span class='hs-varid'>fpbuf</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>pbuf</span> <span class='hs-keyglyph'>-></span>
<a name="line-281"></a> <span class='hs-varid'>copyBytes</span> <span class='hs-varid'>pf</span> <span class='hs-layout'>(</span><span class='hs-varid'>pbuf</span> <span class='hs-varop'>`plusPtr`</span> <span class='hs-varid'>o</span><span class='hs-layout'>)</span> <span class='hs-varid'>l</span>
<a name="line-282"></a> <span class='hs-varid'>copyChunks</span> <span class='hs-varid'>lbs'</span> <span class='hs-layout'>(</span><span class='hs-varid'>pf</span> <span class='hs-varop'>`plusPtr`</span> <span class='hs-varid'>l</span><span class='hs-layout'>)</span>
<a name="line-283"></a>
<a name="line-284"></a><a name="toByteString"></a><span class='hs-comment'>-- | Run the builder to construct a strict bytestring containing the sequence</span>
<a name="line-285"></a><span class='hs-comment'>-- of bytes denoted by the builder. This is done by first serializing to a lazy bytestring and then packing its</span>
<a name="line-286"></a><span class='hs-comment'>-- chunks to a appropriately sized strict bytestring.</span>
<a name="line-287"></a><span class='hs-comment'>--</span>
<a name="line-288"></a><span class='hs-comment'>-- > toByteString = packChunks . toLazyByteString</span>
<a name="line-289"></a><span class='hs-comment'>--</span>
<a name="line-290"></a><span class='hs-comment'>-- Note that @'toByteString'@ is a 'Monoid' homomorphism.</span>
<a name="line-291"></a><span class='hs-comment'>--</span>
<a name="line-292"></a><span class='hs-comment'>-- > toByteString mempty == mempty</span>
<a name="line-293"></a><span class='hs-comment'>-- > toByteString (x `mappend` y) == toByteString x `mappend` toByteString y</span>
<a name="line-294"></a><span class='hs-comment'>--</span>
<a name="line-295"></a><span class='hs-comment'>-- However, in the second equation, the left-hand-side is generally faster to</span>
<a name="line-296"></a><span class='hs-comment'>-- execute.</span>
<a name="line-297"></a><span class='hs-comment'>--</span>
<a name="line-298"></a><span class='hs-definition'>toByteString</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Builder</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>S</span><span class='hs-varop'>.</span><span class='hs-conid'>ByteString</span>
<a name="line-299"></a><span class='hs-definition'>toByteString</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>packChunks</span> <span class='hs-varop'>.</span> <span class='hs-varid'>toLazyByteString</span>
<a name="line-300"></a>
<a name="line-301"></a>
<a name="line-302"></a><a name="toByteStringIOWith"></a><span class='hs-comment'>-- | @toByteStringIOWith bufSize io b@ runs the builder @b@ with a buffer of</span>
<a name="line-303"></a><span class='hs-comment'>-- at least the size @bufSize@ and executes the 'IO' action @io@ whenever the</span>
<a name="line-304"></a><span class='hs-comment'>-- buffer is full.</span>
<a name="line-305"></a><span class='hs-comment'>--</span>
<a name="line-306"></a><span class='hs-comment'>-- Compared to 'toLazyByteStringWith' this function requires less allocation,</span>
<a name="line-307"></a><span class='hs-comment'>-- as the output buffer is only allocated once at the start of the</span>
<a name="line-308"></a><span class='hs-comment'>-- serialization and whenever something bigger than the current buffer size has</span>
<a name="line-309"></a><span class='hs-comment'>-- to be copied into the buffer, which should happen very seldomly for the</span>
<a name="line-310"></a><span class='hs-comment'>-- default buffer size of 32kb. Hence, the pressure on the garbage collector is</span>
<a name="line-311"></a><span class='hs-comment'>-- reduced, which can be an advantage when building long sequences of bytes.</span>
<a name="line-312"></a><span class='hs-comment'>--</span>
<a name="line-313"></a><span class='hs-definition'>toByteStringIOWith</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Int</span> <span class='hs-comment'>-- ^ Buffer size (upper bounds</span>
<a name="line-314"></a> <span class='hs-comment'>-- the number of bytes forced</span>
<a name="line-315"></a> <span class='hs-comment'>-- per call to the 'IO' action).</span>
<a name="line-316"></a> <span class='hs-keyglyph'>-></span> <span class='hs-layout'>(</span><span class='hs-conid'>S</span><span class='hs-varop'>.</span><span class='hs-conid'>ByteString</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>IO</span> <span class='hs-conid'>()</span><span class='hs-layout'>)</span> <span class='hs-comment'>-- ^ 'IO' action to execute per</span>
<a name="line-317"></a> <span class='hs-comment'>-- full buffer, which is</span>
<a name="line-318"></a> <span class='hs-comment'>-- referenced by a strict</span>
<a name="line-319"></a> <span class='hs-comment'>-- 'S.ByteString'.</span>
<a name="line-320"></a> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>Builder</span> <span class='hs-comment'>-- ^ 'Builder' to run.</span>
<a name="line-321"></a> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>IO</span> <span class='hs-conid'>()</span> <span class='hs-comment'>-- ^ Resulting 'IO' action.</span>
<a name="line-322"></a><span class='hs-definition'>toByteStringIOWith</span> <span class='hs-varid'>bufSize</span> <span class='hs-varid'>io</span> <span class='hs-layout'>(</span><span class='hs-conid'>Builder</span> <span class='hs-varid'>b</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span>
<a name="line-323"></a> <span class='hs-varid'>fillBuffer</span> <span class='hs-varid'>bufSize</span> <span class='hs-layout'>(</span><span class='hs-varid'>b</span> <span class='hs-layout'>(</span><span class='hs-varid'>buildStep</span> <span class='hs-varid'>finalStep</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<a name="line-324"></a> <span class='hs-keyword'>where</span>
<a name="line-325"></a> <span class='hs-varid'>finalStep</span> <span class='hs-varop'>!</span><span class='hs-layout'>(</span><span class='hs-conid'>BufRange</span> <span class='hs-varid'>pf</span> <span class='hs-keyword'>_</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>return</span> <span class='hs-varop'>$</span> <span class='hs-conid'>Done</span> <span class='hs-varid'>pf</span> <span class='hs-conid'>()</span>
<a name="line-326"></a>
<a name="line-327"></a> <span class='hs-varid'>fillBuffer</span> <span class='hs-varop'>!</span><span class='hs-varid'>size</span> <span class='hs-varid'>step</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
<a name="line-328"></a> <span class='hs-conid'>S</span><span class='hs-varop'>.</span><span class='hs-varid'>mallocByteString</span> <span class='hs-varid'>size</span> <span class='hs-varop'>>>=</span> <span class='hs-varid'>fill</span>
<a name="line-329"></a> <span class='hs-keyword'>where</span>
<a name="line-330"></a> <span class='hs-varid'>fill</span> <span class='hs-varid'>fpbuf</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span>
<a name="line-331"></a> <span class='hs-keyword'>let</span> <span class='hs-varop'>!</span><span class='hs-varid'>pf</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>unsafeForeignPtrToPtr</span> <span class='hs-varid'>fpbuf</span>
<a name="line-332"></a> <span class='hs-varop'>!</span><span class='hs-varid'>br</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>BufRange</span> <span class='hs-varid'>pf</span> <span class='hs-layout'>(</span><span class='hs-varid'>pf</span> <span class='hs-varop'>`plusPtr`</span> <span class='hs-varid'>size</span><span class='hs-layout'>)</span>
<a name="line-333"></a> <span class='hs-comment'>-- safe due to later reference of fpbuf</span>
<a name="line-334"></a> <span class='hs-comment'>-- BETTER than withForeignPtr, as we lose a tail call otherwise</span>
<a name="line-335"></a> <span class='hs-varid'>signal</span> <span class='hs-keyglyph'><-</span> <span class='hs-varid'>runBuildStep</span> <span class='hs-varid'>step</span> <span class='hs-varid'>br</span>
<a name="line-336"></a> <span class='hs-keyword'>case</span> <span class='hs-varid'>signal</span> <span class='hs-keyword'>of</span>
<a name="line-337"></a> <span class='hs-conid'>Done</span> <span class='hs-varid'>pf'</span> <span class='hs-keyword'>_</span> <span class='hs-keyglyph'>-></span> <span class='hs-varid'>io</span> <span class='hs-varop'>$</span> <span class='hs-conid'>S</span><span class='hs-varop'>.</span><span class='hs-conid'>PS</span> <span class='hs-varid'>fpbuf</span> <span class='hs-num'>0</span> <span class='hs-layout'>(</span><span class='hs-varid'>pf'</span> <span class='hs-varop'>`minusPtr`</span> <span class='hs-varid'>pf</span><span class='hs-layout'>)</span>
<a name="line-338"></a>
<a name="line-339"></a> <span class='hs-conid'>BufferFull</span> <span class='hs-varid'>minSize</span> <span class='hs-varid'>pf'</span> <span class='hs-varid'>nextStep</span> <span class='hs-keyglyph'>-></span> <span class='hs-keyword'>do</span>
<a name="line-340"></a> <span class='hs-varid'>io</span> <span class='hs-varop'>$</span> <span class='hs-conid'>S</span><span class='hs-varop'>.</span><span class='hs-conid'>PS</span> <span class='hs-varid'>fpbuf</span> <span class='hs-num'>0</span> <span class='hs-layout'>(</span><span class='hs-varid'>pf'</span> <span class='hs-varop'>`minusPtr`</span> <span class='hs-varid'>pf</span><span class='hs-layout'>)</span>
<a name="line-341"></a> <span class='hs-varid'>fillBuffer</span> <span class='hs-layout'>(</span><span class='hs-varid'>max</span> <span class='hs-varid'>bufSize</span> <span class='hs-varid'>minSize</span><span class='hs-layout'>)</span> <span class='hs-varid'>nextStep</span>
<a name="line-342"></a>
<a name="line-343"></a> <span class='hs-conid'>InsertByteString</span> <span class='hs-varid'>pf'</span> <span class='hs-varid'>bs</span> <span class='hs-varid'>nextStep</span> <span class='hs-keyglyph'>-></span> <span class='hs-keyword'>do</span>
<a name="line-344"></a> <span class='hs-varid'>io</span> <span class='hs-varop'>$</span> <span class='hs-conid'>S</span><span class='hs-varop'>.</span><span class='hs-conid'>PS</span> <span class='hs-varid'>fpbuf</span> <span class='hs-num'>0</span> <span class='hs-layout'>(</span><span class='hs-varid'>pf'</span> <span class='hs-varop'>`minusPtr`</span> <span class='hs-varid'>pf</span><span class='hs-layout'>)</span>
<a name="line-345"></a> <span class='hs-varid'>unless</span> <span class='hs-layout'>(</span><span class='hs-conid'>S</span><span class='hs-varop'>.</span><span class='hs-varid'>null</span> <span class='hs-varid'>bs</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>io</span> <span class='hs-varid'>bs</span><span class='hs-layout'>)</span>
<a name="line-346"></a> <span class='hs-varid'>fillBuffer</span> <span class='hs-varid'>bufSize</span> <span class='hs-varid'>nextStep</span>
<a name="line-347"></a>
<a name="line-348"></a><a name="toByteStringIO"></a><span class='hs-comment'>-- | Run the builder with a 'defaultBufferSize'd buffer and execute the given</span>
<a name="line-349"></a><span class='hs-comment'>-- 'IO' action whenever the buffer is full or gets flushed.</span>
<a name="line-350"></a><span class='hs-comment'>--</span>
<a name="line-351"></a><span class='hs-comment'>-- @ 'toByteStringIO' = 'toByteStringIOWith' 'defaultBufferSize'@</span>
<a name="line-352"></a><span class='hs-comment'>--</span>
<a name="line-353"></a><span class='hs-comment'>-- This is a 'Monoid' homomorphism in the following sense.</span>
<a name="line-354"></a><span class='hs-comment'>--</span>
<a name="line-355"></a><span class='hs-comment'>-- > toByteStringIO io mempty == return ()</span>
<a name="line-356"></a><span class='hs-comment'>-- > toByteStringIO io (x `mappend` y) == toByteStringIO io x >> toByteStringIO io y</span>
<a name="line-357"></a><span class='hs-comment'>--</span>
<a name="line-358"></a><span class='hs-definition'>toByteStringIO</span> <span class='hs-keyglyph'>::</span> <span class='hs-layout'>(</span><span class='hs-conid'>S</span><span class='hs-varop'>.</span><span class='hs-conid'>ByteString</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>IO</span> <span class='hs-conid'>()</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>Builder</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>IO</span> <span class='hs-conid'>()</span>
<a name="line-359"></a><span class='hs-definition'>toByteStringIO</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>toByteStringIOWith</span> <span class='hs-varid'>defaultBufferSize</span>
<a name="line-360"></a><span class='hs-comment'>{-# INLINE toByteStringIO #-}</span>
<a name="line-361"></a>
<a name="line-362"></a><a name="writeToByteString"></a><span class='hs-comment'>-- | Run a 'Write' to produce a strict 'S.ByteString'.</span>
<a name="line-363"></a><span class='hs-comment'>-- This is equivalent to @('toByteString' . 'fromWrite')@, but is more</span>
<a name="line-364"></a><span class='hs-comment'>-- efficient because it uses just one appropriately-sized buffer.</span>
<a name="line-365"></a><span class='hs-definition'>writeToByteString</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Write</span> <span class='hs-keyglyph'>-></span> <span class='hs-conid'>S</span><span class='hs-varop'>.</span><span class='hs-conid'>ByteString</span>
<a name="line-366"></a><a name="!"></a><span class='hs-definition'>writeToByteString</span> <span class='hs-varop'>!</span><span class='hs-varid'>w</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>unsafeDupablePerformIO</span> <span class='hs-varop'>$</span> <span class='hs-keyword'>do</span>
<a name="line-367"></a> <span class='hs-varid'>fptr</span> <span class='hs-keyglyph'><-</span> <span class='hs-conid'>S</span><span class='hs-varop'>.</span><span class='hs-varid'>mallocByteString</span> <span class='hs-layout'>(</span><span class='hs-varid'>getBound</span> <span class='hs-varid'>w</span><span class='hs-layout'>)</span>
<a name="line-368"></a> <span class='hs-varid'>len</span> <span class='hs-keyglyph'><-</span> <span class='hs-varid'>withForeignPtr</span> <span class='hs-varid'>fptr</span> <span class='hs-varop'>$</span> <span class='hs-keyglyph'>\</span><span class='hs-varid'>ptr</span> <span class='hs-keyglyph'>-></span> <span class='hs-keyword'>do</span>
<a name="line-369"></a> <span class='hs-varid'>end</span> <span class='hs-keyglyph'><-</span> <span class='hs-varid'>runWrite</span> <span class='hs-varid'>w</span> <span class='hs-varid'>ptr</span>
<a name="line-370"></a> <span class='hs-varid'>return</span> <span class='hs-varop'>$!</span> <span class='hs-varid'>end</span> <span class='hs-varop'>`minusPtr`</span> <span class='hs-varid'>ptr</span>
<a name="line-371"></a> <span class='hs-varid'>return</span> <span class='hs-varop'>$!</span> <span class='hs-conid'>S</span><span class='hs-varop'>.</span><span class='hs-varid'>fromForeignPtr</span> <span class='hs-varid'>fptr</span> <span class='hs-num'>0</span> <span class='hs-varid'>len</span>
<a name="line-372"></a><span class='hs-comment'>{-# INLINE writeToByteString #-}</span>
<a name="line-373"></a>
<a name="line-374"></a><span class='hs-comment'>------------------------------------------------------------------------------</span>
<a name="line-375"></a><span class='hs-comment'>-- Draft of new builder/put execution code</span>
<a name="line-376"></a><span class='hs-comment'>------------------------------------------------------------------------------</span>
<a name="line-377"></a>
<a name="line-378"></a><span class='hs-comment'>{- FIXME: Generalize this code such that it can replace the above clunky
<a name="line-379"></a> - implementations.
<a name="line-380"></a>
<a name="line-381"></a>-- | A monad for lazily composing lazy bytestrings using continuations.
<a name="line-382"></a>newtype LBSM a = LBSM { unLBSM :: (a, L.ByteString -> L.ByteString) }
<a name="line-383"></a>
<a name="line-384"></a>instance Monad LBSM where
<a name="line-385"></a> return x = LBSM (x, id)
<a name="line-386"></a> (LBSM (x,k)) >>= f = let LBSM (x',k') = f x in LBSM (x', k . k')
<a name="line-387"></a> (LBSM (_,k)) >> (LBSM (x',k')) = LBSM (x', k . k')
<a name="line-388"></a>
<a name="line-389"></a>-- | Execute a put and return the written buffers as the chunks of a lazy
<a name="line-390"></a>-- bytestring.
<a name="line-391"></a>toLazyByteString :: Put a -> (a, L.ByteString)
<a name="line-392"></a>toLazyByteString put =
<a name="line-393"></a> (fst result, k (bufToLBSCont (snd result) L.empty))
<a name="line-394"></a> where
<a name="line-395"></a>
<a name="line-396"></a> -- FIXME: Check with ByteString guys why allocation in inlinePerformIO is
<a name="line-397"></a> -- bad.
<a name="line-398"></a>
<a name="line-399"></a> -- initial buffer
<a name="line-400"></a> buf0 = S.inlinePerformIO $ allocBuffer defaultBufferSize
<a name="line-401"></a> -- run put, but don't force result => we're lazy enough
<a name="line-402"></a> LBSM (result, k) = runPut liftIO outputBuf outputBS put buf0
<a name="line-403"></a> -- convert a buffer to a lazy bytestring continuation
<a name="line-404"></a> bufToLBSCont = maybe id L.Chunk . unsafeFreezeNonEmptyBuffer
<a name="line-405"></a> -- lifting an io putsignal to a lazy bytestring monad
<a name="line-406"></a> liftIO io = LBSM (S.inlinePerformIO io, id)
<a name="line-407"></a> -- add buffer as a chunk prepare allocation of new one
<a name="line-408"></a> outputBuf minSize buf = LBSM
<a name="line-409"></a> ( S.inlinePerformIO $ allocBuffer (max minSize defaultBufferSize)
<a name="line-410"></a> , bufToLBSCont buf )
<a name="line-411"></a> -- add bytestring directly as a chunk; exploits postcondition of runPut
<a name="line-412"></a> -- that bytestrings are non-empty
<a name="line-413"></a> outputBS bs = LBSM ((), L.Chunk bs)
<a name="line-414"></a>
<a name="line-415"></a>
<a name="line-416"></a>{-
<a name="line-417"></a>-- | A Builder that traces a message
<a name="line-418"></a>traceBuilder :: String -> Builder
<a name="line-419"></a>traceBuilder msg = fromBuildStepCont $ \k br@(BufRange op ope) -> do
<a name="line-420"></a> putStrLn $ "traceBuilder " ++ show (op, ope) ++ ": " ++ msg
<a name="line-421"></a> k br
<a name="line-422"></a>
<a name="line-423"></a>test2 :: Word8 -> [S.ByteString]
<a name="line-424"></a>test2 x = L.toChunks $ toLazyByteString2 $ fromBuilder $ mconcat
<a name="line-425"></a> [ traceBuilder "before flush"
<a name="line-426"></a> , fromWord8 48
<a name="line-427"></a> , flushBuilder
<a name="line-428"></a> , flushBuilder
<a name="line-429"></a> , traceBuilder "after flush"
<a name="line-430"></a> , fromWord8 x
<a name="line-431"></a> ]
<a name="line-432"></a>
<a name="line-433"></a>-}
<a name="line-434"></a>
<a name="line-435"></a>-}</span>
</pre></body>
</html>
|