76 changes: 76 additions & 0 deletions libc/src/locale/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
add_object_library(
locale
SRCS
locale.cpp
HDRS
locale.h
DEPENDS
libc.include.locale
)

add_entrypoint_object(
localeconv
SRCS
localeconv.cpp
HDRS
localeconv.h
DEPENDS
libc.include.locale
CXX_STANDARD
20 # For designated initializers
)

add_entrypoint_object(
newlocale
SRCS
newlocale.cpp
HDRS
newlocale.h
DEPENDS
libc.include.locale
.locale
)

add_entrypoint_object(
duplocale
SRCS
duplocale.cpp
HDRS
duplocale.h
DEPENDS
libc.include.locale
.locale
)

add_entrypoint_object(
setlocale
SRCS
setlocale.cpp
HDRS
setlocale.h
DEPENDS
libc.include.locale
.locale
)

add_entrypoint_object(
uselocale
SRCS
uselocale.cpp
HDRS
uselocale.h
DEPENDS
libc.include.locale
.locale
)

add_entrypoint_object(
freelocale
SRCS
freelocale.cpp
HDRS
freelocale.h
DEPENDS
libc.include.locale
.locale
)
21 changes: 21 additions & 0 deletions libc/src/locale/duplocale.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//===-- Implementation of duplocale ---------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "src/locale/duplocale.h"
#include "include/llvm-libc-macros/locale-macros.h"
#include "src/locale/locale.h"

#include "src/__support/CPP/string_view.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"

namespace LIBC_NAMESPACE_DECL {

LLVM_LIBC_FUNCTION(locale_t, duplocale, (locale_t loc)) { return loc; }

} // namespace LIBC_NAMESPACE_DECL
22 changes: 22 additions & 0 deletions libc/src/locale/duplocale.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//===-- Implementation header for duplocale ---------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIBC_SRC_LOCALE_DUPLOCALE_H
#define LLVM_LIBC_SRC_LOCALE_DUPLOCALE_H

#include "src/__support/macros/config.h"

#include "hdr/types/locale_t.h"

namespace LIBC_NAMESPACE_DECL {

locale_t duplocale(locale_t loc);

} // namespace LIBC_NAMESPACE_DECL

#endif // LLVM_LIBC_SRC_LOCALE_DUPLOCALE_H
21 changes: 21 additions & 0 deletions libc/src/locale/freelocale.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//===-- Implementation of freelocale --------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "src/locale/freelocale.h"
#include "include/llvm-libc-macros/locale-macros.h"
#include "src/locale/locale.h"

#include "src/__support/CPP/string_view.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"

namespace LIBC_NAMESPACE_DECL {

LLVM_LIBC_FUNCTION(void, freelocale, (locale_t)) {}

} // namespace LIBC_NAMESPACE_DECL
22 changes: 22 additions & 0 deletions libc/src/locale/freelocale.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//===-- Implementation header for freelocale --------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIBC_SRC_LOCALE_FREELOCALE_H
#define LLVM_LIBC_SRC_LOCALE_FREELOCALE_H

#include "src/__support/macros/config.h"

#include "hdr/types/locale_t.h"

namespace LIBC_NAMESPACE_DECL {

void freelocale(locale_t loc);

} // namespace LIBC_NAMESPACE_DECL

#endif // LLVM_LIBC_SRC_LOCALE_FREELOCALE_H
21 changes: 21 additions & 0 deletions libc/src/locale/locale.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//===-- Implementation of locale ------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "src/locale/locale.h"

#include "include/llvm-libc-macros/locale-macros.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"

namespace LIBC_NAMESPACE_DECL {

__locale_t c_locale = {nullptr};

locale_t locale = nullptr;

} // namespace LIBC_NAMESPACE_DECL
36 changes: 36 additions & 0 deletions libc/src/locale/locale.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//===-- Implementation header for the locale --------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIBC_SRC_LOCALE_LOCALECONV_H
#define LLVM_LIBC_SRC_LOCALE_LOCALECONV_H

#include "src/__support/macros/attributes.h"
#include "src/__support/macros/config.h"

#include "hdr/types/locale_t.h"

#include <stddef.h>

