Юникодизация программы: оцените подход.
От: Модуль Оверлеев  
Дата: 15.08.07 12:36
Оценка:
привет!
в рамках очередного проекта надо перевести программу с анси на юникод. перво-наперво хочется уйти от выходов за границы буферов, которые сплошь и рядом возможны в местах подобных такому:
TCHAR valName[MAX_PATH];
for(    DWORD i = 0, valNameSize = sizeof(valName); 
    ERROR_SUCCESS == RegEnumValue(key.m_hKey, i, valName, &valNameSize, NULL, NULL, NULL, NULL); 
    ++i, valNameSize = sizeof_arr(valName))

пока массив valName был char[], размер буффера соответствовал размеру sizeof(valName), когда он стал wchar_t[], передаваемый RegEnumValue размер стал больше, чем сам буффер, и стало возможно переполнение.
определять размер статического массива очень удобно с помощью макроса, найденного мной на этом форуме:
template<class T, std::size_t N> 
char(&sizeof_funca(T(&)[N]))[N];

#define lengthof_arr(arr) sizeof(unicodization::sizeof_funca(arr))

великолепие этого подхода состоит в том, что данному макросу можно передать только переменную-массив, ничто другое не скомпилится. была идея подменить sizeof lengthof_arr и исправить все ошибки, которые возникают в результате компиляции. т.е. код, приведенный в первом примере, скомпилился бы, а вот код типа
int i = sizeof(int);
int j = sizeof(i);

компиляться бы отказался, и нужно было бы sizeof на что-то менять. мне показалось, что будет логично заменить на что-то похожее на
int i = lengthof_type(int);
int j = lengthof_val(i);

и очень хочется, чтобы lengthof_type можно было использовать только с типом, и lengthof_val только со значением. указатели хочется исключить.
вот что у меня получилось:
namespace unicodization
{
    template<class T, std::size_t N> 
    char(&sizeof_funca(T(&)[N]))[N];

    template<class T, std::size_t N> 
    struct sizeof_class;
    template<class T> 
    struct sizeof_class<T, 0>{ char size[sizeof(T)]; };
    template<class T> 
    struct sizeof_class<T*, 0>;

    template<typename T>
    sizeof_class<T, 0>(&sizeof_funcv(T&));
    template<class T, std::size_t N> 
    sizeof_class<T, N>(&sizeof_funcv(T(&)[N]));

    template<typename T>
    struct type_check{ typedef T thetype;char size[sizeof(T)]; };

}

#define lengthof_arr(arr) sizeof(unicodization::sizeof_funca(arr))
#define lengthof_val(val) sizeof(unicodization::sizeof_funcv(val))
#define lengthof_type(t) sizeof(unicodization::type_check< t >)

#define sizeof(x) sizeof_arr(x)


по ходу исправления ошибок я проверяю, какой именно сайзоф нужен,и ставлю именно его. заключительном этапом является исправление всех sizeof на lengthof_arr и раздефайниванием сайзофа.
какие камни я не увидел, может есть что-то проще?
---
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.