Skip to content

Commit

Permalink
utils: add CLocale
Browse files Browse the repository at this point in the history
  • Loading branch information
Montellese committed Mar 6, 2015
1 parent e5ed79d commit 2541675
Show file tree
Hide file tree
Showing 5 changed files with 667 additions and 0 deletions.
235 changes: 235 additions & 0 deletions xbmc/utils/Locale.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
/*
* Copyright (C) 2015 Team XBMC
* http://xbmc.org
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with XBMC; see the file COPYING. If not, see
* <http://www.gnu.org/licenses/>.
*
*/

#include "Locale.h"
#include "utils/StringUtils.h"

const CLocale CLocale::Empty;

CLocale::CLocale()
: m_valid(false),
m_language(),
m_territory(),
m_codeset(),
m_modifier()
{ }

CLocale::CLocale(const std::string& language)
: m_valid(false),
m_language(),
m_territory(),
m_codeset(),
m_modifier()
{
m_valid = ParseLocale(language, m_language, m_territory, m_codeset, m_modifier);
}

CLocale::CLocale(const std::string& language, const std::string& territory)
: m_valid(false),
m_language(language),
m_territory(territory),
m_codeset(),
m_modifier()
{
Initialize();
}

CLocale::CLocale(const std::string& language, const std::string& territory, const std::string& codeset)
: m_valid(false),
m_language(language),
m_territory(territory),
m_codeset(codeset),
m_modifier()
{
Initialize();
}

CLocale::CLocale(const std::string& language, const std::string& territory, const std::string& codeset, const std::string& modifier)
: m_valid(false),
m_language(language),
m_territory(territory),
m_codeset(codeset),
m_modifier(modifier)
{
Initialize();
}

CLocale::~CLocale()
{ }

CLocale CLocale::FromString(const std::string& locale)
{
return CLocale(locale);
}

bool CLocale::operator==(const CLocale& other) const
{
if (!m_valid && !other.m_valid)
return true;

return m_valid == other.m_valid &&
StringUtils::EqualsNoCase(m_language, other.m_language) &&
StringUtils::EqualsNoCase(m_territory, other.m_territory) &&
StringUtils::EqualsNoCase(m_codeset, other.m_codeset) &&
StringUtils::EqualsNoCase(m_modifier, other.m_modifier);
}

std::string CLocale::ToString() const
{
if (!m_valid)
return "";

std::string locale = ToShortString();

if (!m_codeset.empty())
locale += "." + m_codeset;

if (!m_modifier.empty())
locale += "@" + m_modifier;

return locale;
}

std::string CLocale::ToStringLC() const
{
if (!m_valid)
return "";

std::string locale = ToString();
StringUtils::ToLower(locale);

return locale;
}

std::string CLocale::ToShortString() const
{
if (!m_valid)
return "";

std::string locale = m_language;

if (!m_territory.empty())
locale += "_" + m_territory;

return locale;
}

std::string CLocale::ToShortStringLC() const
{
if (!m_valid)
return "";

std::string locale = ToShortString();
StringUtils::ToLower(locale);

return locale;
}

bool CLocale::Equals(const std::string& locale) const
{
CLocale other = FromString(locale);

return *this == other;
}

bool CLocale::Matches(const std::string& locale) const
{
CLocale other = FromString(locale);

if (!m_valid && !other.m_valid)
return true;
if (!m_valid || !other.m_valid)
return false;

if (!StringUtils::EqualsNoCase(m_language, other.m_language))
return false;
if (!m_territory.empty() && !other.m_territory.empty() && !StringUtils::EqualsNoCase(m_territory, other.m_territory))
return false;
if (!m_codeset.empty() && !other.m_codeset.empty() && !StringUtils::EqualsNoCase(m_codeset, other.m_codeset))
return false;
if (!m_modifier.empty() && !other.m_modifier.empty() && !StringUtils::EqualsNoCase(m_modifier, other.m_modifier))
return false;

return true;
}

bool CLocale::CheckValidity(const std::string& language, const std::string& territory, const std::string& codeset, const std::string& modifier)
{
static_cast<void>(territory);
static_cast<void>(codeset);
static_cast<void>(modifier);

return !language.empty();
}

bool CLocale::ParseLocale(const std::string &locale, std::string &language, std::string &territory, std::string &codeset, std::string &modifier)
{
if (locale.empty())
return false;

language.clear();
territory.clear();
codeset.clear();
modifier.clear();

// the format for a locale is [language[_territory][.codeset][@modifier]]
std::string tmp = locale;

// look for the modifier after @
size_t pos = tmp.find("@");
if (pos != std::string::npos)
{
modifier = tmp.substr(pos + 1);
tmp = tmp.substr(0, pos);
}

// look for the codeset after .
pos = tmp.find(".");
if (pos != std::string::npos)
{
codeset = tmp.substr(pos + 1);
tmp = tmp.substr(0, pos);
}

// look for the codeset after _
pos = tmp.find("_");
if (pos != std::string::npos)
{
territory = tmp.substr(pos + 1);
StringUtils::ToUpper(territory);
tmp = tmp.substr(0, pos);
}

// what remains is the language
language = tmp;
StringUtils::ToLower(language);

return CheckValidity(language, territory, codeset, modifier);
}

void CLocale::Initialize()
{
m_valid = CheckValidity(m_language, m_territory, m_codeset, m_modifier);
if (m_valid)
{
StringUtils::ToLower(m_language);
StringUtils::ToUpper(m_territory);
}
}
146 changes: 146 additions & 0 deletions xbmc/utils/Locale.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
#pragma once
/*
* Copyright (C) 2015 Team XBMC
* http://xbmc.org
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with XBMC; see the file COPYING. If not, see
* <http://www.gnu.org/licenses/>.
*
*/

#include <string>

/*!
\brief Class representing a full locale of the form [language[_territory][.codeset][@modifier]].
*/
class CLocale
{
public:
CLocale();
CLocale(const std::string& language);
CLocale(const std::string& language, const std::string& territory);
CLocale(const std::string& language, const std::string& territory, const std::string& codeset);
CLocale(const std::string& language, const std::string& territory, const std::string& codeset, const std::string& modifier);
~CLocale();

/*!
\brief Empty (and invalid) CLocale instance.
*/
static const CLocale Empty;

/*!
\brief Parses the given string representation and turns it into a locale.
\param locale String representation of a locale
*/
static CLocale FromString(const std::string& locale);

bool operator==(const CLocale& other) const;
inline bool operator!=(const CLocale& other) const { return !(*this == other); }

/*!
\brief Whether the locale is valid or not.
\details A locale is considered valid if at least the language code is set.
*/
bool IsValid() const { return m_valid; }

/*!
\brief Returns the (lower-case) ISO 639-1 language code of the locale.
*/
const std::string& GetLanguageCode() const { return m_language; }
/*!
\brief Returns the (upper-case) ISO 3166-1 Alpha-2 territory code of the locale.
*/
const std::string& GetTerritoryCode() const { return m_territory; }
/*!
\brief Returns the codeset of the locale.
*/
const std::string& GetCodeset() const { return m_codeset; }
/*!
\brief Returns the modifier of the locale.
*/
const std::string& GetModifier() const { return m_modifier; }

/*!
\brief Returns the full string representation of the locale.
\details The format of the string representation is
[language[_territory][.codeset][@modifier]] where the language is
represented as a (lower-case) two character ISO 639-1 code and the territory
is represented as a (upper-case) two character ISO 3166-1 Alpha-2 code.
*/
std::string ToString() const;
/*!
\brief Returns the full string representation of the locale in lowercase.
\details The format of the string representation is
[language[_territory][.codeset][@modifier]] where the language is
represented as a two character ISO 639-1 code and the territory is
represented as a two character ISO 3166-1 Alpha-2 code.
*/
std::string ToStringLC() const;
/*!
\brief Returns the short string representation of the locale.
\details The format of the short string representation is
[language[_territory] where the language is represented as a (lower-case)
two character ISO 639-1 code and the territory is represented as a
(upper-case) two character ISO 3166-1 Alpha-2 code.
*/
std::string ToShortString() const;
/*!
\brief Returns the short string representation of the locale in lowercase.
\details The format of the short string representation is
[language[_territory] where the language is represented as a two character
ISO 639-1 code and the territory is represented as a two character
ISO 3166-1 Alpha-2 code.
*/
std::string ToShortStringLC() const;

/*!
\brief Checks if the given string representation of a locale exactly matches
the locale.
\param locale String representation of a locale
\return True if the string representation matches the locale, false otherwise.
*/
bool Equals(const std::string& locale) const;

/*!
\brief Checks if the given string representation of a locale partly matches
the locale.
\details Partial matching means that every available locale part needs to
match the same locale part of the other locale if present.
\param locale String representation of a locale
\return True if the string representation matches the locale, false otherwise.
*/
bool Matches(const std::string& locale) const;

private:
static bool CheckValidity(const std::string& language, const std::string& territory, const std::string& codeset, const std::string& modifier);
static bool ParseLocale(const std::string &locale, std::string &language, std::string &territory, std::string &codeset, std::string &modifier);

void Initialize();

bool m_valid;
std::string m_language;
std::string m_territory;
std::string m_codeset;
std::string m_modifier;
};

1 change: 1 addition & 0 deletions xbmc/utils/Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ SRCS += JSONVariantWriter.cpp
SRCS += LabelFormatter.cpp
SRCS += LangCodeExpander.cpp
SRCS += LegacyPathTranslation.cpp
SRCS += Locale.cpp
SRCS += log.cpp
SRCS += md5.cpp
SRCS += Mime.cpp
Expand Down
1 change: 1 addition & 0 deletions xbmc/utils/test/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ SRCS= \
TestJSONVariantWriter.cpp \
TestLabelFormatter.cpp \
TestLangCodeExpander.cpp \
TestLocale.cpp \
Testlog.cpp \
TestMathUtils.cpp \
Testmd5.cpp \
Expand Down
Loading

0 comments on commit 2541675

Please sign in to comment.