Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fill std::string directly from C API

I find myself writing c++ wrappers around C style APIs pretty frequently, and a common bit of wasteful code I write goes like this:

//getSomeString() wraps C api that gets some C string from somewhere
std::string MyClass::getSomeString()
{
    char buffer[BUFFER_MAX];
    memset(buffer, '\0', BUFFER_MAX);
    auto result = GetCApiString(buffer, BUFFER_MAX); //C style string getter 
    return (result == NO_ERROR) ? std::string{buffer} : ""; //Copy here
}

But I'd really like to do something like this:

//getSomeString(): as before
std::string MyClass::getSomeString()
{
    DirectStringFillIterator<char> returnString; // <--HERE. Is something like this possible?
    auto result = GetCApiString(returnString, BUFFER_MAX);
    return (result == NO_ERROR) ? returnString.str() : ""; 
}

Is such a thing possible?

like image 631
Tyler Lewis Avatar asked Dec 23 '22 13:12

Tyler Lewis


1 Answers

std::string is guaranteed to be contiguous since C++11 (but it's such even in C++03 on every implementation I've ever met). So, usually you can just do

std::string MyClass::getSomeString() {
    std::string ret(BUFFER_MAX, '\0');
    if(GetCApiString(&ret[0], ret.size()) != NO_ERROR) return "";
    ret.resize(ret.find_first_of(0));
    return ret;
}

This avoid one copy over your first method (from local buffer to the returned string), but forces the returned string to allocate BUFFER_MAX bytes always, which may or may not be a downside in your cases.

like image 167
Matteo Italia Avatar answered Jan 26 '23 10:01

Matteo Italia