2016-05-06 43 views
10

我想複製有效的std::streambuf實例之間的數據。也就是說,我想剷除它們之間的數據塊,而不是逐字符複製。例如,這是不是我在尋找:流緩衝區之間的數據的塊級複製

stringbuf in{ios_base::in}; 
stringbuf out{ios_base::out}; 
copy(istreambuf_iterator<char>{in}, 
    istreambuf_iterator<char>{}, 
    ostreambuf_iterator<char>{out}); 

存在着這種語法糖,有一點錯誤檢查:

ostream os{&out}; 
os << &in; 

這裏是operator<<(basic_streambuf<..>*)實施的一個片段在我的標準庫(Mac OS X,XCode 7)中:

   typedef istreambuf_iterator<_CharT, _Traits> _Ip; 
       typedef ostreambuf_iterator<_CharT, _Traits> _Op; 
       _Ip __i(__sb); 
       _Ip __eof; 
       _Op __o(*this); 
       size_t __c = 0; 
       for (; __i != __eof; ++__i, ++__o, ++__c) 
       { 
        *__o = *__i; 
        if (__o.failed()) 
         break; 
       } 

底線是:這仍然是每個字符複製。我希望標準庫使用的算法依賴於流緩衝區的塊級成員函數sputnsgetn,而不是每個字符的傳輸。標準庫是否提供了這樣的算法,還是必須推出自己的算法?

+3

的問題的輸出是,這是基於與虛擬功能的接口上。你永遠不知道什麼時候'* __ o = * __ i''將無法輸出,所以你不能提前閱讀並且有可能失去這些角色。 –

+0

你找到了方法嗎? – barney

回答

1

恐怕答案是:目前標準庫的設計是不可能的。原因是流緩衝區完全隱藏了它們管理的字符序列。這使得不可能將字節從一個流緩衝區的get區域直接複製到另一個緩衝區的放置區域。

如果「輸入」流緩衝區會暴露其內部緩衝區,那麼「輸出」流緩衝區可以使用sputn(in.data(), in.size())。或者更明顯的是:如果輸出緩衝區還暴露了其內部緩衝區,那麼可以使用普通的memcpy剷除兩者之間的字節。其他I/O庫以這種方式運行:例如Google協議緩衝區的stream implementation。 Boost IOStreams有optimized implementation to copy between streams。在這兩種情況下,高效的塊級複製都是可能的,因爲等效的流緩衝區提供對中間緩衝區的訪問。具有諷刺意味的是,流緩衝區甚至不需要緩衝區:當操作無緩衝區時,每個讀/寫操作都會直接傳送到底層設備。據推測,這是標準庫不支持內省的原因之一。不幸的是,輸入和輸出流緩衝之間沒有有效的複製是可能的。塊級複製需要一箇中間緩衝區,複製算法的操作如下:

  1. 通過sgetn將輸入流緩衝區讀入中間緩衝區。
  2. 通過sputn從中間緩衝區寫入輸出流緩衝區。
  3. 轉到1.直到輸入信息已耗盡或寫入失敗streambuffer