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 | /*====== |
5 | This file is part of PerconaFT. |
6 | |
7 | |
8 | Copyright (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 <string.h> |
42 | |
43 | #include "portability/memory.h" |
44 | #include "portability/toku_assert.h" |
45 | #include "portability/toku_htonl.h" |
46 | #include "portability/toku_portability.h" |
47 | #include "util/memarena.h" |
48 | |
49 | struct rbuf { |
50 | unsigned char *buf; |
51 | unsigned int size; |
52 | unsigned int ndone; |
53 | }; |
54 | #define RBUF_INITIALIZER ((struct rbuf){.buf = NULL, .size=0, .ndone=0}) |
55 | |
56 | static inline void rbuf_init(struct rbuf *r, unsigned char *buf, unsigned int size) { |
57 | r->buf = buf; |
58 | r->size = size; |
59 | r->ndone = 0; |
60 | } |
61 | |
62 | static inline unsigned int rbuf_get_roffset(struct rbuf *r) { |
63 | return r->ndone; |
64 | } |
65 | |
66 | static inline unsigned char rbuf_char (struct rbuf *r) { |
67 | assert(r->ndone<r->size); |
68 | return r->buf[r->ndone++]; |
69 | } |
70 | |
71 | static inline void rbuf_ma_uint8_t (struct rbuf *r, memarena *ma __attribute__((__unused__)), uint8_t *num) { |
72 | *num = rbuf_char(r); |
73 | } |
74 | |
75 | static inline void rbuf_ma_bool (struct rbuf *r, memarena *ma __attribute__((__unused__)), bool *b) { |
76 | uint8_t n = rbuf_char(r); |
77 | *b = (n!=0); |
78 | } |
79 | |
80 | //Read an int that MUST be in network order regardless of disk order |
81 | static unsigned int rbuf_network_int (struct rbuf *r) __attribute__((__unused__)); |
82 | static unsigned int rbuf_network_int (struct rbuf *r) { |
83 | assert(r->ndone+4 <= r->size); |
84 | uint32_t result = toku_ntohl(*(uint32_t*)(r->buf+r->ndone)); // This only works on machines where unaligned loads are OK. |
85 | r->ndone+=4; |
86 | return result; |
87 | } |
88 | |
89 | static unsigned int rbuf_int (struct rbuf *r) { |
90 | #if 1 |
91 | assert(r->ndone+4 <= r->size); |
92 | uint32_t result = toku_dtoh32(*(uint32_t*)(r->buf+r->ndone)); // This only works on machines where unaligned loads are OK. |
93 | r->ndone+=4; |
94 | return result; |
95 | #else |
96 | unsigned char c0 = rbuf_char(r); |
97 | unsigned char c1 = rbuf_char(r); |
98 | unsigned char c2 = rbuf_char(r); |
99 | unsigned char c3 = rbuf_char(r); |
100 | return ((c0<<24)| |
101 | (c1<<16)| |
102 | (c2<<8)| |
103 | (c3<<0)); |
104 | #endif |
105 | } |
106 | |
107 | static inline void rbuf_literal_bytes (struct rbuf *r, const void **bytes, unsigned int n_bytes) { |
108 | *bytes = &r->buf[r->ndone]; |
109 | r->ndone+=n_bytes; |
110 | assert(r->ndone<=r->size); |
111 | } |
112 | |
113 | /* Return a pointer into the middle of the buffer. */ |
114 | static inline void rbuf_bytes (struct rbuf *r, const void **bytes, unsigned int *n_bytes) |
115 | { |
116 | *n_bytes = rbuf_int(r); |
117 | rbuf_literal_bytes(r, bytes, *n_bytes); |
118 | } |
119 | |
120 | static inline unsigned long long rbuf_ulonglong (struct rbuf *r) { |
121 | unsigned i0 = rbuf_int(r); |
122 | unsigned i1 = rbuf_int(r); |
123 | return ((unsigned long long)(i0)<<32) | ((unsigned long long)(i1)); |
124 | } |
125 | |
126 | static inline signed long long rbuf_longlong (struct rbuf *r) { |
127 | return (signed long long)rbuf_ulonglong(r); |
128 | } |
129 | |
130 | static inline void rbuf_ma_uint32_t (struct rbuf *r, memarena *ma __attribute__((__unused__)), uint32_t *num) { |
131 | *num = rbuf_int(r); |
132 | } |
133 | |
134 | static inline void rbuf_ma_uint64_t (struct rbuf *r, memarena *ma __attribute__((__unused__)), uint64_t *num) { |
135 | *num = rbuf_ulonglong(r); |
136 | } |
137 | |
138 | // Don't try to use the same space, malloc it |
139 | static inline void rbuf_BYTESTRING (struct rbuf *r, BYTESTRING *bs) { |
140 | bs->len = rbuf_int(r); |
141 | uint32_t newndone = r->ndone + bs->len; |
142 | assert(newndone <= r->size); |
143 | bs->data = (char *) toku_memdup(&r->buf[r->ndone], (size_t)bs->len); |
144 | assert(bs->data); |
145 | r->ndone = newndone; |
146 | } |
147 | |
148 | static inline void rbuf_ma_BYTESTRING (struct rbuf *r, memarena *ma, BYTESTRING *bs) { |
149 | bs->len = rbuf_int(r); |
150 | uint32_t newndone = r->ndone + bs->len; |
151 | assert(newndone <= r->size); |
152 | bs->data = (char *) ma->malloc_from_arena(bs->len); |
153 | assert(bs->data); |
154 | memcpy(bs->data, &r->buf[r->ndone], bs->len); |
155 | r->ndone = newndone; |
156 | } |
157 | |