Потоковая манипуляция языком в C ++ - PullRequest
1 голос
/ 03 июля 2011

Есть ли какой-либо стандартный способ установки локали для разных платформ? Я вижу, что xlocale предоставляет uselocale, но он не поддерживается в Windows. Существует "_configthreadlocale (_ENABLE_PER_THREAD_LOCALE);" в Windows, после чего setlocale работает на основе потока. У меня вопрос, есть ли библиотека, которая обеспечивает эти специфичные для локали манипуляции независимым от платформы способом ??? Или какой-то другой способ сделать это?

Спасибо, Gokul.

Ответы [ 2 ]

1 голос
/ 18 июня 2013

У меня была такая же проблема, и я в итоге написал для нее небольшой код кросс-совместимости. Я пытался следовать спецификации как можно ближе, но у нее есть несколько ограничений.

В этом коде newlocale не позволяет вам указать базовый языковой стандарт, и вы также не можете смешивать маски категорий. Но для некоторого базового переключения между различными локалями этого должно быть достаточно.

// Locale Cross-Compatibility
#ifdef _WIN32
#define locale_t         _locale_t
#define freelocale       _free_locale

#define LC_GLOBAL_LOCALE ((locale_t)-1)
#define LC_ALL_MASK      LC_ALL
#define LC_COLLATE_MASK  LC_COLLATE
#define LC_CTYPE_MASK    LC_CTYPE
#define LC_MONETARY_MASK LC_MONETARY
#define LC_NUMERIC_MASK  LC_NUMERIC
#define LC_TIME_MASK     LC_TIME

// Base locale is ignored and mixing of masks is not supported
#define newlocale(mask, locale, base) _create_locale(mask, locale)

locale_t uselocale(locale_t new_locale)
{
    // Retrieve the current per thread locale setting
    bool bIsPerThread = (_configthreadlocale(0) == _ENABLE_PER_THREAD_LOCALE);

    // Retrieve the current thread-specific locale
    locale_t old_locale = bIsPerThread ? _get_current_locale() : LC_GLOBAL_LOCALE;

    if(new_locale == LC_GLOBAL_LOCALE)
    {
        // Restore the global locale
        _configthreadlocale(_DISABLE_PER_THREAD_LOCALE);
    }
    else if(new_locale != NULL)
    {
        // Configure the thread to set the locale only for this thread
        _configthreadlocale(_ENABLE_PER_THREAD_LOCALE);

        // Set all locale categories
        for(int i = LC_MIN; i <= LC_MAX; i++)
            setlocale(i, new_locale->locinfo->lc_category[i].locale);
    }

    return old_locale;
}
#endif

Поместите этот код в свой проект, и вы сможете переключать локаль для потока на любой платформе, например:

#include <locale.h>
#ifdef __APPLE__
#include <xlocale.h>
#endif

// Apply a new locale to this thread
locale_t locale = newlocale(LC_NUMERIC_MASK, "C", NULL);
locale_t old_locale = uselocale(locale);

// Print out some text
printf("Always use dot-decimal notation: %f", 1.5);

// Restore the global locale
uselocale(old_locale);
freelocale(locale);
0 голосов
/ 03 июля 2011

Boost :: Locale предоставляет кросс-платформенный интерфейс на основе библиотеки iconv .Это может быть не идеальным интерфейсом, если вы надеетесь, что стандартные функции библиотеки C будут вести себя должным образом, как только вы установите языковой стандарт.Вместо этого вы будете вручную управлять локалями как объектами и явно использовать их.Вы явно генерируете локали и используете их для создания компараторов и всего, что вам нужно, в зависимости от локали.

С одной стороны, это означает любой ранее разработанный код, который вы написаликоторый зависит от конкретной локали, должен быть переписан.С другой стороны, под капотом скрыто намного меньше ошибок, поскольку вы явно определяете, какой язык / кодировка используется где.

...