user3758447
user3758447

Reputation: 3

wcscpy_s not affecting wchar_t*

I'm trying to load some strings from a database into a struct, but I keep running into an odd issue. Using my struct datum,

struct datum {
    wchar_t*    name;
    wchar_t*    lore;
};

I tried the following code snippet

datum thisDatum;
size_t len = 0;
wchar_t wBuffer[2048];

mbstowcs_s(&len, wBuffer, (const char*)sqlite3_column_text(pStmt, 1), 2048);
if (len) {
    thisDatum.name = new wchar_t[len + 1];
    wcscpy_s(thisDatum.name, len + 1, wBuffer);
} else thisDatum.name = 0;

mbstowcs_s(&len, wBuffer, (const char*)sqlite3_column_text(pStmt, 2), 2048);
if (len) {
    thisDatum.lore = new wchar_t[len + 1];
    wcscpy_s(thisDatum.lore, len + 1, wBuffer);
} else thisDatum.name = 0;

However, while thisDatum.name copies correctly, thisDatum.lore is always garbage, except on two occassions. If the project is Debug, everything is fine, but that just isn't an option. I also discovered that rewriting the struct datum

struct datum {
    wchar_t*    lore;
    wchar_t*    name;
};

completely fixes the issue for thisDatum.lore, but gives me garbage for thisDatum.name.

Upvotes: 0

Views: 480

Answers (1)

Remy Lebeau
Remy Lebeau

Reputation: 597580

Try something more like this:

struct datum {
    wchar_t*    name;
    wchar_t*    lore;
};

wchar_t* widen(const char *str)
{
    wchar_t *wBuffer = NULL;
    size_t len = strlen(str) + 1;
    size_t wlen = 0;
    mbstowcs_s(&wlen, NULL, 0, str, len);
    if (wlen)
    {
        wBuffer = new wchar_t[wlen];
        mbstowcs_s(NULL, wBuffer, wlen, str, len);
    }
    return wBuffer;
}

datum thisDatum;
thisDatum.name = widen((const char*)sqlite3_column_text(pStmt, 1));
thisDatum.lore = widen((const char*)sqlite3_column_text(pStmt, 2));
...
delete[] thisDatum.name;
delete[] thisDatum.lore;

That being said, I would use std::wstring instead:

struct datum {
    std::wstring    name;
    std::wstring    lore;
};

#include <locale>
#include <codecvt>

std::wstring widen(const char *str)
{
    std::wstring_convert< std::codecvt<wchar_t, char, std::mbstate_t> > conv;
    return conv.from_bytes(str);
}

datum thisDatum;
thisDatum.name = widen((const char*)sqlite3_column_text(pStmt, 1));
thisDatum.lore = widen((const char*)sqlite3_column_text(pStmt, 2));

Upvotes: 1

Related Questions