ライブラリから受け取っているchar *とデータ長があり、データをistreamを受け取る関数に渡す必要があります。
文字列ストリームを作成できることは知っていますが、すべてのデータがコピーされます。また、Zipファイルであるため、データには必ず0が含まれます。stringstreamを作成すると、最初の0までデータが取得されます。
Char *からistreamを作成する方法はありますか?また、すべてのデータをコピーせずにそのサイズになりますか?
非推奨のメソッドは次のとおりです Webで見つかりました 、独自のstd::streambuf
クラスですが、簡単で動作するようです:
#include <iostream>
#include <istream>
#include <streambuf>
#include <string>
struct membuf : std::streambuf
{
membuf(char* begin, char* end) {
this->setg(begin, begin, end);
}
};
int main()
{
char buffer[] = "I'm a buffer with embedded nulls\0and line\n feeds";
membuf sbuf(buffer, buffer + sizeof(buffer));
std::istream in(&sbuf);
std::string line;
while (std::getline(in, line)) {
std::cout << "line: " << line << "\n";
}
return 0;
}
どの出力:
line: I'm a buffer with embedded nullsand line
line: feeds
Boostを使用した非推奨のソリューション:
#include <boost/iostreams/stream.hpp>
#include <boost/iostreams/device/array.hpp>
using namespace boost::iostreams;
basic_array_source<char> input_source(my_ptr_to_char, byte_count);
stream<basic_array_source<char> > input_stream(input_source);
またはさらに簡単:
#include <boost/interprocess/streams/bufferstream.hpp>
using namespace boost::interprocess;
bufferstream input_stream(my_ptr_to_char, byte_count);
tellg
とseekg
をサポートし、ブーストを必要としないソリューションが必要でした。
char_array_buffer
from カスタムストリームバッファ(std :: streambuf)を作成するための初心者向けガイド は、開始点を示しています。
byte_array_buffer.h:
#include <cstdio>
#include <string>
#include <list>
#include <fstream>
#include <iostream>
//
// http://www.mr-edd.co.uk/blog/beginners_guide_streambuf
//
class byte_array_buffer : public std::streambuf
{
public:
byte_array_buffer(const uint8_t *begin, const size_t size);
private:
int_type underflow();
int_type uflow();
int_type pbackfail(int_type ch);
std::streamsize showmanyc();
std::streampos seekoff ( std::streamoff off, std::ios_base::seekdir way,
std::ios_base::openmode which = std::ios_base::in | std::ios_base::out );
std::streampos seekpos ( std::streampos sp,
std::ios_base::openmode which = std::ios_base::in | std::ios_base::out);
// copy ctor and assignment not implemented;
// copying not allowed
byte_array_buffer(const byte_array_buffer &);
byte_array_buffer &operator= (const byte_array_buffer &);
private:
const uint8_t * const begin_;
const uint8_t * const end_;
const uint8_t * current_;
};
byte_array_buffer.cpp:
#include "byte_array_buffer.h"
#include <cassert>
byte_array_buffer::byte_array_buffer(const uint8_t *begin, const size_t size) :
begin_(begin),
end_(begin + size),
current_(begin_)
{
assert(std::less_equal<const uint8_t *>()(begin_, end_));
}
byte_array_buffer::int_type byte_array_buffer::underflow()
{
if (current_ == end_)
return traits_type::eof();
return traits_type::to_int_type(*current_);
}
byte_array_buffer::int_type byte_array_buffer::uflow()
{
if (current_ == end_)
return traits_type::eof();
return traits_type::to_int_type(*current_++);
}
byte_array_buffer::int_type byte_array_buffer::pbackfail(int_type ch)
{
if (current_ == begin_ || (ch != traits_type::eof() && ch != current_[-1]))
return traits_type::eof();
return traits_type::to_int_type(*--current_);
}
std::streamsize byte_array_buffer::showmanyc()
{
assert(std::less_equal<const uint8_t *>()(current_, end_));
return end_ - current_;
}
std::streampos byte_array_buffer::seekoff ( std::streamoff off, std::ios_base::seekdir way,
std::ios_base::openmode which )
{
if (way == std::ios_base::beg)
{
current_ = begin_ + off;
}
else if (way == std::ios_base::cur)
{
current_ += off;
}
else if (way == std::ios_base::end)
{
current_ = end_;
}
if (current_ < begin_ || current_ > end_)
return -1;
return current_ - begin_;
}
std::streampos byte_array_buffer::seekpos ( std::streampos sp,
std::ios_base::openmode which )
{
current_ = begin_ + sp;
if (current_ < begin_ || current_ > end_)
return -1;
return current_ - begin_;
}
唯一の(単純な)移植可能な方法には、コピーの作成が含まれます。
std::istringstream ss(std::string(buf,len));
実際、これはデータを2回コピーする可能性があります。1回はstring
を作成し、1回はistringstream
を作成します。 (C++ 11は、移動コンストラクターを介してコピーの1つを回避できる可能性があります。私にはわかりません。)
ただし、運がよければ、C++実装でこれを行うことができます。
std::istringstream ss;
ss.rdbuf()->pubsetbuf(buf,len);
GNU C++(および、他のいくつかの実装)では、これによりデータをコピーせずに文字列ストリームが作成されます。ただし、これは仕様に従って「実装定義」の動作です。 この質問 。)
len
パラメーターを含めることにより、これらの両方がヌル文字に問題がないことを確認できます。
必要なことを行う唯一の移植可能な方法は、独自のstringbuf
のサブクラスを実装し、それを使用して文字列ストリームを初期化することです。気弱な人向けではありません。
Std :: istrstreamを試しましたか? http://stdcxx.Apache.org/doc/stdlibref/istrstream.html
技術的には、非推奨ですが、まだ標準の一部であると思います。