1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
// Copyright (c) 2014 Baidu, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef BUTIL_RAW_PACK_H
#define BUTIL_RAW_PACK_H
#include "butil/sys_byteorder.h"
namespace butil {
// -------------------------------------------------------------------------
// NOTE: RawPacker/RawUnpacker is used for packing/unpacking low-level and
// hard-to-change header. If the fields are likely to be changed in future,
// use protobuf.
// -------------------------------------------------------------------------
// This utility class packs 32-bit and 64-bit integers into binary data
// that can be unpacked by RawUnpacker. Notice that the packed data is
// schemaless and user must match pack..() methods with same-width
// unpack..() methods to get the integers back.
// Example:
// char buf[16]; // 4 + 8 + 4 bytes.
// butil::RawPacker(buf).pack32(a).pack64(b).pack32(c); // buf holds packed data
//
// ... network ...
//
// // positional correspondence with pack..()
// butil::Unpacker(buf2).unpack32(a).unpack64(b).unpack32(c);
class RawPacker {
public:
// Notice: User must guarantee `stream' is as long as the packed data.
explicit RawPacker(void* stream) : _stream((char*)stream) {}
~RawPacker() {}
// Not using operator<< because some values may be packed differently from
// its type.
RawPacker& pack32(uint32_t host_value) {
*(uint32_t*)_stream = HostToNet32(host_value);
_stream += 4;
return *this;
}
RawPacker& pack64(uint64_t host_value) {
uint32_t *p = (uint32_t*)_stream;
p[0] = HostToNet32(host_value >> 32);
p[1] = HostToNet32(host_value & 0xFFFFFFFF);
_stream += 8;
return *this;
}
private:
char* _stream;
};
// This utility class unpacks 32-bit and 64-bit integers from binary data
// packed by RawPacker.
class RawUnpacker {
public:
explicit RawUnpacker(const void* stream) : _stream((const char*)stream) {}
~RawUnpacker() {}
RawUnpacker& unpack32(uint32_t & host_value) {
host_value = NetToHost32(*(const uint32_t*)_stream);
_stream += 4;
return *this;
}
RawUnpacker& unpack64(uint64_t & host_value) {
const uint32_t *p = (const uint32_t*)_stream;
host_value = (((uint64_t)NetToHost32(p[0])) << 32) | NetToHost32(p[1]);
_stream += 8;
return *this;
}
private:
const char* _stream;
};
} // namespace butil
#endif // BUTIL_RAW_PACK_H