]> git.ipfire.org Git - thirdparty/squid.git/blob - src/base/Packable.h
SourceFormat Enforcement
[thirdparty/squid.git] / src / base / Packable.h
1 /*
2 * Copyright (C) 1996-2017 The Squid Software Foundation and contributors
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
8
9 #ifndef SQUID_SRC_BASE_PACKABLE_H
10 #define SQUID_SRC_BASE_PACKABLE_H
11
12 /**
13 * A uniform interface to store-like modules
14 *
15 * Rationale:
16 * ----------
17 *
18 * We have two major interfaces Comm and Store, which take a variety of
19 * different data buffering objects and have different output actions
20 * to be performed on data.
21 *
22 * Store has a nice storeAppend[Printf] capability which makes "storing"
23 * things easy and painless.
24 *
25 * Comm lacks commAppend[Printf] because Comm does not handle its own
26 * buffers (no mem_obj equivalent for Comm).
27 *
28 * Thus, if one wants to be able to Store _and_ Comm::Write an object, 'e
29 * has to implement almost identical functions for using all the data
30 * storage objects and their associated actions. Doing this for all the
31 * available data storage types is a tedious nightmare of almost-duplicated
32 * code.
33 *
34 * Packer
35 * ------
36 *
37 * Objects inheriting from Packable provide a uniform interface for code to
38 * assemble data before passing to Store and Comm modules.
39 *
40 * Packable objects have their own append and printf routines that "know"
41 * where to send incoming data. In case of Store interface, sending data to
42 * storeAppend. Packable buffer objects retain the data such that it can be
43 * flushed later to Comm::Write.
44 *
45 * Thus, one can write just one function that will take a Packable object
46 * and either "pack" things for Comm::Write or "append" things to Store,
47 * depending on actual Packable object supplied.
48 *
49 * XXX: Misnamed. This is a Packer or Packager API (i.e., "something that packs
50 * or packages others"); this is not a "something that can be packed" API.
51 */
52 class Packable
53 {
54 public:
55 virtual ~Packable() {}
56
57 /// Appends a c-string to existing packed data.
58 virtual void append(const char *buf, int size) = 0;
59
60 /// Append operation with printf-style arguments.
61 void appendf(const char *fmt,...) PRINTF_FORMAT_ARG2
62 {
63 va_list args;
64 va_start(args, fmt);
65 vappendf(fmt, args);
66 va_end(args);
67 }
68
69 /** Append operation, with vsprintf(3)-style arguments.
70 *
71 * \note arguments may be evaluated more than once, be careful
72 * of side-effects
73 *
74 * XXX: This method either should not exist or should not be virtual.
75 * Kids should not be forced to re-implement vappendf() logic.
76 * That logic should be implemented once, using other [Packable] APIs.
77 * Packable is not about providing a printf(3) service. Packable
78 * is about writing opaque data to various custom destinations.
79 */
80 virtual void vappendf(const char *fmt, va_list ap) = 0;
81
82 /** start buffering appends (if relevant)
83 *
84 * Indicates that a number of small appends are about to
85 * follow so would be detrimental to trigger expensive
86 * activity on each.
87 */
88 virtual void buffer() {}
89
90 /** perform a buffer flush (if relevant)
91 *
92 * Used by code such as PackableStream, that assumes the
93 * Packable leads to some form of output buffer.
94 */
95 virtual void flush() {}
96 };
97
98 #endif /* SQUID_SRC_BASE_PACKABLE_H */
99