namespace LIBC_NAMESPACE_DECL {

// We only support the "C" locale right now.
static constexpr size_t MAX_LOCALE_NAME_SIZE = 2;

struct __locale_data {
char name[MAX_LOCALE_NAME_SIZE];
};

// The pointer to the default "C" locale.
extern __locale_t c_locale;

// The global locale instance.
LIBC_THREAD_LOCAL extern locale_t locale;

} // namespace LIBC_NAMESPACE_DECL

#endif // LLVM_LIBC_SRC_LOCALE_LOCALECONV_H
49 changes: 49 additions & 0 deletions libc/src/locale/localeconv.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
//===-- Implementation of localeconv --------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "src/locale/localeconv.h"

#include "src/__support/CPP/limits.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"

namespace LIBC_NAMESPACE_DECL {

static char DOT_STRING[] = ".";
static char EMPTY_STRING[] = "";

static struct lconv C_LCONV = {
.decimal_point = DOT_STRING,
.thousands_sep = EMPTY_STRING,
.grouping = EMPTY_STRING,
.mon_decimal_point = EMPTY_STRING,
.mon_thousands_sep = EMPTY_STRING,
.mon_grouping = EMPTY_STRING,
.positive_sign = EMPTY_STRING,
.negative_sign = EMPTY_STRING,
.currency_symbol = EMPTY_STRING,
.frac_digits = CHAR_MAX,
.p_cs_precedes = CHAR_MAX,
.n_cs_precedes = CHAR_MAX,
.p_sep_by_space = CHAR_MAX,
.n_sep_by_space = CHAR_MAX,
.p_sign_posn = CHAR_MAX,
.n_sign_posn = CHAR_MAX,
.int_curr_symbol = EMPTY_STRING,
.int_frac_digits = CHAR_MAX,
.int_p_cs_precedes = CHAR_MAX,
.int_n_cs_precedes = CHAR_MAX,
.int_p_sep_by_space = CHAR_MAX,
.int_n_sep_by_space = CHAR_MAX,
.int_p_sign_posn = CHAR_MAX,
.int_n_sign_posn = CHAR_MAX,
};

LLVM_LIBC_FUNCTION(struct lconv *, localeconv, ()) { return &C_LCONV; }

} // namespace LIBC_NAMESPACE_DECL
22 changes: 22 additions & 0 deletions libc/src/locale/localeconv.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//===-- Implementation header for localeconv --------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIBC_SRC_LOCALE_LOCALECONV_H
#define LLVM_LIBC_SRC_LOCALE_LOCALECONV_H

#include "src/__support/macros/config.h"

#include "include/llvm-libc-types/struct_lconv.h"

namespace LIBC_NAMESPACE_DECL {

struct lconv *localeconv();

} // namespace LIBC_NAMESPACE_DECL

#endif // LLVM_LIBC_SRC_LOCALE_LOCALECONV_H
28 changes: 28 additions & 0 deletions libc/src/locale/newlocale.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//===-- Implementation of newlocale ---------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "src/locale/newlocale.h"
#include "include/llvm-libc-macros/locale-macros.h"
#include "src/locale/locale.h"

#include "src/__support/CPP/string_view.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"

namespace LIBC_NAMESPACE_DECL {

LLVM_LIBC_FUNCTION(locale_t, newlocale,
(int category_mask, const char *locale_name, locale_t)) {
cpp::string_view name(locale_name);
if (category_mask > LC_ALL || (!name.empty() && name != "C"))
return nullptr;

return &c_locale;
}

} // namespace LIBC_NAMESPACE_DECL
22 changes: 22 additions & 0 deletions libc/src/locale/newlocale.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//===-- Implementation header for setlocale ---------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIBC_SRC_LOCALE_SETLOCALE_H
#define LLVM_LIBC_SRC_LOCALE_SETLOCALE_H

#include "src/__support/macros/config.h"

#include "hdr/types/locale_t.h"

namespace LIBC_NAMESPACE_DECL {

locale_t newlocale(int category_mask, const char *locale_name, locale_t base);

} // namespace LIBC_NAMESPACE_DECL

#endif // LLVM_LIBC_SRC_LOCALE_SETLOCALE_H
28 changes: 28 additions & 0 deletions libc/src/locale/setlocale.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//===-- Implementation of setlocale ---------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "src/locale/setlocale.h"
#include "include/llvm-libc-macros/locale-macros.h"
#include "src/locale/locale.h"

#include "src/__support/CPP/string_view.h"
#include "src/__support/common.h"
#include "src/__support/macros/config.h"

