2012-10-16 78 views
3

我似乎無法找到protobuf中的MessageLite類的MergeFrom*ParseFrom*方法之間的明顯區別。MergeFrom *與ParseFrom *在谷歌的protobuf庫

我試圖儘量減少我必須做數據複製的量,所以我寫了下面的下面的代碼來解碼一個長度爲前綴的消息:

bool StreamMessageDelimiter::receiveWithLengthPrefix(Message& message) 
{ 
    google::protobuf::uint32 messageSize; 
    auto_ptr<google::protobuf::uint8> prefixBuf(new google::protobuf::uint8[sizeof(messageSize)]); 
    int receivedBytes = receiveNBytes(prefixBuf.get(), sizeof(messageSize)); 
    if(receivedBytes != sizeof(messageSize)) 
    { 
     return false; 
    } 

    CodedInputStream prefixInput(prefixBuf.get(), sizeof(messageSize)); 
    prefixInput.ReadLittleEndian32(&messageSize); 

    google::protobuf::uint8* payloadBuf = new google::protobuf::uint8[messageSize]; 
    receivedBytes = receiveNBytes(payloadBuf, messageSize); 
    if(receivedBytes != messageSize) 
    { 
     return false; 
    } 

    ArrayInputStream rawInput(payloadBuf, messageSize); 
    CodedInputStream codedInput(&rawInput); 

    if(!message.MergeFromCodedStream(&codedInput)) 
    { 
     return false; 
    } 

    return true; 
} 

我的問題是不使用MergeFromCodedStream導致message取得payloadBuf的所有權,或message是否製作底層數據的副本?如果message確實複製了一份,那麼我明顯應該使用auto_ptr作爲payloadBuf,就像我爲prefixBuf所做的一樣。

感謝您的意見!

回答

1

檢查ArrayInputStream的文檔:

「數據」保持通話對方的財產,但必須保持有效,直到 流被破壞。

所以不,它不承擔所有權,您應該確保在正確的時間釋放內存。

我想你可能會在函數名稱中使用Merge這個詞而感到困惑。它不會說「數據是從傳遞的緩衝區中合併的」(我認爲這會導致您考慮所有權),而是「數據被合併到消息中」。因此,Parse在填寫消息之前調用Clear(),而Merge使用您原樣直接傳遞的消息。

5

首先MergeFrom*不像ParseFrom*的方法工作。像MergeFrom從消息類 第一個工作:

奇異字段將被覆蓋,除了其中將合併嵌入消息。重複的字段將被連接。

ParseFrom是wraper,和呼叫之前簡單地調用ClearMergeFrom

清除()避免釋放內存中,假設分配的任何內存來保存將被再次需要保持該消息的部分下一條消息。如果您確實想釋放消息使用的內存,則必須將其刪除。

因此,直到您的消息被清除,所有重複的字段將聚合新的數據。

存儲在序列化流中的數據是Varint encoded,因此解析通過解釋流中的數據並複製到Message對象字段來完成。

解析完成後,消息本身不需要緩衝區。

相關問題