Pergunta

Aparentemente boost::asio::async_read não como cordas, como a única sobrecarga de boost::asio::buffer me permite criar const_buffers, por isso estou preso com a ler tudo em um streambuf.
Agora eu quero copiar o conteúdo do streambuf em uma string, mas aparentemente só suporta escrevendo para char * (sgetn()), criando um istream com o streambuf e usando getline().

Existe alguma outra maneira de criar uma string com o conteúdo streambufs sem copiar excessiva?

Foi útil?

Solução

Eu não sei se isso conta como " cópia excessiva ", mas você pode usar um stringstream:

std::ostringstream ss;
ss << someStreamBuf;
std::string s = ss.str();

Como, para ler tudo, desde stdin em uma string, faça

std::ostringstream ss;
ss << std::cin.rdbuf();
std::string s = ss.str();

Como alternativa, você também pode usar um istreambuf_iterator. Você terá que medir se este ou o caminho acima é mais rápido -. Eu não sei

std::string s((istreambuf_iterator<char>(someStreamBuf)), 
               istreambuf_iterator<char>());

Note que someStreamBuf acima pretende representar uma streambuf*, por isso tome o seu endereço, conforme apropriado. Além disso, observe os parênteses adicionais ao redor do primeiro argumento no último exemplo, para que ele não interpreta isso como uma declaração de função a devolver uma cadeia e tendo um iterador e outro ponteiro de função ( "mais irritante de análise").

Outras dicas

de realmente enterrado nos docs ...

boost::asio::streambuf b Dada, com size_t buf_size ...

boost::asio::streambuf::const_buffers_type bufs = b.data();
std::string str(boost::asio::buffers_begin(bufs),
                boost::asio::buffers_begin(bufs) + buf_size);

Outra possibilidade com boost::asio::streambuf é usar boost::asio::buffer_cast<const char*>() em conjunto com boost::asio::streambuf::data() e boost::asio::streambuf::consume() assim:

const char* header=boost::asio::buffer_cast<const char*>(readbuffer.data());
//Do stuff with header, maybe construct a std::string with std::string(header,header+length)
readbuffer.consume(length);

Isso não vai funcionar com streambufs e normal pode ser considerado sujo, mas parece ser a maneira mais rápida de fazê-lo.

Para boost::asio::streambuf você pode encontrar uma solução como esta:

    boost::asio::streambuf buf;
    /*put data into buf*/

    std::istream is(&buf);
    std::string line;
    std::getline(is, line);

Imprima o string:

    std::cout << line << std::endl;

Você pode encontrar aqui: http: // www. boost.org/doc/libs/1_49_0/doc/html/boost_asio/reference/async_read_until/overload3.html

Pode-se também obter os caracteres a partir asio::streambuf usando std::basic_streambuf::sgetn:

asio::streambuf in;
// ...
char cbuf[in.size()+1]; int rc = in.sgetn (cbuf, sizeof cbuf); cbuf[rc] = 0;
std::string str (cbuf, rc);

A razão que você só pode criar const_buffer de std :: string é porque std :: string explicitamente não suporta escrita à base de ponteiro direto em seu contrato. Você poderia fazer algo mal como redimensionar a string para um certo tamanho, então const_cast o constness de c_str () e tratá-lo como um char cru * buffer, mas isso é muito desobediente e vai chegar em algum dia problemas.

Eu uso std :: vector para os meus tampões porque, enquanto o vetor não redimensionar (ou você é cuidadoso ao lidar com o redimensionamento), você pode fazer ponteiro direto escrever muito bem. Se eu precisar de alguns dos dados como um std :: string, eu tenho que copiá-lo para fora, mas o que eu negócio caminho com meus buffers de leitura, qualquer coisa que precisa última para além das necessidades de leitura de retorno de chamada a ser copiado independentemente.

A resposta mais simples seria a de convertê-lo em std::string e manipulá-lo alguns que como este

 std::string buffer_to_string(const boost::asio::streambuf &buffer)
 {
  using boost::asio::buffers_begin;
  auto bufs = buffer.data();
  std::string result(buffers_begin(bufs), buffers_begin(bufs) + buffer.size());
 return result;
}

Dar um código muito concisa para a tarefa.

Eu acho que é mais parecido com:


streambuf.commit( number_of_bytes_read );

istream istr( &streambuf );
string s;
istr >> s;

Eu não olhei para o código basic_streambuf, mas eu acredito que deve ser apenas uma cópia para o string.

Eu testei a primeira resposta e tem um erro do compilador quando compilar usando "g ++ -std = c ++ 11" O que funcionou para mim foi:

        #include <string>
        #include <boost/asio.hpp>
        #include <sstream>           
        //other code ...
        boost::asio::streambuf response;
        //more code
        std::ostringstream sline;
        sline << &response; //need '&' or you a compiler error
        std::string line = sline.str(); 

Este compilado e correu.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top