namespace LIBC_NAMESPACE_DECL {

LLVM_LIBC_FUNCTION(char *, setlocale, (int category, const char *locale_name)) {
cpp::string_view name(locale_name);
if (category > LC_ALL || (!name.empty() && name != "C"))
return nullptr;

static char locale_str[] = "C";
return locale_str;
}

} // namespace LIBC_NAMESPACE_DECL
22 changes: 22 additions & 0 deletions libc/src/locale/setlocale.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//===-- Implementation header for setlocale ---------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIBC_SRC_LOCALE_SETLOCALE_H
#define LLVM_LIBC_SRC_LOCALE_SETLOCALE_H

#include "src/__support/macros/config.h"

#include "hdr/types/locale_t.h"

namespace LIBC_NAMESPACE_DECL {

char *setlocale(int category, const char *locale_name);

} // namespace LIBC_NAMESPACE_DECL

#endif // LLVM_LIBC_SRC_LOCALE_SETLOCALE_H
23 changes: 23 additions & 0 deletions libc/src/locale/uselocale.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//===-- Implementation of uselocale ---------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "src/locale/uselocale.h"
#include "src/locale/locale.h"

#include "src/__support/common.h"
#include "src/__support/macros/config.h"

namespace LIBC_NAMESPACE_DECL {

LLVM_LIBC_FUNCTION(locale_t, uselocale, (locale_t newloc)) {
if (!newloc)
return locale;
return locale = newloc;
}

} // namespace LIBC_NAMESPACE_DECL
22 changes: 22 additions & 0 deletions libc/src/locale/uselocale.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//===-- Implementation header for uselocale ---------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIBC_SRC_LOCALE_USELOCALE_H
#define LLVM_LIBC_SRC_LOCALE_USELOCALE_H

#include "src/__support/macros/config.h"

#include "hdr/types/locale_t.h"

namespace LIBC_NAMESPACE_DECL {

locale_t uselocale(locale_t newloc);

} // namespace LIBC_NAMESPACE_DECL

#endif // LLVM_LIBC_SRC_LOCALE_USELOCALE_H
1 change: 1 addition & 0 deletions libc/test/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ add_subdirectory(setjmp)
add_subdirectory(signal)
add_subdirectory(spawn)
add_subdirectory(time)
add_subdirectory(locale)

if(${LIBC_TARGET_OS} STREQUAL "linux")
add_subdirectory(pthread)
Expand Down
25 changes: 25 additions & 0 deletions libc/test/src/locale/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
add_custom_target(libc-locale-tests)

add_libc_test(
locale_test
SUITE
libc-locale-tests
SRCS
locale_test.cpp
DEPENDS
libc.include.locale
libc.src.locale.newlocale
libc.src.locale.uselocale
libc.src.locale.freelocale
)

add_libc_test(
localeconv_test
SUITE
libc-locale-tests
SRCS
localeconv_test.cpp
DEPENDS
libc.include.locale
libc.src.locale.localeconv
)
27 changes: 27 additions & 0 deletions libc/test/src/locale/locale_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//===-- Unittests for locale ----------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "src/locale/freelocale.h"
#include "src/locale/newlocale.h"
#include "src/locale/uselocale.h"

#include "test/UnitTest/Test.h"

#include "include/llvm-libc-macros/locale-macros.h"

TEST(LlvmLibcLocale, DefaultLocale) {
locale_t new_locale = LIBC_NAMESPACE::newlocale(LC_ALL, "C", nullptr);
EXPECT_NE(new_locale, static_cast<locale_t>(nullptr));

locale_t old_locale = LIBC_NAMESPACE::uselocale(new_locale);
EXPECT_NE(old_locale, static_cast<locale_t>(nullptr));

LIBC_NAMESPACE::freelocale(new_locale);

LIBC_NAMESPACE::uselocale(old_locale);
}
17 changes: 17 additions & 0 deletions libc/test/src/locale/localeconv_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//===-- Unittests for localeconv ------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "include/llvm-libc-macros/locale-macros.h"
#include "src/locale/localeconv.h"

#include "test/UnitTest/Test.h"

TEST(LlvmLibcLocale, DefaultLocale) {
struct lconv *conv = LIBC_NAMESPACE::localeconv();
EXPECT_STREQ(conv->decimal_point, ".");
}