1/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
3#ident "$Id$"
4/*======
5This file is part of PerconaFT.
6
7
8Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved.
9
10 PerconaFT is free software: you can redistribute it and/or modify
11 it under the terms of the GNU General Public License, version 2,
12 as published by the Free Software Foundation.
13
14 PerconaFT is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with PerconaFT. If not, see <http://www.gnu.org/licenses/>.
21
22----------------------------------------
23
24 PerconaFT is free software: you can redistribute it and/or modify
25 it under the terms of the GNU Affero General Public License, version 3,
26 as published by the Free Software Foundation.
27
28 PerconaFT is distributed in the hope that it will be useful,
29 but WITHOUT ANY WARRANTY; without even the implied warranty of
30 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 GNU Affero General Public License for more details.
32
33 You should have received a copy of the GNU Affero General Public License
34 along with PerconaFT. If not, see <http://www.gnu.org/licenses/>.
35======= */
36
37#ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved."
38
39#pragma once
40
41#include <memory.h>
42#include <string.h>
43
44#include "portability/toku_htonl.h"
45
46#include "util/bytestring.h"
47#include "util/x1764.h"
48
49/* When serializing a value, write it into a buffer. */
50/* This code requires that the buffer be big enough to hold whatever you put into it. */
51/* This abstraction doesn't do a good job of hiding its internals.
52 * Why? The performance of this code is important, and we want to inline stuff */
53//Why is size here an int instead of DISKOFF like in the initializer?
54struct wbuf {
55 unsigned char *buf;
56 unsigned int size;
57 unsigned int ndone;
58 struct x1764 checksum; // The checksum state
59};
60
61static inline void wbuf_nocrc_init (struct wbuf *w, void *buf, unsigned int size) {
62 w->buf = (unsigned char *) buf;
63 w->size = size;
64 w->ndone = 0;
65}
66
67static inline void wbuf_init (struct wbuf *w, void *buf, unsigned int size) {
68 wbuf_nocrc_init(w, buf, size);
69 toku_x1764_init(&w->checksum);
70}
71
72static inline size_t wbuf_get_woffset(struct wbuf *w) {
73 return w->ndone;
74}
75
76/* Write a character. */
77static inline void wbuf_nocrc_char (struct wbuf *w, unsigned char ch) {
78 assert(w->ndone<w->size);
79 w->buf[w->ndone++]=ch;
80}
81
82/* Write a character. */
83static inline void wbuf_nocrc_uint8_t (struct wbuf *w, uint8_t ch) {
84 assert(w->ndone<w->size);
85 w->buf[w->ndone++]=ch;
86}
87
88static inline void wbuf_char (struct wbuf *w, unsigned char ch) {
89 wbuf_nocrc_char (w, ch);
90 toku_x1764_add(&w->checksum, &w->buf[w->ndone-1], 1);
91}
92
93//Write an int that MUST be in network order regardless of disk order
94static void wbuf_network_int (struct wbuf *w, int32_t i) __attribute__((__unused__));
95static void wbuf_network_int (struct wbuf *w, int32_t i) {
96 assert(w->ndone + 4 <= w->size);
97 *(uint32_t*)(&w->buf[w->ndone]) = toku_htonl(i);
98 toku_x1764_add(&w->checksum, &w->buf[w->ndone], 4);
99 w->ndone += 4;
100}
101
102static inline void wbuf_nocrc_int (struct wbuf *w, int32_t i) {
103#if 0
104 wbuf_nocrc_char(w, i>>24);
105 wbuf_nocrc_char(w, i>>16);
106 wbuf_nocrc_char(w, i>>8);
107 wbuf_nocrc_char(w, i>>0);
108#else
109 assert(w->ndone + 4 <= w->size);
110 #if 0
111 w->buf[w->ndone+0] = i>>24;
112 w->buf[w->ndone+1] = i>>16;
113 w->buf[w->ndone+2] = i>>8;
114 w->buf[w->ndone+3] = i>>0;
115 #else
116 *(uint32_t*)(&w->buf[w->ndone]) = toku_htod32(i);
117 #endif
118 w->ndone += 4;
119#endif
120}
121
122static inline void wbuf_int (struct wbuf *w, int32_t i) {
123 wbuf_nocrc_int(w, i);
124 toku_x1764_add(&w->checksum, &w->buf[w->ndone-4], 4);
125}
126
127static inline void wbuf_nocrc_uint (struct wbuf *w, uint32_t i) {
128 wbuf_nocrc_int(w, (int32_t)i);
129}
130
131static inline void wbuf_uint (struct wbuf *w, uint32_t i) {
132 wbuf_int(w, (int32_t)i);
133}
134
135static inline uint8_t* wbuf_nocrc_reserve_literal_bytes(struct wbuf *w, uint32_t nbytes) {
136 assert(w->ndone + nbytes <= w->size);
137 uint8_t * dest = w->buf + w->ndone;
138 w->ndone += nbytes;
139 return dest;
140}
141
142static inline void wbuf_nocrc_literal_bytes(struct wbuf *w, const void *bytes_bv, uint32_t nbytes) {
143 const unsigned char *bytes = (const unsigned char *) bytes_bv;
144#if 0
145 { int i; for (i=0; i<nbytes; i++) wbuf_nocrc_char(w, bytes[i]); }
146#else
147 assert(w->ndone + nbytes <= w->size);
148 memcpy(w->buf + w->ndone, bytes, (size_t)nbytes);
149 w->ndone += nbytes;
150#endif
151}
152
153static inline void wbuf_literal_bytes(struct wbuf *w, const void *bytes_bv, uint32_t nbytes) {
154 wbuf_nocrc_literal_bytes(w, bytes_bv, nbytes);
155 toku_x1764_add(&w->checksum, &w->buf[w->ndone-nbytes], nbytes);
156}
157
158static void wbuf_nocrc_bytes (struct wbuf *w, const void *bytes_bv, uint32_t nbytes) {
159 wbuf_nocrc_uint(w, nbytes);
160 wbuf_nocrc_literal_bytes(w, bytes_bv, nbytes);
161}
162
163static void wbuf_bytes (struct wbuf *w, const void *bytes_bv, uint32_t nbytes) {
164 wbuf_uint(w, nbytes);
165 wbuf_literal_bytes(w, bytes_bv, nbytes);
166}
167
168static void wbuf_nocrc_ulonglong (struct wbuf *w, uint64_t ull) {
169 wbuf_nocrc_uint(w, (uint32_t)(ull>>32));
170 wbuf_nocrc_uint(w, (uint32_t)(ull&0xFFFFFFFF));
171}
172
173static void wbuf_ulonglong (struct wbuf *w, uint64_t ull) {
174 wbuf_uint(w, (uint32_t)(ull>>32));
175 wbuf_uint(w, (uint32_t)(ull&0xFFFFFFFF));
176}
177
178static inline void wbuf_nocrc_uint64_t(struct wbuf *w, uint64_t ull) {
179 wbuf_nocrc_ulonglong(w, ull);
180}
181
182
183static inline void wbuf_uint64_t(struct wbuf *w, uint64_t ull) {
184 wbuf_ulonglong(w, ull);
185}
186
187static inline void wbuf_nocrc_bool (struct wbuf *w, bool b) {
188 wbuf_nocrc_uint8_t(w, (uint8_t)(b ? 1 : 0));
189}
190
191static inline void wbuf_nocrc_BYTESTRING (struct wbuf *w, BYTESTRING v) {
192 wbuf_nocrc_bytes(w, v.data, v.len);
193}
194
195static inline void wbuf_BYTESTRING (struct wbuf *w, BYTESTRING v) {
196 wbuf_bytes(w, v.data, v.len);
197}
198
199static inline void wbuf_uint8_t (struct wbuf *w, uint8_t v) {
200 wbuf_char(w, v);
201}
202
203static inline void wbuf_nocrc_uint32_t (struct wbuf *w, uint32_t v) {
204 wbuf_nocrc_uint(w, v);
205}
206
207static inline void wbuf_uint32_t (struct wbuf *w, uint32_t v) {
208 wbuf_uint(w, v);
209}
210