include/boost/http/zstd/compress.hpp

100.0% Lines (1/0/1) 100.0% List of functions (1/0/1)
compress.hpp
f(x) Functions (1)
Line TLA Hits Source Code
1 //
2 // Copyright (c) 2026 Mohammad Nejati
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // Official repository: https://github.com/cppalliance/http
8 //
9
10 #ifndef BOOST_HTTP_ZSTD_COMPRESS_HPP
11 #define BOOST_HTTP_ZSTD_COMPRESS_HPP
12
13 #include <boost/http/detail/config.hpp>
14 #include <boost/http/zstd/error.hpp>
15 #include <boost/http/zstd/service.hpp>
16 #include <boost/http/zstd/types.hpp>
17
18 #include <boost/capy/ex/execution_context.hpp>
19
20 #include <cstddef>
21
22 namespace boost {
23 namespace http {
24 namespace zstd {
25
26 /** Opaque structure that holds compression context state.
27
28 A context is created with @ref compress_service::create_cctx
29 and released with @ref compress_service::free_cctx. It holds
30 the sticky parameters and the state of the frame being
31 compressed, and may be reused for successive frames.
32 */
33 struct cctx;
34
35 /** Opaque structure that holds a digested compression dictionary.
36
37 Created with @ref compress_service::create_cdict and released
38 with @ref compress_service::free_cdict. A digested dictionary
39 is read-only and may be shared by multiple contexts and threads.
40 */
41 struct cdict;
42
43 /** Streaming end directives.
44
45 These values control how @ref compress_service::compress_stream
46 treats the input it is given.
47 */
48 enum class end_directive
49 {
50 /** Collect more data; the encoder decides when to emit output. */
51 continue_ = 0,
52
53 /** Flush all data provided so far.
54
55 Creates at least one new block that can be decoded
56 immediately on reception. The frame continues, so
57 future data can still reference previous content.
58 */
59 flush = 1,
60
61 /** Flush all remaining data and close the current frame. */
62 end = 2
63 };
64
65 /** Compression strategies, listed from fastest to strongest.
66
67 Selected with the @ref c_parameter::strategy parameter.
68 New strategies may be added in the future; only the
69 ordering from fast to strong is guaranteed.
70 */
71 enum class strategy
72 {
73 fast = 1,
74 dfast = 2,
75 greedy = 3,
76 lazy = 4,
77 lazy2 = 5,
78 btlazy2 = 6,
79 btopt = 7,
80 btultra = 8,
81 btultra2 = 9
82 };
83
84 /** Compression parameter identifiers.
85
86 These values identify parameters that can be set on a
87 compression context with @ref compress_service::set_parameter.
88 Parameters are sticky: once set they apply to every frame
89 compressed with that context until the context's parameters
90 are reset. For the bounded parameters, a value of zero
91 means "use the default".
92 */
93 enum class c_parameter
94 {
95 /** Compression level; negative values select faster modes. */
96 compression_level = 100,
97
98 /** Maximum back-reference distance, as a power of 2.
99
100 This sets the memory budget for streaming decompression,
101 with larger values requiring more memory and typically
102 compressing better.
103 */
104 window_log = 101,
105
106 /** Size of the initial probe table, as a power of 2. */
107 hash_log = 102,
108
109 /** Size of the multi-probe search table, as a power of 2. */
110 chain_log = 103,
111
112 /** Number of search attempts, as a power of 2. */
113 search_log = 104,
114
115 /** Minimum size of searched matches. */
116 min_match = 105,
117
118 /** Match length considered "good enough" to stop searching. */
119 target_length = 106,
120
121 /** Compression strategy, see @ref boost::http::zstd::strategy. */
122 strategy = 107,
123
124 /** Enable long distance matching for large inputs. */
125 enable_long_distance_matching = 160,
126
127 /** Size of the long distance matching table, as a power of 2. */
128 ldm_hash_log = 161,
129
130 /** Minimum match size for the long distance matcher. */
131 ldm_min_match = 162,
132
133 /** Log size of each bucket in the long distance matching table. */
134 ldm_bucket_size_log = 163,
135
136 /** Frequency of inserting entries into the long distance matching table. */
137 ldm_hash_rate_log = 164,
138
139 /** Write the content size into the frame header whenever known (default: 1). */
140 content_size_flag = 200,
141
142 /** Write a 32-bit checksum of the content at the end of the frame (default: 0). */
143 checksum_flag = 201,
144
145 /** Write the dictionary ID into the frame header when applicable (default: 1). */
146 dict_id_flag = 202,
147
148 /** Number of worker threads; zero selects single-threaded mode. */
149 nb_workers = 400,
150
151 /** Size of a compression job when using worker threads. */
152 job_size = 401,
153
154 /** Overlap between jobs, as a fraction of the window size (0-9). */
155 overlap_log = 402
156 };
157
158 /** Provides the Zstandard compression API.
159
160 This service interface exposes Zstandard compression
161 functionality through a set of virtual functions. Data
162 can be compressed in one shot with @ref compress or
163 @ref compress2, or incrementally with @ref compress_stream.
164
165 Most functions return a `std::size_t` which is either a
166 byte count or an encoded error code. Test results with
167 @ref is_error and convert them with @ref get_error_code
168 or @ref get_error_name.
169
170 Compression contexts are reusable: after a frame is
171 complete, the same context can compress another frame,
172 keeping the parameters that were set on it.
173
174 @code
175 // Example: Simple one-shot compression
176 auto& compressor = boost::http::zstd::install_compress_service(ctx);
177
178 std::vector<char> input = get_input();
179 std::vector<char> output(compressor.compress_bound(input.size()));
180
181 std::size_t n = compressor.compress(
182 output.data(), output.size(),
183 input.data(), input.size(),
184 compressor.default_level());
185
186 if (! compressor.is_error(n))
187 {
188 output.resize(n);
189 // Use compressed data
190 }
191 @endcode
192
193 @code
194 // Example: Streaming compression
195 auto* ctx = compressor.create_cctx();
196
197 compressor.set_parameter(ctx,
198 boost::http::zstd::c_parameter::compression_level, 5);
199 compressor.set_parameter(ctx,
200 boost::http::zstd::c_parameter::checksum_flag, 1);
201
202 std::vector<char> buf(compressor.stream_out_size());
203 boost::http::zstd::in_buffer in{ input.data(), input.size(), 0 };
204 std::size_t remaining;
205 do
206 {
207 boost::http::zstd::out_buffer out{ buf.data(), buf.size(), 0 };
208 remaining = compressor.compress_stream(ctx, out, in,
209 boost::http::zstd::end_directive::end);
210 if (compressor.is_error(remaining))
211 break;
212 output.insert(output.end(), buf.data(), buf.data() + out.pos);
213 }
214 while (remaining != 0);
215
216 compressor.free_cctx(ctx);
217 @endcode
218 */
219 struct BOOST_SYMBOL_VISIBLE
220 compress_service
221 : capy::execution_context::service
222 {
223 /** Return the Zstandard library version number.
224 @return The version as `MAJOR * 10000 + MINOR * 100 + RELEASE`.
225 */
226 virtual
227 unsigned
228 version_number() const noexcept = 0;
229
230 /** Return the Zstandard library version string.
231 @return Pointer to a string such as "1.5.7".
232 */
233 virtual
234 char const*
235 version_string() const noexcept = 0;
236
237 /** Return the minimum compression level.
238 @return The most negative level allowed.
239 */
240 virtual
241 int
242 min_level() const noexcept = 0;
243
244 /** Return the maximum compression level.
245 @return The highest level available.
246 */
247 virtual
248 int
249 max_level() const noexcept = 0;
250
251 /** Return the default compression level.
252 @return The level used when none is specified.
253 */
254 virtual
255 int
256 default_level() const noexcept = 0;
257
258 /** Return the maximum compressed size in the worst case.
259 @param src_size The size of the input data.
260 @return An upper bound on the compressed size of a
261 single frame, or an error code if `src_size`
262 is too large.
263 */
264 virtual
265 std::size_t
266 compress_bound(std::size_t src_size) const noexcept = 0;
267
268 /** Compress data in one call as a single frame.
269 @param dst Output buffer.
270 @param dst_capacity Output buffer size.
271 @param src Input data.
272 @param src_size Input data size.
273 @param level The compression level.
274 @return The compressed size, or an error code.
275 */
276 virtual
277 std::size_t
278 compress(
279 void* dst,
280 std::size_t dst_capacity,
281 void const* src,
282 std::size_t src_size,
283 int level) const noexcept = 0;
284
285 /** Create a new compression context.
286 @return Pointer to the context, or nullptr on error.
287 */
288 virtual
289 cctx*
290 create_cctx() const noexcept = 0;
291
292 /** Release a compression context.
293 @param ctx The context to release; may be nullptr.
294 @return Zero, or an error code.
295 */
296 virtual
297 std::size_t
298 free_cctx(cctx* ctx) const noexcept = 0;
299
300 /** Return the current memory usage of a compression context.
301 @param ctx The context.
302 @return Memory usage in bytes.
303 */
304 virtual
305 std::size_t
306 sizeof_cctx(cctx const* ctx) const noexcept = 0;
307
308 /** Return the valid bounds of a compression parameter.
309 @param param The parameter identifier.
310 @return The bounds; test the `error` field with @ref is_error.
311 */
312 virtual
313 bounds
314 param_bounds(c_parameter param) const noexcept = 0;
315
316 /** Set a compression parameter.
317
318 Parameters can only be set between frames, before
319 compression of the next frame starts. Values beyond
320 the bounds are either clamped or rejected, depending
321 on the parameter.
322
323 @param ctx The context.
324 @param param The parameter identifier.
325 @param value The parameter value.
326 @return Zero, or an error code.
327 */
328 virtual
329 std::size_t
330 set_parameter(
331 cctx* ctx,
332 c_parameter param,
333 int value) const noexcept = 0;
334
335 /** Declare the total input size of the next frame.
336
337 The value is written into the frame header and checked
338 at the end of the frame. It applies to the next frame
339 only; afterwards the size reverts to unknown.
340
341 @param ctx The context.
342 @param pledged_src_size The input size, or
343 @ref content_size_unknown.
344 @return Zero, or an error code.
345 */
346 virtual
347 std::size_t
348 set_pledged_src_size(
349 cctx* ctx,
350 unsigned long long pledged_src_size) const noexcept = 0;
351
352 /** Reset a compression context.
353 @param ctx The context.
354 @param directive What to reset.
355 @return Zero, or an error code.
356 */
357 virtual
358 std::size_t
359 reset(
360 cctx* ctx,
361 reset_directive directive) const noexcept = 0;
362
363 /** Compress data in one call using a context's parameters.
364
365 Always starts a new frame; any unfinished frame held
366 by the context is discarded.
367
368 @param ctx The context.
369 @param dst Output buffer.
370 @param dst_capacity Output buffer size.
371 @param src Input data.
372 @param src_size Input data size.
373 @return The compressed size, or an error code.
374 */
375 virtual
376 std::size_t
377 compress2(
378 cctx* ctx,
379 void* dst,
380 std::size_t dst_capacity,
381 void const* src,
382 std::size_t src_size) const noexcept = 0;
383
384 /** Compress data in streaming mode.
385
386 Consumes input from `input` and writes output to
387 `output`, advancing the `pos` field of each. Input
388 may not be fully consumed if the output buffer fills
389 up; present the remaining input again after making
390 room for more output.
391
392 @param ctx The context.
393 @param output The output buffer.
394 @param input The input buffer.
395 @param end_op The end directive.
396 @return A minimum estimate of the bytes still buffered
397 internally, or an error code. With
398 @ref end_directive::flush or @ref end_directive::end,
399 keep calling with the same directive until zero
400 is returned.
401 */
402 virtual
403 std::size_t
404 compress_stream(
405 cctx* ctx,
406 out_buffer& output,
407 in_buffer& input,
408 end_directive end_op) const noexcept = 0;
409
410 /** Return the recommended input buffer size for streaming.
411 @return Size in bytes.
412 */
413 virtual
414 std::size_t
415 stream_in_size() const noexcept = 0;
416
417 /** Return the recommended output buffer size for streaming.
418
419 An output buffer of this size is guaranteed to be able
420 to flush at least one complete compressed block.
421
422 @return Size in bytes.
423 */
424 virtual
425 std::size_t
426 stream_out_size() const noexcept = 0;
427
428 /** Create a digested dictionary for compression.
429 @param dict The dictionary content; copied internally.
430 @param dict_size The dictionary size.
431 @param level The compression level to digest for.
432 @return Pointer to the dictionary, or nullptr on error.
433 */
434 virtual
435 cdict*
436 create_cdict(
437 void const* dict,
438 std::size_t dict_size,
439 int level) const noexcept = 0;
440
441 /** Release a digested dictionary.
442 @param dict The dictionary to release; may be nullptr.
443 @return Zero, or an error code.
444 */
445 virtual
446 std::size_t
447 free_cdict(cdict* dict) const noexcept = 0;
448
449 /** Return the current memory usage of a digested dictionary.
450 @param dict The dictionary.
451 @return Memory usage in bytes.
452 */
453 virtual
454 std::size_t
455 sizeof_cdict(cdict const* dict) const noexcept = 0;
456
457 /** Load a dictionary into a context.
458
459 The content is copied and digested; it is used for all
460 future frames until the parameters are reset or another
461 dictionary is loaded. Loading a null or empty dictionary
462 returns to no-dictionary mode.
463
464 @param ctx The context.
465 @param dict The dictionary content.
466 @param dict_size The dictionary size.
467 @return Zero, or an error code.
468 */
469 virtual
470 std::size_t
471 load_dictionary(
472 cctx* ctx,
473 void const* dict,
474 std::size_t dict_size) const noexcept = 0;
475
476 /** Reference a digested dictionary from a context.
477
478 The dictionary is only referenced and must outlive its
479 use by the context. Its compression parameters supersede
480 those set on the context. Referencing nullptr returns
481 to no-dictionary mode.
482
483 @param ctx The context.
484 @param dict The digested dictionary.
485 @return Zero, or an error code.
486 */
487 virtual
488 std::size_t
489 ref_cdict(
490 cctx* ctx,
491 cdict const* dict) const noexcept = 0;
492
493 /** Reference a prefix for the next frame.
494
495 A prefix is a single-use dictionary of raw content,
496 discarded once the frame ends. The buffer is only
497 referenced and must remain valid and unmodified while
498 the frame is compressed.
499
500 @param ctx The context.
501 @param prefix The prefix content.
502 @param prefix_size The prefix size.
503 @return Zero, or an error code.
504 */
505 virtual
506 std::size_t
507 ref_prefix(
508 cctx* ctx,
509 void const* prefix,
510 std::size_t prefix_size) const noexcept = 0;
511
512 /** Return the dictionary ID stored within a dictionary.
513 @param dict The dictionary content.
514 @param dict_size The dictionary size.
515 @return The dictionary ID, or zero if the content is
516 not a conformant dictionary.
517 */
518 virtual
519 unsigned
520 get_dict_id_from_dict(
521 void const* dict,
522 std::size_t dict_size) const noexcept = 0;
523
524 /** Check whether a result is an error code.
525 @param result A value returned from a function of this service.
526 @return True if the result encodes an error.
527 */
528 virtual
529 bool
530 is_error(std::size_t result) const noexcept = 0;
531
532 /** Convert a result to an error code.
533 @param result A value returned from a function of this service.
534 @return The error code, or @ref error::no_error.
535 */
536 virtual
537 error
538 get_error_code(std::size_t result) const noexcept = 0;
539
540 /** Return a readable description of a result.
541 @param result A value returned from a function of this service.
542 @return Pointer to a description string.
543 */
544 virtual
545 char const*
546 get_error_name(std::size_t result) const noexcept = 0;
547
548 /** Return a string description of an error code.
549 @param c The error code.
550 @return Pointer to error description string.
551 */
552 virtual
553 char const*
554 error_string(error c) const noexcept = 0;
555
556 protected:
557 5x void shutdown() override {}
558 };
559
560 } // zstd
561 } // http
562 } // boost
563
564 #endif
565