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