简体   繁体   中英

Create a streambuf from const char* WITHOUT boost?

Same question as Create a streambuf from const char* except that I can't use boost .

I have to implement an function that takes a const char * as input parameter, and to do so I have to call an other function that takes a istream as input parameter.

Here is a sample of code very simplified:

#include <iostream>
#include <string>
using namespace std ;

void inner_function_I_cant_change ( istream & input ) // the function I must use
    {
    string s ; // dummy implementation
    input >> s ;
    cout << s.size() << " : <" << s << ">" << endl ;
    }

struct externbuf : streambuf // my own streambuf using a char*...
    {
    int    size ;
    bool   done ;
    char * buffer ;

    externbuf ( const char * buffer , int size ) :
        size(size),
        done(false),
        buffer(const_cast<char*>( buffer )) {} // ...that forces me to an ugly const_cast !

    int underflow () 
        {
        if (this->gptr() == this->egptr()) 
            {
            if (done) return std::char_traits<char>::eof() ;
            this->setg( buffer,buffer,buffer+size ) ;
            done = true ;
            }
        return char_traits<char>::to_int_type( *this->gptr()) ;
        }
    };

void API_function_I_must_povide ( const char * data , int size ) // the function I must implement
    {
    externbuf buf( data,size ) ;
    istream   input( &buf ) ;
    inner_function_I_cant_change( input )  ;
    }

int main ()
    {
    API_function_I_must_povide( "bazinga!",8 ) ;
    }

This code I works well but I had to do an ugly const_cast !
I tried using a basic_streambuf<const char, char_traits<const char> > instead of a streambuf but I get many errors that I didn't understand well.

Is there a proper way to do it?
(and, as I said, I can't use boost )

Thanks !

Thanks Remy , your link to Art Of Code made my day!

So, for those who are interested, here my new code, without memcpy and ugly const_cast :


#include <iostream>
#include <string>
using namespace std ;

void inner_function_I_cant_change ( istream & input )
    {
    char buffer [1000] ;
    input.read( buffer,sizeof buffer ) ;
    string s1( buffer,input.gcount()) ;
    string s2( "hello \0 world !",15 ) ;
    if (s1 == s2) 
        cout << "success!" ;
    }

struct externbuf : public streambuf 
    {
    externbuf ( const char * data , unsigned int len ) : begin(data),crt(data),end(data + len) {}

    int_type underflow ()
        {
        return crt == end ? traits_type::eof() : traits_type::to_int_type( *crt ) ;
        }
    int_type uflow ()
        {
        return crt == end ? traits_type::eof() : traits_type::to_int_type( *crt++ ) ;
        }
    int_type pbackfail ( int_type ch )
        {
        bool cond = crt == begin || (ch != traits_type::eof() && ch != crt[-1]) ;
        return cond ? traits_type::eof() : traits_type::to_int_type( *--crt ) ;
        }
    streamsize showmanyc ()
        {
        return end - crt ;
        }

    const char *begin,*crt,*end ;
    };

void API_function_I_must_povide ( const char * data , int size )
    {
    externbuf buf( data,size ) ; 
    istream input( &buf ) ;
    inner_function_I_cant_change( input )  ;
    }

int main ()
    {
    API_function_I_must_povide( "hello \0 world !",15 ) ;
    }

Thanks Pete , your solution is development-less but I'm afraid it induces a memcpy from data to the inner buffer of the std::string . And since my buffer may be very big, I try to avoid them as much as possible.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM