banan-os/userspace/libraries/LibC/libintl.cpp

208 lines
5.3 KiB
C++

#include <langinfo.h>
#include <libintl.h>
#include <locale.h>
#include <stdlib.h>
#include <string.h>
struct text_domain_t
{
char* domain_name;
char* codeset;
char* dir_name;
};
static text_domain_t* s_text_domains = nullptr;
static size_t s_text_domain_count = 0;
static char* s_current_domain = nullptr;
static text_domain_t* find_text_domain(const char* domainname)
{
for (size_t i = 0; i < s_text_domain_count; i++)
{
if (strcmp(s_text_domains[i].domain_name, domainname) != 0)
continue;
return &s_text_domains[i];
}
return nullptr;
}
static text_domain_t* bind_new_textdomain(const char* domainname, const char* codeset, const char* dirname)
{
auto* new_text_domains = static_cast<text_domain_t*>(realloc(s_text_domains, (s_text_domain_count + 1) * sizeof(text_domain_t)));
if (new_text_domains == nullptr)
return nullptr;
s_text_domains = new_text_domains;
auto& new_text_domain = new_text_domains[s_text_domain_count];
new_text_domain.domain_name = strdup(domainname);
new_text_domain.dir_name = strdup(dirname);
new_text_domain.codeset = strdup(codeset);
if (!new_text_domain.domain_name || !new_text_domain.codeset || !new_text_domain.dir_name)
{
if (new_text_domain.domain_name)
free(new_text_domain.domain_name);
if (new_text_domain.codeset)
free(new_text_domain.codeset);
if (new_text_domain.dir_name)
free(new_text_domain.dir_name);
return nullptr;
}
s_text_domain_count++;
return &new_text_domain;
}
char* bindtextdomain(const char* domainname, const char* dirname)
{
if (domainname == nullptr || *domainname == '\0')
return nullptr;
auto* text_domain = find_text_domain(domainname);
if (dirname == nullptr)
{
if (text_domain != nullptr)
return text_domain->dir_name;
return const_cast<char*>("");
}
if (text_domain)
{
char* dirname_copy = strdup(dirname);
if (dirname_copy == nullptr)
return nullptr;
if (text_domain->dir_name)
free(text_domain->dir_name);
text_domain->dir_name = dirname_copy;
return text_domain->dir_name;
}
auto* new_current_domain = bind_new_textdomain(domainname, nl_langinfo(CODESET), dirname);
if (new_current_domain == nullptr)
return nullptr;
return new_current_domain->domain_name;
}
char* bind_textdomain_codeset(const char* domainname, const char* codeset)
{
if (domainname == nullptr || *domainname == '\0')
return nullptr;
auto* text_domain = find_text_domain(domainname);
if (codeset == nullptr || *codeset == '\0')
{
if (text_domain == nullptr)
return nl_langinfo(CODESET);
return text_domain->codeset;
}
if (text_domain)
{
char* codeset_copy = strdup(codeset);
if (codeset_copy == nullptr)
return nullptr;
free(text_domain->codeset);
text_domain->codeset = codeset_copy;
return codeset_copy;
}
auto* new_text_domain = bind_new_textdomain(domainname, codeset, "");
if (new_text_domain == nullptr)
return nullptr;
return new_text_domain->codeset;
}
char* textdomain(const char* domainname)
{
if (domainname == nullptr || *domainname == '\0')
{
if (s_current_domain == nullptr)
s_current_domain = strdup("messages");
return s_current_domain;
}
char* new_current_domain = strdup(domainname);
if (new_current_domain == nullptr)
return nullptr;
if (s_current_domain != nullptr)
free(s_current_domain);
s_current_domain = new_current_domain;
return s_current_domain;
}
char* dgettext(const char* domainname, const char* msgid)
{
return dgettext_l(domainname, msgid, __getlocale(LC_MESSAGES));
}
char* dgettext_l(const char* domainname, const char* msgid, locale_t locale)
{
return dngettext_l(domainname, msgid, nullptr, 1, locale);
}
char* dcgettext(const char* domainname, const char* msgid, int category)
{
return dcgettext_l(domainname, msgid, category, __getlocale(LC_MESSAGES));
}
char* dcgettext_l(const char* domainname, const char* msgid, int category, locale_t locale)
{
return dcngettext_l(domainname, msgid, nullptr, 1, category, locale);
}
char* dngettext(const char* domainname, const char* msgid, const char* msgid_plural, unsigned long int n)
{
return dngettext_l(domainname, msgid, msgid_plural, n, __getlocale(LC_MESSAGES));
}
char* dngettext_l(const char* domainname, const char* msgid, const char* msgid_plural, unsigned long int n, locale_t locale)
{
return dcngettext_l(domainname, msgid, msgid_plural, n, 0, locale);
}
char* dcngettext(const char* domainname, const char* msgid, const char* msgid_plural, unsigned long int n, int category)
{
return dcngettext_l(domainname, msgid, msgid_plural, n, category, __getlocale(LC_MESSAGES));
}
char* dcngettext_l(const char* domainname, const char* msgid, const char* msgid_plural, unsigned long int n, int category, locale_t locale)
{
// TODO: do actual translations :D
// FIXME: handle domain codeset
(void)locale;
(void)domainname;
(void)category;
return const_cast<char*>((n == 1) ? msgid : msgid_plural);
}
char* gettext(const char* msgid)
{
return gettext_l(msgid, __getlocale(LC_MESSAGES));
}
char* gettext_l(const char* msgid, locale_t locale)
{
return dgettext_l(s_current_domain, msgid, locale);
}
char* ngettext(const char* msgid, const char* msgid_plural, unsigned long int n)
{
return ngettext_l(msgid, msgid_plural, n, __getlocale(LC_MESSAGES));
}
char* ngettext_l(const char* msgid, const char* msgid_plural, unsigned long int n, locale_t locale)
{
return dngettext_l(s_current_domain, msgid, msgid_plural, n, locale);
}