1/*
2 * Copyright (c) 2017-2018, Intel Corporation
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * * Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of Intel Corporation nor the names of its contributors
13 * may be used to endorse or promote products derived from this software
14 * without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include "util/join.h"
30
31#define COPY_FIELD(x) COPY(&x, sizeof(x))
32#define COPY_LEFTFIXES JOIN(sc_left_, FN_SUFFIX)
33#define COPY_SOM_INFO JOIN(sc_som_, FN_SUFFIX)
34
35static
36size_t COPY_LEFTFIXES(const struct RoseEngine *rose, size_t currOffset,
37 STREAM_QUAL struct hs_stream *stream,
38 BUF_QUAL char *buf, UNUSED size_t buf_size) {
39 if (!rose->activeLeftIterOffset) {
40 return currOffset;
41 }
42
43 const struct RoseStateOffsets *so = &rose->stateOffsets;
44 STREAM_QUAL char *stream_body
45 = ((STREAM_QUAL char *)stream) + sizeof(struct hs_stream);
46
47 /* Note: in the expand case the active left array has already been copied
48 * into the stream. */
49 const u8 *ara = (const u8 *)(stream_body + so->activeLeftArray);
50 const u32 arCount = rose->activeLeftCount;
51 const struct LeftNfaInfo *left_table = getLeftTable(rose);
52
53 /* We only want to look at non-transient leftfixes */
54 const struct mmbit_sparse_iter *it = getActiveLeftIter(rose);
55 struct mmbit_sparse_state si_state[MAX_SPARSE_ITER_STATES];
56 u32 dummy;
57 u32 ri = mmbit_sparse_iter_begin(ara, arCount, &dummy, it, si_state);
58 for (; ri != MMB_INVALID;
59 ri = mmbit_sparse_iter_next(ara, arCount, ri, &dummy, it, si_state)) {
60 u32 qi = ri + rose->leftfixBeginQueue;
61 UNUSED const struct LeftNfaInfo *left = left_table + ri;
62 const struct NfaInfo *nfa_info = getNfaInfoByQueue(rose, qi);
63 const struct NFA *nfa = getNfaByInfo(rose, nfa_info);
64
65 COPY(stream_body + nfa_info->stateOffset, nfa->streamStateSize);
66 /* copy the one whole byte for active leftfixes as well */
67 assert(left->lagIndex != ROSE_OFFSET_INVALID);
68 COPY(stream_body + so->leftfixLagTable + left->lagIndex, 1);
69 }
70
71 return currOffset;
72}
73
74static
75size_t COPY_SOM_INFO(const struct RoseEngine *rose, size_t currOffset,
76 STREAM_QUAL struct hs_stream *stream,
77 BUF_QUAL char *buf, UNUSED size_t buf_size) {
78 const struct RoseStateOffsets *so = &rose->stateOffsets;
79
80 if (!so->somLocation) {
81 assert(!so->somValid);
82 assert(!so->somWritable);
83 return currOffset;
84 }
85
86 STREAM_QUAL char *stream_body
87 = ((STREAM_QUAL char *)stream) + sizeof(struct hs_stream);
88
89 assert(so->somValid);
90 assert(so->somWritable);
91
92 COPY_MULTIBIT(stream_body + so->somWritable, rose->somLocationCount);
93 COPY_MULTIBIT(stream_body + so->somValid, rose->somLocationCount);
94
95 /* Copy only the som slots which contain valid values. */
96 /* Note: in the expand case the som valid array has been copied in. */
97 const u8 *svalid = (const u8 *)(stream_body + so->somValid);
98 u32 s_count = rose->somLocationCount;
99 u32 s_width = rose->somHorizon;
100 for (u32 slot = mmbit_iterate(svalid, s_count, MMB_INVALID);
101 slot != MMB_INVALID; slot = mmbit_iterate(svalid, s_count, slot)) {
102 COPY(stream_body + so->somLocation + slot * s_width, s_width);
103 }
104
105 return currOffset;
106}
107
108static
109size_t JOIN(sc_, FN_SUFFIX)(const struct RoseEngine *rose,
110 STREAM_QUAL struct hs_stream *stream,
111 BUF_QUAL char *buf, UNUSED size_t buf_size) {
112 size_t currOffset = 0;
113 const struct RoseStateOffsets *so = &rose->stateOffsets;
114
115 STREAM_QUAL char *stream_body
116 = ((STREAM_QUAL char *)stream) + sizeof(struct hs_stream);
117
118 COPY_FIELD(stream->offset);
119 ASSIGN(stream->rose, rose);
120
121 COPY(stream_body + ROSE_STATE_OFFSET_STATUS_FLAGS, 1);
122 COPY_MULTIBIT(stream_body + ROSE_STATE_OFFSET_ROLE_MMBIT, rose->rolesWithStateCount);
123
124 /* stream is valid in compress/size, and stream->offset has been set already
125 * on the expand side */
126 u64a offset = stream->offset;
127 u32 history = MIN((u32)offset, rose->historyRequired);
128
129 /* copy the active mmbits */
130 COPY_MULTIBIT(stream_body + so->activeLeafArray, rose->activeArrayCount);
131 COPY_MULTIBIT(stream_body + so->activeLeftArray, rose->activeLeftCount);
132
133 COPY(stream_body + so->longLitState, so->longLitState_size);
134
135 /* Leftlag table will be handled later, for active leftfixes */
136
137 /* anchored table state is not required once we are deep in the stream */
138 if (offset <= rose->anchoredDistance) {
139 COPY(stream_body + so->anchorState, rose->anchorStateSize);
140 }
141
142 COPY(stream_body + so->groups, so->groups_size);
143
144 /* copy the real bits of history */
145 UNUSED u32 hend = so->history + rose->historyRequired;
146 COPY(stream_body + hend - history, history);
147
148 /* copy the exhaustion multibit */
149 COPY_MULTIBIT(stream_body + so->exhausted, rose->ekeyCount);
150
151 /* copy the logical multibit */
152 COPY_MULTIBIT(stream_body + so->logicalVec,
153 rose->lkeyCount + rose->lopCount);
154
155 /* copy the combination multibit */
156 COPY_MULTIBIT(stream_body + so->combVec, rose->ckeyCount);
157
158 /* copy nfa stream state for endfixes */
159 /* Note: in the expand case the active array has already been copied into
160 * the stream. */
161 const u8 *aa = (const u8 *)(stream_body + so->activeLeafArray);
162 u32 aaCount = rose->activeArrayCount;
163 for (u32 qi = mmbit_iterate(aa, aaCount, MMB_INVALID); qi != MMB_INVALID;
164 qi = mmbit_iterate(aa, aaCount, qi)) {
165 DEBUG_PRINTF("saving stream state for qi=%u\n", qi);
166 const struct NfaInfo *nfa_info = getNfaInfoByQueue(rose, qi);
167 const struct NFA *nfa = getNfaByInfo(rose, nfa_info);
168 COPY(stream_body + nfa_info->stateOffset, nfa->streamStateSize);
169 }
170
171 /* copy nfa stream state for leftfixes */
172 currOffset = COPY_LEFTFIXES(rose, currOffset, stream, buf, buf_size);
173 if (!currOffset) {
174 return 0;
175 }
176
177 currOffset = COPY_SOM_INFO(rose, currOffset, stream, buf, buf_size);
178 if (!currOffset) {
179 return 0;
180 }
181
182 return currOffset;
183}
184
185#undef ASSIGN
186#undef COPY
187#undef COPY_FIELD
188#undef COPT_LEFTFIXES
189#undef COPY_MULTIBIT
190#undef COPY_SOM_INFO
191#undef FN_SUFFIX
192#undef BUF_QUAL
193#undef STREAM_QUAL
194