1 #ifndef SRL_ENC_H_
2 #define SRL_ENC_H_
3 
4 #include "EXTERN.h"
5 #include "perl.h"
6 
7 /* General 'config' constants */
8 #ifdef MEMDEBUG
9 #   define INITIALIZATION_SIZE 1
10 #else
11 #   define INITIALIZATION_SIZE 64
12 #endif
13 
14 #include "srl_inline.h"
15 #include "srl_buffer_types.h"
16 
17 typedef struct PTABLE * ptable_ptr;
18 typedef struct {
19     srl_buffer_t buf;
20     srl_buffer_t tmp_buf;     /* temporary buffer for swapping */
21 
22     U32 operational_flags;    /* flags that pertain to one encode run (rather than being options): See SRL_OF_* defines */
23     U32 flags;                /* flag-like options: See SRL_F_* defines */
24     U32 protocol_version;     /* The version of the Sereal protocol to emit. */
25     UV max_recursion_depth;   /* Configurable limit on the number of recursive calls we're willing to make */
26 
27     UV recursion_depth;       /* current Perl-ref recursion depth */
28     ptable_ptr ref_seenhash;  /* ptr table for avoiding circular refs */
29     ptable_ptr weak_seenhash; /* ptr table for avoiding dangling weakrefs */
30     ptable_ptr str_seenhash;  /* ptr table for issuing COPY commands based on PTRS (used for classnames and keys)
31                                * for now this is also coopted to track which objects we have dumped as objects,
32                                * and to ensure we only output a given object once.
33                                * Possibly this should be replaced with freezeobj_svhash, but this works fine.
34                                */
35     ptable_ptr freezeobj_svhash; /* ptr table for tracking objects and their frozen replacments via FREEZE */
36     HV *string_deduper_hv;    /* track strings we have seen before, by content */
37 
38     void *snappy_workmem;     /* lazily allocated if and only if using Snappy */
39     IV compress_threshold;    /* do not compress things smaller than this even if compression enabled */
40     IV compress_level;        /* For ZLIB and ZSTD, the compression level */
41 
42                               /* only used if SRL_F_ENABLE_FREEZE_SUPPORT is set. */
43     SV *sereal_string_sv;     /* SV that says "Sereal" for FREEZE support */
44     SV *scratch_sv;           /* SV used by encoder for scratch operations */
45 } srl_encoder_t;
46 
47 typedef struct {
48     SV *sv;
49     U32 hash;
50 } sv_with_hash;
51 
52 typedef struct {
53     union {
54         SV *sv;
55     } key;
56     union {
57         HE *he;
58         SV *sv;
59     } val;
60 } HE_SV;
61 
62 /* constructor from options */
63 srl_encoder_t *srl_build_encoder_struct(pTHX_ HV *opt, sv_with_hash *options);
64 
65 /* clone; "constructor from prototype" */
66 srl_encoder_t *srl_build_encoder_struct_alike(pTHX_ srl_encoder_t *proto);
67 
68 void srl_clear_encoder(pTHX_ srl_encoder_t *enc);
69 
70 /* Explicit destructor */
71 void srl_destroy_encoder(pTHX_ srl_encoder_t *enc);
72 
73 /* Write Sereal packet header to output buffer */
74 void srl_write_header(pTHX_ srl_encoder_t *enc, SV *user_header_src, const U32 compress_flags);
75 /* Start dumping a top-level SV */
76 SV *srl_dump_data_structure_mortal_sv(pTHX_ srl_encoder_t *enc, SV *src, SV *user_header_src, const U32 flags);
77 
78 
79 /* define option bits in srl_encoder_t's flags member */
80 
81 /* Will default to "on". If set, hash keys will be shared using COPY.
82  * Corresponds to the inverse of constructor option "no_shared_hashkeys" */
83 #define SRL_F_SHARED_HASHKEYS                   0x00001UL
84 /* If set, then we're using the OO interface and we shouldn't destroy the
85  * encoder struct during SAVEDESTRUCTOR_X time */
86 #define SRL_F_REUSE_ENCODER                     0x00002UL
87 /* If set in flags, then we rather croak than serialize an object.
88  * Corresponds to the 'croak_on_bless' option to the Perl constructor. */
89 #define SRL_F_CROAK_ON_BLESS                    0x00004UL
90 /* If set in flags, then we will emit <undef> for all data types
91  * that aren't supported.  Corresponds to the 'undef_unknown' option. */
92 #define SRL_F_UNDEF_UNKNOWN                     0x00008UL
93 /* If set in flags, then we will stringify (SvPV) all data types
94  * that aren't supported.  Corresponds to the 'stringify_unknown' option. */
95 #define SRL_F_STRINGIFY_UNKNOWN                 0x00010UL
96 /* If set in flags, then we warn() when trying to serialize an unsupported
97  * data structure.  Applies only if stringify_unknown or undef_unknown are
98  * set since we otherwise croak.  Corresponds to the 'warn_unknown' option. */
99 #define SRL_F_WARN_UNKNOWN                      0x00020UL
100 
101 /* WARNING:
102  * #define SRL_F_COMPRESS_SNAPPY               0x00040UL
103  * #define SRL_F_COMPRESS_SNAPPY_INCREMENTAL   0x00080UL
104  * #define SRL_F_COMPRESS_ZLIB                 0x00100UL
105  * are moved to srl_compress.h
106  * note that there is SRL_F_COMPRESS_ZSTD defined below
107  */
108 
109 /* Only meaningful if SRL_F_WARN_UNKNOWN also set. If this one is set, then we don't warn
110  * if the unsupported item has string overloading. */
111 #define SRL_F_NOWARN_UNKNOWN_OVERLOAD           0x00200UL
112 
113 /* Only meaningful if SRL_F_WARN_UNKNOWN also set. If this one is set, then we don't warn
114  * if the unsupported item has string overloading. */
115 #define SRL_F_SORT_KEYS                         0x00400UL
116 
117 /* If set, use a hash to emit COPY() tags for all duplicated strings
118  * (slow, but great compression) */
119 #define SRL_F_DEDUPE_STRINGS                    0x00800UL
120 
121 /* Like SRL_F_DEDUPE_STRINGS but emits ALIAS() instead of COPY() for
122  * non-class-name, non-hash-key strings that are deduped. If set,
123  * supersedes SRL_F_DEDUPE_STRINGS. */
124 #define SRL_F_ALIASED_DEDUPE_STRINGS            0x01000UL
125 
126 /* If set in flags, then we serialize objects without class information.
127  * Corresponds to the 'no_bless_objects' flag found in the Decoder. */
128 #define SRL_F_NO_BLESS_OBJECTS                  0x02000UL
129 
130 /* If set in flags, then support calling FREEZE method on objects. */
131 #define SRL_F_ENABLE_FREEZE_SUPPORT             0x04000UL
132 
133 /* if set in flags, then do not use ARRAYREF or HASHREF ever */
134 #define SRL_F_CANONICAL_REFS                    0x08000UL
135 
136 #define SRL_F_SORT_KEYS_PERL                    0x10000UL
137 #define SRL_F_SORT_KEYS_PERL_REV                0x20000UL
138 
139 /* WARNING:
140  * SRL_F_COMPRESS_ZSTD is defined in srl_compress.h
141  * #define SRL_F_COMPRESS_ZSTD                  0x40000UL
142  */
143 
144 /* ====================================================================
145  * oper flags
146  */
147 /* Set while the encoder is in active use / dirty */
148 #define SRL_OF_ENCODER_DIRTY                 1UL
149 
150 #define SRL_ENC_HAVE_OPTION(enc, flag_num) ((enc)->flags & (flag_num))
151 #define SRL_ENC_SET_OPTION(enc, flag_num) STMT_START {(enc)->flags |= (flag_num);}STMT_END
152 #define SRL_ENC_RESET_OPTION(enc, flag_num) STMT_START {(enc)->flags &= ~(flag_num);}STMT_END
153 
154 #define SRL_ENC_HAVE_OPER_FLAG(enc, flag_num) ((enc)->operational_flags & (flag_num))
155 #define SRL_ENC_SET_OPER_FLAG(enc, flag_num) STMT_START {(enc)->operational_flags |= (flag_num);}STMT_END
156 #define SRL_ENC_RESET_OPER_FLAG(enc, flag_num) STMT_START {(enc)->operational_flags &= ~(flag_num);}STMT_END
157 
158 #define SRL_ENC_SV_COPY_ALWAYS 0x00000000UL
159 #define SRL_ENC_SV_REUSE_MAYBE 0x00000001UL
160 
161 #define SRL_UNSUPPORTED_SvTYPE(svt) (   \
162     /* svt == SVt_INVLIST || */         \
163     svt == SVt_PVGV ||                  \
164     svt == SVt_PVCV ||                  \
165     svt == SVt_PVFM ||                  \
166     svt == SVt_PVIO ||                  \
167     0 )
168 
169 /* by default we do not allow people to build with support for SRL_HDR_LONG_DOUBLE */
170 #if defined(SRL_ALLOW_LONG_DOUBLE) && defined(USE_LONG_DOUBLE) && defined(HAS_LONG_DOUBLE)
171 #define SRL_DO_LONG_DOUBLE      1
172 #else
173 #define SRL_DO_LONG_DOUBLE      0
174 #endif
175 
176 /* Options Parsing related code */
177 #define SRL_INIT_OPTION(idx, str) STMT_START {                          \
178     MY_CXT.options[idx].sv = newSVpvn((str ""), (sizeof(str) - 1));     \
179     PERL_HASH(MY_CXT.options[idx].hash, (str ""), (sizeof(str) - 1));   \
180 } STMT_END
181 
182 #define SRL_ENC_OPT_STR_ALIASED_DEDUPE_STRINGS "aliased_dedupe_strings"
183 #define SRL_ENC_OPT_IDX_ALIASED_DEDUPE_STRINGS 0
184 
185 #define SRL_ENC_OPT_STR_CANONICAL "canonical"
186 #define SRL_ENC_OPT_IDX_CANONICAL 1
187 
188 #define SRL_ENC_OPT_STR_CANONICAL_REFS "canonical_refs"
189 #define SRL_ENC_OPT_IDX_CANONICAL_REFS 2
190 
191 #define SRL_ENC_OPT_STR_COMPRESS "compress"
192 #define SRL_ENC_OPT_IDX_COMPRESS 3
193 
194 #define SRL_ENC_OPT_STR_COMPRESS_LEVEL "compress_level"
195 #define SRL_ENC_OPT_IDX_COMPRESS_LEVEL 4
196 
197 #define SRL_ENC_OPT_STR_COMPRESS_THRESHOLD "compress_threshold"
198 #define SRL_ENC_OPT_IDX_COMPRESS_THRESHOLD 5
199 
200 #define SRL_ENC_OPT_STR_CROAK_ON_BLESS "croak_on_bless"
201 #define SRL_ENC_OPT_IDX_CROAK_ON_BLESS 6
202 
203 #define SRL_ENC_OPT_STR_DEDUPE_STRINGS "dedupe_strings"
204 #define SRL_ENC_OPT_IDX_DEDUPE_STRINGS 7
205 
206 #define SRL_ENC_OPT_STR_FREEZE_CALLBACKS "freeze_callbacks"
207 #define SRL_ENC_OPT_IDX_FREEZE_CALLBACKS 8
208 
209 #define SRL_ENC_OPT_STR_MAX_RECURSION_DEPTH "max_recursion_depth"
210 #define SRL_ENC_OPT_IDX_MAX_RECURSION_DEPTH 9
211 
212 #define SRL_ENC_OPT_STR_NO_BLESS_OBJECTS "no_bless_objects"
213 #define SRL_ENC_OPT_IDX_NO_BLESS_OBJECTS 10
214 
215 #define SRL_ENC_OPT_STR_NO_SHARED_HASHKEYS "no_shared_hashkeys"
216 #define SRL_ENC_OPT_IDX_NO_SHARED_HASHKEYS 11
217 
218 #define SRL_ENC_OPT_STR_PROTOCOL_VERSION "protocol_version"
219 #define SRL_ENC_OPT_IDX_PROTOCOL_VERSION 12
220 
221 #define SRL_ENC_OPT_STR_SNAPPY "snappy"
222 #define SRL_ENC_OPT_IDX_SNAPPY 13
223 
224 #define SRL_ENC_OPT_STR_SNAPPY_INCR "snappy_incr"
225 #define SRL_ENC_OPT_IDX_SNAPPY_INCR 14
226 
227 #define SRL_ENC_OPT_STR_SNAPPY_THRESHOLD "snappy_threshold"
228 #define SRL_ENC_OPT_IDX_SNAPPY_THRESHOLD 15
229 
230 #define SRL_ENC_OPT_STR_SORT_KEYS "sort_keys"
231 #define SRL_ENC_OPT_IDX_SORT_KEYS 16
232 
233 #define SRL_ENC_OPT_STR_STRINGIFY_UNKNOWN "stringify_unknown"
234 #define SRL_ENC_OPT_IDX_STRINGIFY_UNKNOWN 17
235 
236 #define SRL_ENC_OPT_STR_UNDEF_UNKNOWN "undef_unknown"
237 #define SRL_ENC_OPT_IDX_UNDEF_UNKNOWN 18
238 
239 #define SRL_ENC_OPT_STR_USE_PROTOCOL_V1 "use_protocol_v1"
240 #define SRL_ENC_OPT_IDX_USE_PROTOCOL_V1 19
241 
242 #define SRL_ENC_OPT_STR_WARN_UNKNOWN "warn_unknown"
243 #define SRL_ENC_OPT_IDX_WARN_UNKNOWN 20
244 
245 #define SRL_ENC_OPT_COUNT 21
246 
247 #endif
248