// Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. // https://developers.google.com/protocol-buffers/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Author: [email protected] (Kenton Varda) // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. // // This file contains the CodedInputStream and CodedOutputStream classes, // which wrap a ZeroCopyInputStream or ZeroCopyOutputStream, respectively, // and allow you to read or write individual pieces of data in various // formats. In particular, these implement the varint encoding for // integers, a simple variable-length encoding in which smaller numbers // take fewer bytes. // // Typically these classes will only be used internally by the protocol // buffer library in order to encode and decode protocol buffers. Clients // of the library only need to know about this class if they wish to write // custom message parsing or serialization procedures. // // CodedOutputStream example: // // Write some data to "myfile". First we write a 4-byte "magic number" // // to identify the file type, then write a length-delimited string. The // // string is composed of a varint giving the length followed by the raw // // bytes. // int fd = open("myfile", O_CREAT | O_WRONLY); // ZeroCopyOutputStream* raw_output = new FileOutputStream(fd); // CodedOutputStream* coded_output = new CodedOutputStream(raw_output); // // int magic_number = 1234; // char text[] = "Hello world!"; // coded_output->WriteLittleEndian32(magic_number); // coded_output->WriteVarint32(strlen(text)); // coded_output->WriteRaw(text, strlen(text)); // // delete coded_output; // delete raw_output; // close(fd); // // CodedInputStream example: // // Read a file created by the above code. // int fd = open("myfile", O_RDONLY); // ZeroCopyInputStream* raw_input = new FileInputStream(fd); // CodedInputStream* coded_input = new CodedInputStream(raw_input); // // coded_input->ReadLittleEndian32(&magic_number); // if (magic_number != 1234) { // cerr << "File not in expected format." << endl; // return; // } // // uint32_t size; // coded_input->ReadVarint32(&size); // // char* text = new char[size + 1]; // coded_input->ReadRaw(buffer, size); // text[size] = '\0'; // // delete coded_input; // delete raw_input; // close(fd); // // cout << "Text is: " << text << endl; // delete [] text; // // For those who are interested, varint encoding is defined as follows: // // The encoding operates on unsigned integers of up to 64 bits in length. // Each byte of the encoded value has the format: // * bits 0-6: Seven bits of the number being encoded. // * bit 7: Zero if this is the last byte in the encoding (in which // case all remaining bits of the number are zero) or 1 if // more bytes follow. // The first byte contains the least-significant 7 bits of the number, the // second byte (if present) contains the next-least-significant 7 bits, // and so on. So, the binary number 1011000101011 would be encoded in two // bytes as "10101011 00101100". // // In theory, varint could be used to encode integers of any length. // However, for practicality we set a limit at 64 bits. The maximum encoded // length of a number is thus 10 bytes. #ifndef GOOGLE_PROTOBUF_IO_CODED_STREAM_H__ #define GOOGLE_PROTOBUF_IO_CODED_STREAM_H__ #include <assert.h> #include <atomic> #include <climits> #include <cstddef> #include <cstring> #include <limits> #include <string> #include <type_traits> #include <utility> #if defined(_MSC_VER) && _MSC_VER >= 1300 && !defined(__INTEL_COMPILER) // If MSVC has "/RTCc" set, it will complain about truncating casts at // runtime. This file contains some intentional truncating casts. #pragma runtime_checks("c", off) #endif #include <google/protobuf/stubs/common.h> #include <google/protobuf/stubs/logging.h> #include <google/protobuf/stubs/strutil.h> #include <google/protobuf/port.h> #include <google/protobuf/stubs/port.h> // Must be included last. #include <google/protobuf/port_def.inc> namespace google { namespace protobuf { class DescriptorPool; class MessageFactory; class ZeroCopyCodedInputStream; namespace internal { void MapTestForceDeterministic(); class EpsCopyByteStream; } // namespace internal namespace io { // Defined in this file. class CodedInputStream; class CodedOutputStream; // Defined in other files. class ZeroCopyInputStream; // zero_copy_stream.h class ZeroCopyOutputStream; // zero_copy_stream.h // Class which reads and decodes binary data which is composed of varint- // encoded integers and fixed-width pieces. Wraps a ZeroCopyInputStream. // Most users will not need to deal with CodedInputStream. // // Most methods of CodedInputStream that return a bool return false if an // underlying I/O error occurs or if the data is malformed. Once such a // failure occurs, the CodedInputStream is broken and is no longer useful. // After a failure, callers also should assume writes to "out" args may have // occurred, though nothing useful can be determined from those writes. class PROTOBUF_EXPORT CodedInputStream { … }; // EpsCopyOutputStream wraps a ZeroCopyOutputStream and exposes a new stream, // which has the property you can write kSlopBytes (16 bytes) from the current // position without bounds checks. The cursor into the stream is managed by // the user of the class and is an explicit parameter in the methods. Careful // use of this class, ie. keep ptr a local variable, eliminates the need to // for the compiler to sync the ptr value between register and memory. class PROTOBUF_EXPORT EpsCopyOutputStream { … }; template <> inline uint8_t* EpsCopyOutputStream::WriteRawLittleEndian<1>(const void* data, int size, uint8_t* ptr) { … } template <> inline uint8_t* EpsCopyOutputStream::WriteRawLittleEndian<4>(const void* data, int size, uint8_t* ptr) { … } template <> inline uint8_t* EpsCopyOutputStream::WriteRawLittleEndian<8>(const void* data, int size, uint8_t* ptr) { … } // Class which encodes and writes binary data which is composed of varint- // encoded integers and fixed-width pieces. Wraps a ZeroCopyOutputStream. // Most users will not need to deal with CodedOutputStream. // // Most methods of CodedOutputStream which return a bool return false if an // underlying I/O error occurs. Once such a failure occurs, the // CodedOutputStream is broken and is no longer useful. The Write* methods do // not return the stream status, but will invalidate the stream if an error // occurs. The client can probe HadError() to determine the status. // // Note that every method of CodedOutputStream which writes some data has // a corresponding static "ToArray" version. These versions write directly // to the provided buffer, returning a pointer past the last written byte. // They require that the buffer has sufficient capacity for the encoded data. // This allows an optimization where we check if an output stream has enough // space for an entire message before we start writing and, if there is, we // call only the ToArray methods to avoid doing bound checks for each // individual value. // i.e., in the example above: // // CodedOutputStream* coded_output = new CodedOutputStream(raw_output); // int magic_number = 1234; // char text[] = "Hello world!"; // // int coded_size = sizeof(magic_number) + // CodedOutputStream::VarintSize32(strlen(text)) + // strlen(text); // // uint8_t* buffer = // coded_output->GetDirectBufferForNBytesAndAdvance(coded_size); // if (buffer != nullptr) { // // The output stream has enough space in the buffer: write directly to // // the array. // buffer = CodedOutputStream::WriteLittleEndian32ToArray(magic_number, // buffer); // buffer = CodedOutputStream::WriteVarint32ToArray(strlen(text), buffer); // buffer = CodedOutputStream::WriteRawToArray(text, strlen(text), buffer); // } else { // // Make bound-checked writes, which will ask the underlying stream for // // more space as needed. // coded_output->WriteLittleEndian32(magic_number); // coded_output->WriteVarint32(strlen(text)); // coded_output->WriteRaw(text, strlen(text)); // } // // delete coded_output; class PROTOBUF_EXPORT CodedOutputStream { … }; // inline methods ==================================================== // The vast majority of varints are only one byte. These inline // methods optimize for that case. inline bool CodedInputStream::ReadVarint32(uint32_t* value) { … } inline bool CodedInputStream::ReadVarint64(uint64_t* value) { … } inline bool CodedInputStream::ReadVarintSizeAsInt(int* value) { … } // static inline const uint8_t* CodedInputStream::ReadLittleEndian32FromArray( const uint8_t* buffer, uint32_t* value) { … } // static inline const uint8_t* CodedInputStream::ReadLittleEndian64FromArray( const uint8_t* buffer, uint64_t* value) { … } inline bool CodedInputStream::ReadLittleEndian32(uint32_t* value) { … } inline bool CodedInputStream::ReadLittleEndian64(uint64_t* value) { … } inline uint32_t CodedInputStream::ReadTagNoLastTag() { … } inline std::pair<uint32_t, bool> CodedInputStream::ReadTagWithCutoffNoLastTag( uint32_t cutoff) { … } inline bool CodedInputStream::LastTagWas(uint32_t expected) { … } inline bool CodedInputStream::ConsumedEntireMessage() { … } inline bool CodedInputStream::ExpectTag(uint32_t expected) { … } inline const uint8_t* CodedInputStream::ExpectTagFromArray( const uint8_t* buffer, uint32_t expected) { … } inline void CodedInputStream::GetDirectBufferPointerInline(const void** data, int* size) { … } inline bool CodedInputStream::ExpectAtEnd() { … } inline int CodedInputStream::CurrentPosition() const { … } inline void CodedInputStream::Advance(int amount) { … } inline void CodedInputStream::SetRecursionLimit(int limit) { … } inline bool CodedInputStream::IncrementRecursionDepth() { … } inline void CodedInputStream::DecrementRecursionDepth() { … } inline void CodedInputStream::UnsafeDecrementRecursionDepth() { … } inline void CodedInputStream::SetExtensionRegistry(const DescriptorPool* pool, MessageFactory* factory) { … } inline const DescriptorPool* CodedInputStream::GetExtensionPool() { … } inline MessageFactory* CodedInputStream::GetExtensionFactory() { … } inline int CodedInputStream::BufferSize() const { … } inline CodedInputStream::CodedInputStream(ZeroCopyInputStream* input) : … { … } inline CodedInputStream::CodedInputStream(const uint8_t* buffer, int size) : … { … } inline bool CodedInputStream::IsFlat() const { … } inline bool CodedInputStream::Skip(int count) { … } template <class Stream, class> inline CodedOutputStream::CodedOutputStream(Stream* stream) : impl_(stream, IsDefaultSerializationDeterministic(), &cur_), start_count_(stream->ByteCount()) { … } template <class Stream, class> inline CodedOutputStream::CodedOutputStream(Stream* stream, bool eager_init) : impl_(stream, IsDefaultSerializationDeterministic(), &cur_), start_count_(stream->ByteCount()) { … } template <class Stream> inline void CodedOutputStream::InitEagerly(Stream* stream) { … } inline uint8_t* CodedOutputStream::WriteVarint32ToArray(uint32_t value, uint8_t* target) { … } inline uint8_t* CodedOutputStream::WriteVarint32ToArrayOutOfLine( uint32_t value, uint8_t* target) { … } inline uint8_t* CodedOutputStream::WriteVarint64ToArray(uint64_t value, uint8_t* target) { … } inline void CodedOutputStream::WriteVarint32SignExtended(int32_t value) { … } inline uint8_t* CodedOutputStream::WriteVarint32SignExtendedToArray( int32_t value, uint8_t* target) { … } inline uint8_t* CodedOutputStream::WriteLittleEndian32ToArray(uint32_t value, uint8_t* target) { … } inline uint8_t* CodedOutputStream::WriteLittleEndian64ToArray(uint64_t value, uint8_t* target) { … } inline void CodedOutputStream::WriteVarint32(uint32_t value) { … } inline void CodedOutputStream::WriteVarint64(uint64_t value) { … } inline void CodedOutputStream::WriteTag(uint32_t value) { … } inline uint8_t* CodedOutputStream::WriteTagToArray(uint32_t value, uint8_t* target) { … } inline size_t CodedOutputStream::VarintSize32(uint32_t value) { … } inline size_t CodedOutputStream::VarintSize32PlusOne(uint32_t value) { … } inline size_t CodedOutputStream::VarintSize64(uint64_t value) { … } inline size_t CodedOutputStream::VarintSize64PlusOne(uint64_t value) { … } inline size_t CodedOutputStream::VarintSize32SignExtended(int32_t value) { … } inline size_t CodedOutputStream::VarintSize32SignExtendedPlusOne( int32_t value) { … } inline void CodedOutputStream::WriteString(const std::string& str) { … } inline void CodedOutputStream::WriteRawMaybeAliased(const void* data, int size) { … } inline uint8_t* CodedOutputStream::WriteRawToArray(const void* data, int size, uint8_t* target) { … } inline uint8_t* CodedOutputStream::WriteStringToArray(const std::string& str, uint8_t* target) { … } } // namespace io } // namespace protobuf } // namespace google #if defined(_MSC_VER) && _MSC_VER >= 1300 && !defined(__INTEL_COMPILER) #pragma runtime_checks("c", restore) #endif // _MSC_VER && !defined(__INTEL_COMPILER) #include <google/protobuf/port_undef.inc> #endif // GOOGLE_PROTOBUF_IO_CODED_STREAM_H__