// Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you 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