//====== Copyright 1996-2014, Valve Corporation, All rights reserved. ======= // // Purpose: Simple C++ protobuf manipulation routines. For a more advanced, // fully-featured library, see https://developers.google.com/protocol-buffers/ // //=========================================================================== #include "SimpleProtobuf.h" // // NOTE: // You should probably be using the official protobuf library instead if you // have any concerns about how this code works, or are planning to modify it. // #define CHECK_OVERRUN( ptr, end, len ) ( end < ptr || (size_t)( end - ptr ) < len ) static void ProtobufEncodeVarInt( std::string& strProtobuf, uint64 ulVarInt ) { for ( ; ulVarInt >= 128; ulVarInt >>= 7 ) strProtobuf.append( 1, ((char)ulVarInt & (char)127) | (char)128 ); strProtobuf.append( 1, (char)ulVarInt ); } void ProtobufWriteField_Integer( std::string& strProtobuf, uint32 uFieldNumber, uint64 ulVarIntData ) { ProtobufEncodeVarInt( strProtobuf, PROTOBUF_FIELDTAG_INTEGER( uFieldNumber ) ); ProtobufEncodeVarInt( strProtobuf, ulVarIntData ); } void ProtobufWriteField_SInteger( std::string& strProtobuf, uint32 uFieldNumber, int64 ulSwizzleVarIntData ) { ProtobufEncodeVarInt( strProtobuf, PROTOBUF_FIELDTAG_SINTEGER( uFieldNumber ) ); ProtobufEncodeVarInt( strProtobuf, (ulSwizzleVarIntData << 1) ^ (ulSwizzleVarIntData >> 63) ); } void ProtobufWriteField_Fixed64( std::string& strProtobuf, uint32 uFieldNumber, uint64 ulFixed64Data ) { ProtobufEncodeVarInt( strProtobuf, PROTOBUF_FIELDTAG_FIXED64( uFieldNumber ) ); #ifdef VALVE_BIG_ENDIAN ulFixed64Data = QWordSwap( ulFixed64Data ); #endif strProtobuf.append( reinterpret_cast(&ulFixed64Data), 8 ); } void ProtobufWriteField_Fixed64( std::string& strProtobuf, uint32 uFieldNumber, double flFixed64Data ) { ProtobufEncodeVarInt( strProtobuf, PROTOBUF_FIELDTAG_FIXED64( uFieldNumber ) ); const char *pData = reinterpret_cast(&flFixed64Data); #ifdef VALVE_BIG_ENDIAN strProtobuf.append( std::const_reverse_iterator( pData + 8 ), std::const_reverse_iterator( pData ) ); #else strProtobuf.append( pData, 8 ); #endif } void ProtobufWriteField_String( std::string& strProtobuf, uint32 uFieldNumber, const char *pchData, size_t cchData ) { ProtobufEncodeVarInt( strProtobuf, PROTOBUF_FIELDTAG_STRING( uFieldNumber ) ); ProtobufEncodeVarInt( strProtobuf, cchData ); strProtobuf.append( pchData, cchData ); } void ProtobufWriteField_String( std::string& strProtobuf, uint32 uFieldNumber, const std::string &strData ) { ProtobufWriteField_String( strProtobuf, uFieldNumber, strData.data(), strData.size() ); } void ProtobufWriteField_String( std::string& strProtobuf, uint32 uFieldNumber, const char *pchData ) { ProtobufWriteField_String( strProtobuf, uFieldNumber, pchData, strlen( pchData ) ); } void ProtobufWriteField_Fixed32( std::string& strProtobuf, uint32 uFieldNumber, uint32 ulFixed32Data ) { ProtobufEncodeVarInt( strProtobuf, PROTOBUF_FIELDTAG_FIXED32( uFieldNumber ) ); #ifdef VALVE_BIG_ENDIAN ulFixed32Data = DWordSwap( ulFixed32Data ); #endif strProtobuf.append( reinterpret_cast(&ulFixed32Data), 4 ); } void ProtobufWriteField_Fixed32( std::string& strProtobuf, uint32 uFieldNumber, float flFixed32Data ) { ProtobufEncodeVarInt( strProtobuf, PROTOBUF_FIELDTAG_FIXED32( uFieldNumber ) ); const char *pData = reinterpret_cast(&flFixed32Data); #ifdef VALVE_BIG_ENDIAN strProtobuf.append( std::const_reverse_iterator( pData + 4 ), std::const_reverse_iterator( pData ) ); #else strProtobuf.append( pData, 4 ); #endif } static bool ProtobufDecodeVarInt( const char * &pParsePosition, const char *pParseEnd, uint64 &ulVarInt ) { const char * pStart = pParsePosition; while ( pParsePosition < pParseEnd && (*pParsePosition & 128) ) ++pParsePosition; if ( pParsePosition >= pParseEnd ) return false; uint64 v = 0; for ( const char *p = pParsePosition++; p >= pStart; --p ) v = (v << 7) + (*p & 127); ulVarInt = v; return true; } bool ProtobufReadFieldTag( const char * &pParsePosition, const char *pParseEnd, uint32 &uFieldTag ) { uint64 v; if ( !ProtobufDecodeVarInt( pParsePosition, pParseEnd, v ) || v == 0 || (v >> 32) != 0 ) { pParsePosition = pParseEnd; return false; } uFieldTag = (uint32)v; return true; } bool ProtobufSkipFieldValue( const char * &pParsePosition, const char *pParseEnd, uint32 uFieldTag ) { switch ( uFieldTag & 7 ) { case 0: // VARINT while ( pParsePosition < pParseEnd ) { char c = *pParsePosition++; if ( !( c & 128 ) ) return true; } return false; case 1: // FIXED64 if ( CHECK_OVERRUN( pParsePosition, pParseEnd, 8 ) ) { pParsePosition = pParseEnd; return false; } pParsePosition += 8; return true; case 2: // LENGTH DELIM (string, etc) { uint64 ulLength = 0; if ( !ProtobufDecodeVarInt( pParsePosition, pParseEnd, ulLength ) ) return false; if ( CHECK_OVERRUN( pParsePosition, pParseEnd, ulLength ) ) { pParsePosition = pParseEnd; return false; } pParsePosition += ulLength; return true; } case 5: // FIXED32 if ( CHECK_OVERRUN( pParsePosition, pParseEnd, 4 ) ) { pParsePosition = pParseEnd; return false; } pParsePosition += 4; return true; default: // UNKNOWN pParsePosition = pParseEnd; return false; } } bool ProtobufReadFixed32( const char * &pParsePosition, const char *pParseEnd, int32 &nValue ) { if ( CHECK_OVERRUN( pParsePosition, pParseEnd, 4 ) ) { pParsePosition = pParseEnd; return false; } memcpy( &nValue, pParsePosition, 4 ); #ifdef VALVE_BIG_ENDIAN nValue = DWordSwap( nValue ); #endif pParsePosition += 4; return true; } bool ProtobufReadFixed32( const char * &pParsePosition, const char *pParseEnd, uint32 &uValue ) { if ( CHECK_OVERRUN( pParsePosition, pParseEnd, 4 ) ) { pParsePosition = pParseEnd; return false; } memcpy( &uValue, pParsePosition, 4 ); #ifdef VALVE_BIG_ENDIAN uValue = DWordSwap( uValue ); #endif pParsePosition += 4; return true; } bool ProtobufReadFixed32( const char * &pParsePosition, const char *pParseEnd, float &flValue ) { if ( CHECK_OVERRUN( pParsePosition, pParseEnd, 4 ) ) { pParsePosition = pParseEnd; return false; } #ifdef VALVE_BIG_ENDIAN std::copy( std::const_reverse_iterator( pParsePosition + 4 ), std::const_reverse_iterator( pParsePosition ), reinterpret_cast(&flValue) ); #else memcpy( &flValue, pParsePosition, 4 ); #endif pParsePosition += 4; return true; } bool ProtobufReadFixed64( const char * &pParsePosition, const char *pParseEnd, int64 &lValue ) { if ( CHECK_OVERRUN( pParsePosition, pParseEnd, 8 ) ) { pParsePosition = pParseEnd; return false; } memcpy( &lValue, pParsePosition, 8 ); #ifdef VALVE_BIG_ENDIAN lValue = QWordSwap( lValue ); #endif pParsePosition += 8; return true; } bool ProtobufReadFixed64( const char * &pParsePosition, const char *pParseEnd, uint64 &ulValue ) { if ( CHECK_OVERRUN( pParsePosition, pParseEnd, 8 ) ) { pParsePosition = pParseEnd; return false; } memcpy( &ulValue, pParsePosition, 8 ); #ifdef VALVE_BIG_ENDIAN ulValue = QWordSwap( ulValue ); #endif pParsePosition += 8; return true; } bool ProtobufReadFixed64( const char * &pParsePosition, const char *pParseEnd, double &flValue ) { if ( CHECK_OVERRUN( pParsePosition, pParseEnd, 8 ) ) { pParsePosition = pParseEnd; return false; } #ifdef VALVE_BIG_ENDIAN std::copy( std::const_reverse_iterator( pParsePosition + 8 ), std::const_reverse_iterator( pParsePosition ), reinterpret_cast(&flValue) ); #else memcpy( &flValue, pParsePosition, 8 ); #endif pParsePosition += 8; return true; } bool ProtobufReadInteger( const char * &pParsePosition, const char *pParseEnd, uint64 &ulVarInt ) { return ProtobufDecodeVarInt( pParsePosition, pParseEnd, ulVarInt ); } bool ProtobufReadInteger( const char * &pParsePosition, const char *pParseEnd, int64 &lVarInt ) { return ProtobufDecodeVarInt( pParsePosition, pParseEnd, reinterpret_cast(lVarInt) ); } bool ProtobufReadInteger( const char * &pParsePosition, const char *pParseEnd, uint32 &uVarInt ) { uint64 ulVarInt; if ( !ProtobufDecodeVarInt( pParsePosition, pParseEnd, ulVarInt ) ) return false; uVarInt = (uint32)ulVarInt; return (uint64)uVarInt == ulVarInt; } bool ProtobufReadInteger( const char * &pParsePosition, const char *pParseEnd, int32 &nVarInt ) { uint64 ulVarInt; if ( !ProtobufDecodeVarInt( pParsePosition, pParseEnd, ulVarInt ) ) return false; nVarInt = (int32)ulVarInt; return (uint64)(int64)nVarInt == ulVarInt; } bool ProtobufReadInteger( const char * &pParsePosition, const char *pParseEnd, bool &bVarInt ) { uint64 ulVarInt; if ( !ProtobufDecodeVarInt( pParsePosition, pParseEnd, ulVarInt ) ) return false; bVarInt = ( ulVarInt != 0 ); return true; } bool ProtobufReadSInteger( const char * &pParsePosition, const char *pParseEnd, int64 &lVarInt ) { uint64 v; if ( !ProtobufDecodeVarInt( pParsePosition, pParseEnd, v ) ) return false; lVarInt = (int64)(v >> 1) ^ -(int64)(v & 1); return true; } bool ProtobufReadSInteger( const char * &pParsePosition, const char *pParseEnd, int32 &nVarInt ) { uint64 v; if ( !ProtobufDecodeVarInt( pParsePosition, pParseEnd, v ) ) return false; int64 lVarInt = (int64)(v >> 1) ^ -(int64)(v & 1); nVarInt = (int32)lVarInt; return (int64)nVarInt == lVarInt; } bool ProtobufReadString( const char * &pParsePosition, const char *pParseEnd, std::string &strValue ) { uint64 ulLength; if ( !ProtobufDecodeVarInt( pParsePosition, pParseEnd, ulLength ) ) return false; if ( CHECK_OVERRUN( pParsePosition, pParseEnd, ulLength ) ) { pParsePosition = pParseEnd; return false; } strValue.assign( pParsePosition, (size_t)ulLength ); pParsePosition += ulLength; return true; } bool ProtobufReadStringAlias( const char * &pParsePosition, const char *pParseEnd, const char * &pStringDataStart, const char * &pStringDataEnd ) { uint64 ulLength; if ( !ProtobufDecodeVarInt( pParsePosition, pParseEnd, ulLength ) ) return false; if ( CHECK_OVERRUN( pParsePosition, pParseEnd, ulLength ) ) { pParsePosition = pParseEnd; return false; } pStringDataStart = pParsePosition; pParsePosition += ulLength; pStringDataEnd = pParsePosition; return true; } template < typename T > static bool ProtobufReadRepeated_T( const char * &pParsePosition, const char *pParseEnd, uint32 uFieldTag, std::vector< T > &vecData, bool( *pfnRead )(const char * &, const char *, T &) ) { if ( (uFieldTag & 7) == 2 ) { const char *pStart = NULL, *pEnd = NULL; if ( !ProtobufReadStringAlias( pParsePosition, pParseEnd, pStart, pEnd ) ) return false; while ( pStart != pEnd ) { T v; if ( !pfnRead( pStart, pEnd, v ) ) return false; vecData.push_back( v ); } } else { T v; if ( !pfnRead( pParsePosition, pParseEnd, v ) ) return false; vecData.push_back( v ); } return true; } bool ProtobufReadRepeatedInteger( const char * &pParsePosition, const char *pParseEnd, uint32 uFieldTag, std::vector &vec ) { return ProtobufReadRepeated_T( pParsePosition, pParseEnd, uFieldTag, vec, &ProtobufReadInteger ); } bool ProtobufReadRepeatedInteger( const char * &pParsePosition, const char *pParseEnd, uint32 uFieldTag, std::vector &vec ) { return ProtobufReadRepeated_T( pParsePosition, pParseEnd, uFieldTag, vec, &ProtobufReadInteger ); } bool ProtobufReadRepeatedInteger( const char * &pParsePosition, const char *pParseEnd, uint32 uFieldTag, std::vector &vec ) { return ProtobufReadRepeated_T( pParsePosition, pParseEnd, uFieldTag, vec, &ProtobufReadInteger ); } bool ProtobufReadRepeatedInteger( const char * &pParsePosition, const char *pParseEnd, uint32 uFieldTag, std::vector &vec ) { return ProtobufReadRepeated_T( pParsePosition, pParseEnd, uFieldTag, vec, &ProtobufReadInteger ); } bool ProtobufReadRepeatedInteger( const char * &pParsePosition, const char *pParseEnd, uint32 uFieldTag, std::vector &vec ) { return ProtobufReadRepeated_T( pParsePosition, pParseEnd, uFieldTag, vec, &ProtobufReadInteger ); } bool ProtobufReadRepeatedSInteger( const char * &pParsePosition, const char *pParseEnd, uint32 uFieldTag, std::vector &vec ) { return ProtobufReadRepeated_T( pParsePosition, pParseEnd, uFieldTag, vec, &ProtobufReadSInteger ); } bool ProtobufReadRepeatedSInteger( const char * &pParsePosition, const char *pParseEnd, uint32 uFieldTag, std::vector &vec ) { return ProtobufReadRepeated_T( pParsePosition, pParseEnd, uFieldTag, vec, &ProtobufReadSInteger ); } bool ProtobufReadRepeatedFixed32( const char * &pParsePosition, const char *pParseEnd, uint32 uFieldTag, std::vector &vec ) { return ProtobufReadRepeated_T( pParsePosition, pParseEnd, uFieldTag, vec, &ProtobufReadFixed32 ); } bool ProtobufReadRepeatedFixed32( const char * &pParsePosition, const char *pParseEnd, uint32 uFieldTag, std::vector &vec ) { return ProtobufReadRepeated_T( pParsePosition, pParseEnd, uFieldTag, vec, &ProtobufReadFixed32 ); } bool ProtobufReadRepeatedFixed32( const char * &pParsePosition, const char *pParseEnd, uint32 uFieldTag, std::vector &vec ) { return ProtobufReadRepeated_T( pParsePosition, pParseEnd, uFieldTag, vec, &ProtobufReadFixed32 ); } bool ProtobufReadRepeatedFixed64( const char * &pParsePosition, const char *pParseEnd, uint32 uFieldTag, std::vector &vec ) { return ProtobufReadRepeated_T( pParsePosition, pParseEnd, uFieldTag, vec, &ProtobufReadFixed64 ); } bool ProtobufReadRepeatedFixed64( const char * &pParsePosition, const char *pParseEnd, uint32 uFieldTag, std::vector &vec ) { return ProtobufReadRepeated_T( pParsePosition, pParseEnd, uFieldTag, vec, &ProtobufReadFixed64 ); } bool ProtobufReadRepeatedFixed64( const char * &pParsePosition, const char *pParseEnd, uint32 uFieldTag, std::vector &vec ) { return ProtobufReadRepeated_T( pParsePosition, pParseEnd, uFieldTag, vec, &ProtobufReadFixed64 ); } bool ProtobufReadRepeatedString( const char * &pParsePosition, const char *pParseEnd, uint32 uFieldTag, std::vector &vec ) { vec.push_back( std::string() ); if ( !ProtobufReadString( pParsePosition, pParseEnd, vec.back() ) ) { vec.pop_back(); return false; } return true; } template < typename T > static bool ProtobufExtractField_T( const char *pParsePosition, const char *pParseEnd, uint32 uFieldTag, T &value, bool( *pfnRead )(const char * &, const char *, T &) ) { uint32 uCurrentTag = 0; bool bOK = false; while ( ProtobufReadFieldTag( pParsePosition, pParseEnd, uCurrentTag ) ) { if ( uCurrentTag == uFieldTag ) bOK = pfnRead( pParsePosition, pParseEnd, value ); else ProtobufSkipFieldValue( pParsePosition, pParseEnd, uCurrentTag ); } return bOK; } template < typename T > static bool ProtobufExtractField_T( const char *pParsePosition, const char *pParseEnd, uint32 uFieldTag, T &value, bool( *pfnRead )(const char * &, const char *, uint32, T &) ) { uint32 uCurrentTag = 0; bool bOK = false; while ( ProtobufReadFieldTag( pParsePosition, pParseEnd, uCurrentTag ) ) { if ( uCurrentTag == uFieldTag || uCurrentTag == PROTOBUF_FIELDTAG_STRING( uFieldTag >> 3 ) ) bOK = pfnRead( pParsePosition, pParseEnd, uCurrentTag, value ); else ProtobufSkipFieldValue( pParsePosition, pParseEnd, uCurrentTag ); } return bOK; } bool ProtobufExtractField_Integer( const std::string &strProtobuf, uint32 uFieldNumber, uint64 &value ) { return ProtobufExtractField_T( strProtobuf.data(), strProtobuf.data() + strProtobuf.size(), PROTOBUF_FIELDTAG_INTEGER( uFieldNumber ), value, &ProtobufReadInteger ); } bool ProtobufExtractField_Integer( const std::string &strProtobuf, uint32 uFieldNumber, int64 &value ) { return ProtobufExtractField_T( strProtobuf.data(), strProtobuf.data() + strProtobuf.size(), PROTOBUF_FIELDTAG_INTEGER( uFieldNumber ), value, &ProtobufReadInteger ); } bool ProtobufExtractField_Integer( const std::string &strProtobuf, uint32 uFieldNumber, uint32 &value ) { return ProtobufExtractField_T( strProtobuf.data(), strProtobuf.data() + strProtobuf.size(), PROTOBUF_FIELDTAG_INTEGER( uFieldNumber ), value, &ProtobufReadInteger ); } bool ProtobufExtractField_Integer( const std::string &strProtobuf, uint32 uFieldNumber, int32 &value ) { return ProtobufExtractField_T( strProtobuf.data(), strProtobuf.data() + strProtobuf.size(), PROTOBUF_FIELDTAG_INTEGER( uFieldNumber ), value, &ProtobufReadInteger ); } bool ProtobufExtractField_Integer( const std::string &strProtobuf, uint32 uFieldNumber, bool &value ) { return ProtobufExtractField_T( strProtobuf.data(), strProtobuf.data() + strProtobuf.size(), PROTOBUF_FIELDTAG_INTEGER( uFieldNumber ), value, &ProtobufReadInteger ); } bool ProtobufExtractField_SInteger( const std::string &strProtobuf, uint32 uFieldNumber, int64 &value ) { return ProtobufExtractField_T( strProtobuf.data(), strProtobuf.data() + strProtobuf.size(), PROTOBUF_FIELDTAG_SINTEGER( uFieldNumber ), value, &ProtobufReadSInteger ); } bool ProtobufExtractField_SInteger( const std::string &strProtobuf, uint32 uFieldNumber, int32 &value ) { return ProtobufExtractField_T( strProtobuf.data(), strProtobuf.data() + strProtobuf.size(), PROTOBUF_FIELDTAG_SINTEGER( uFieldNumber ), value, &ProtobufReadSInteger ); } bool ProtobufExtractField_Fixed64( const std::string &strProtobuf, uint32 uFieldNumber, int64 &value ) { return ProtobufExtractField_T( strProtobuf.data(), strProtobuf.data() + strProtobuf.size(), PROTOBUF_FIELDTAG_FIXED64( uFieldNumber ), value, &ProtobufReadFixed64 ); } bool ProtobufExtractField_Fixed64( const std::string &strProtobuf, uint32 uFieldNumber, uint64 &value ) { return ProtobufExtractField_T( strProtobuf.data(), strProtobuf.data() + strProtobuf.size(), PROTOBUF_FIELDTAG_FIXED64( uFieldNumber ), value, &ProtobufReadFixed64 ); } bool ProtobufExtractField_Fixed64( const std::string &strProtobuf, uint32 uFieldNumber, double &value ) { return ProtobufExtractField_T( strProtobuf.data(), strProtobuf.data() + strProtobuf.size(), PROTOBUF_FIELDTAG_FIXED64( uFieldNumber ), value, &ProtobufReadFixed64 ); } bool ProtobufExtractField_Fixed32( const std::string &strProtobuf, uint32 uFieldNumber, int32 &value ) { return ProtobufExtractField_T( strProtobuf.data(), strProtobuf.data() + strProtobuf.size(), PROTOBUF_FIELDTAG_FIXED32( uFieldNumber ), value, &ProtobufReadFixed32 ); } bool ProtobufExtractField_Fixed32( const std::string &strProtobuf, uint32 uFieldNumber, uint32 &value ) { return ProtobufExtractField_T( strProtobuf.data(), strProtobuf.data() + strProtobuf.size(), PROTOBUF_FIELDTAG_FIXED32( uFieldNumber ), value, &ProtobufReadFixed32 ); } bool ProtobufExtractField_Fixed32( const std::string &strProtobuf, uint32 uFieldNumber, float &value ) { return ProtobufExtractField_T( strProtobuf.data(), strProtobuf.data() + strProtobuf.size(), PROTOBUF_FIELDTAG_FIXED32( uFieldNumber ), value, &ProtobufReadFixed32 ); } bool ProtobufExtractField_String( const std::string &strProtobuf, uint32 uFieldNumber, std::string &value ) { return ProtobufExtractField_T( strProtobuf.data(), strProtobuf.data() + strProtobuf.size(), PROTOBUF_FIELDTAG_STRING( uFieldNumber ), value, &ProtobufReadString ); } bool ProtobufExtractField_Integer( const std::string &strProtobuf, uint32 uFieldNumber, std::vector &vec ) { return ProtobufExtractField_T( strProtobuf.data(), strProtobuf.data() + strProtobuf.size(), PROTOBUF_FIELDTAG_INTEGER( uFieldNumber ), vec, &ProtobufReadRepeatedInteger ); } bool ProtobufExtractField_Integer( const std::string &strProtobuf, uint32 uFieldNumber, std::vector &vec ) { return ProtobufExtractField_T( strProtobuf.data(), strProtobuf.data() + strProtobuf.size(), PROTOBUF_FIELDTAG_INTEGER( uFieldNumber ), vec, &ProtobufReadRepeatedInteger ); } bool ProtobufExtractField_Integer( const std::string &strProtobuf, uint32 uFieldNumber, std::vector &vec ) { return ProtobufExtractField_T( strProtobuf.data(), strProtobuf.data() + strProtobuf.size(), PROTOBUF_FIELDTAG_INTEGER( uFieldNumber ), vec, &ProtobufReadRepeatedInteger ); } bool ProtobufExtractField_Integer( const std::string &strProtobuf, uint32 uFieldNumber, std::vector &vec ) { return ProtobufExtractField_T( strProtobuf.data(), strProtobuf.data() + strProtobuf.size(), PROTOBUF_FIELDTAG_INTEGER( uFieldNumber ), vec, &ProtobufReadRepeatedInteger ); } bool ProtobufExtractField_Integer( const std::string &strProtobuf, uint32 uFieldNumber, std::vector &vec ) { return ProtobufExtractField_T( strProtobuf.data(), strProtobuf.data() + strProtobuf.size(), PROTOBUF_FIELDTAG_INTEGER( uFieldNumber ), vec, &ProtobufReadRepeatedInteger ); } bool ProtobufExtractField_SInteger( const std::string &strProtobuf, uint32 uFieldNumber, std::vector &vec ) { return ProtobufExtractField_T( strProtobuf.data(), strProtobuf.data() + strProtobuf.size(), PROTOBUF_FIELDTAG_SINTEGER( uFieldNumber ), vec, &ProtobufReadRepeatedSInteger ); } bool ProtobufExtractField_SInteger( const std::string &strProtobuf, uint32 uFieldNumber, std::vector &vec ) { return ProtobufExtractField_T( strProtobuf.data(), strProtobuf.data() + strProtobuf.size(), PROTOBUF_FIELDTAG_SINTEGER( uFieldNumber ), vec, &ProtobufReadRepeatedSInteger ); } bool ProtobufExtractField_Fixed64( const std::string &strProtobuf, uint32 uFieldNumber, std::vector &vec ) { return ProtobufExtractField_T( strProtobuf.data(), strProtobuf.data() + strProtobuf.size(), PROTOBUF_FIELDTAG_FIXED64( uFieldNumber ), vec, &ProtobufReadRepeatedFixed64 ); } bool ProtobufExtractField_Fixed64( const std::string &strProtobuf, uint32 uFieldNumber, std::vector &vec ) { return ProtobufExtractField_T( strProtobuf.data(), strProtobuf.data() + strProtobuf.size(), PROTOBUF_FIELDTAG_FIXED64( uFieldNumber ), vec, &ProtobufReadRepeatedFixed64 ); } bool ProtobufExtractField_Fixed64( const std::string &strProtobuf, uint32 uFieldNumber, std::vector &vec ) { return ProtobufExtractField_T( strProtobuf.data(), strProtobuf.data() + strProtobuf.size(), PROTOBUF_FIELDTAG_FIXED64( uFieldNumber ), vec, &ProtobufReadRepeatedFixed64 ); } bool ProtobufExtractField_Fixed32( const std::string &strProtobuf, uint32 uFieldNumber, std::vector &vec ) { return ProtobufExtractField_T( strProtobuf.data(), strProtobuf.data() + strProtobuf.size(), PROTOBUF_FIELDTAG_FIXED32( uFieldNumber ), vec, &ProtobufReadRepeatedFixed32 ); } bool ProtobufExtractField_Fixed32( const std::string &strProtobuf, uint32 uFieldNumber, std::vector &vec ) { return ProtobufExtractField_T( strProtobuf.data(), strProtobuf.data() + strProtobuf.size(), PROTOBUF_FIELDTAG_FIXED32( uFieldNumber ), vec, &ProtobufReadRepeatedFixed32 ); } bool ProtobufExtractField_Fixed32( const std::string &strProtobuf, uint32 uFieldNumber, std::vector &vec ) { return ProtobufExtractField_T( strProtobuf.data(), strProtobuf.data() + strProtobuf.size(), PROTOBUF_FIELDTAG_FIXED32( uFieldNumber ), vec, &ProtobufReadRepeatedFixed32 ); } bool ProtobufExtractField_String( const std::string &strProtobuf, uint32 uFieldNumber, std::vector &vec ) { return ProtobufExtractField_T( strProtobuf.data(), strProtobuf.data() + strProtobuf.size(), PROTOBUF_FIELDTAG_STRING( uFieldNumber ), vec, &ProtobufReadRepeatedString ); }