Skip to content

Commit 297cafe

Browse files
committed
[MERGE #5264 @msdimitrov] Implement JavascriptArray::GetLocaleSeparator for Linux/macOS.
Merge pull request #5264 from msdimitrov:locale-separator Implement JavascriptArray::GetLocaleSeparator for Linux/macOS. Refactor JavascriptArray::GetLocaleSeparator into new module PlatformAgnostic::Arrays
2 parents e0a2a58 + 4f7b50c commit 297cafe

File tree

8 files changed

+172
-36
lines changed

8 files changed

+172
-36
lines changed

lib/Common/CommonPal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -744,6 +744,7 @@ namespace PlatformAgnostic
744744

745745
#include "PlatformAgnostic/DateTime.h"
746746
#include "PlatformAgnostic/Numbers.h"
747+
#include "PlatformAgnostic/Arrays.h"
747748
#include "PlatformAgnostic/SystemInfo.h"
748749
#include "PlatformAgnostic/Thread.h"
749750
#include "PlatformAgnostic/AssemblyCommon.h"

lib/Common/PlatformAgnostic/Arrays.h

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//-------------------------------------------------------------------------------------------------------
2+
// Copyright (C) Microsoft. All rights reserved.
3+
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
4+
//-------------------------------------------------------------------------------------------------------
5+
#pragma once
6+
7+
namespace PlatformAgnostic
8+
{
9+
namespace Arrays
10+
{
11+
#ifndef ENABLE_GLOBALIZATION
12+
13+
class ArrayLocalization
14+
{
15+
char16 localeSeparator;
16+
17+
static const uint16 BufSize = 256;
18+
19+
public:
20+
21+
ArrayLocalization();
22+
23+
inline char16 GetLocaleSeparator() { return localeSeparator; }
24+
};
25+
26+
#endif
27+
28+
static const uint32 SeparatorBufferSize = 6;
29+
30+
// According to MSDN the maximum number of characters for the list separator (LOCALE_SLIST) is four, including a terminating null character.
31+
bool GetLocaleSeparator(char16* szSeparator, uint32* sepOutLength, uint32 sepBufferSize);
32+
33+
template <uint32 sepBufferSize>
34+
inline bool GetLocaleSeparator(char16(&szSepatator)[sepBufferSize], uint32 *sepOutLength)
35+
{
36+
return GetLocaleSeparator(szSeparator, sepOutLength, sepBufferSize);
37+
}
38+
39+
} // namespace Arrays
40+
} // namespace PlatformAgnostic

lib/Runtime/Library/JavascriptArray.cpp

Lines changed: 15 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -8246,37 +8246,6 @@ using namespace Js;
82468246
}
82478247
#endif
82488248

8249-
JavascriptString* JavascriptArray::GetLocaleSeparator(ScriptContext* scriptContext)
8250-
{
8251-
#ifdef ENABLE_GLOBALIZATION
8252-
LCID lcid = GetUserDefaultLCID();
8253-
int count = 0;
8254-
char16 szSeparator[6];
8255-
8256-
// According to the document for GetLocaleInfo this is a sufficient buffer size.
8257-
count = GetLocaleInfoW(lcid, LOCALE_SLIST, szSeparator, 5);
8258-
if( !count)
8259-
{
8260-
AssertMsg(FALSE, "GetLocaleInfo failed");
8261-
return scriptContext->GetLibrary()->GetCommaSpaceDisplayString();
8262-
}
8263-
else
8264-
{
8265-
// Append ' ' if necessary
8266-
if( count < 2 || szSeparator[count-2] != ' ')
8267-
{
8268-
szSeparator[count-1] = ' ';
8269-
szSeparator[count] = '\0';
8270-
}
8271-
8272-
return JavascriptString::NewCopyBuffer(szSeparator, count, scriptContext);
8273-
}
8274-
#else
8275-
// xplat-todo: Support locale-specific separator
8276-
return scriptContext->GetLibrary()->GetCommaSpaceDisplayString();
8277-
#endif
8278-
}
8279-
82808249
template <typename T>
82818250
JavascriptString* JavascriptArray::ToLocaleString(T* arr, ScriptContext* scriptContext)
82828251
{
@@ -8318,7 +8287,21 @@ using namespace Js;
83188287

83198288
if (length > 1)
83208289
{
8321-
JavascriptString* separator = GetLocaleSeparator(scriptContext);
8290+
uint32 sepSize = 0;
8291+
char16 szSeparator[Arrays::SeparatorBufferSize];
8292+
8293+
bool hasLocaleSeparator = Arrays::GetLocaleSeparator(szSeparator, &sepSize, Arrays::SeparatorBufferSize);
8294+
8295+
JavascriptString* separator = nullptr;
8296+
8297+
if (hasLocaleSeparator)
8298+
{
8299+
separator = JavascriptString::NewCopyBuffer(szSeparator, static_cast<charcount_t>(sepSize), scriptContext);
8300+
}
8301+
else
8302+
{
8303+
separator = scriptContext->GetLibrary()->GetCommaSpaceDisplayString();
8304+
}
83228305

83238306
for (uint32 i = 1; i < length; i++)
83248307
{

lib/Runtime/Library/JavascriptArray.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -892,7 +892,6 @@ namespace Js
892892

893893
template <typename T>
894894
static JavascriptString* ToLocaleString(T* obj, ScriptContext* scriptContext);
895-
static JavascriptString* GetLocaleSeparator(ScriptContext* scriptContext);
896895

897896
public:
898897
static uint32 GetOffsetOfArrayFlags() { return offsetof(JavascriptArray, arrayFlags); }

lib/Runtime/PlatformAgnostic/Chakra.Runtime.PlatformAgnostic.vcxproj

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<?xml version="1.0" encoding="utf-8"?>
1+
<?xml version="1.0" encoding="utf-8"?>
22
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
33
<Import Condition="'$(ChakraBuildPathImported)'!='true'" Project="$(SolutionDir)Chakra.Build.Paths.props" />
44
<Import Project="$(BuildConfigPropsPath)Chakra.Build.ProjectConfiguration.props" />
@@ -44,8 +44,9 @@
4444
<ClCompile Include="$(MSBuildThisFileDirectory)Platform\Windows\DateTime.cpp" />
4545
<ClCompile Include="$(MSBuildThisFileDirectory)Platform\Windows\DaylightHelper.cpp" />
4646
<ClCompile Include="$(MSBuildThisFileDirectory)Platform\Windows\HiResTimer.cpp" />
47-
<ClCompile Include="$(MSBuildThisFileDirectory)Platform\Windows\UnicodeText.cpp"/>
47+
<ClCompile Include="$(MSBuildThisFileDirectory)Platform\Windows\UnicodeText.cpp" />
4848
<ClCompile Include="$(MSBuildThisFileDirectory)Platform\Windows\NumbersUtility.cpp" />
49+
<ClCompile Include="$(MSBuildThisFileDirectory)Platform\Windows\ArraysUtility.cpp" />
4950
<ClCompile Include="$(MSBuildThisFileDirectory)Platform\Windows\SystemInfo.cpp" />
5051
<ClCompile Include="$(MSBuildThisFileDirectory)Platform\Windows\Thread.cpp" />
5152
<ClCompile Include="$(MSBuildThisFileDirectory)Platform\Windows\PerfTrace.cpp" />
@@ -67,4 +68,4 @@
6768
</ItemGroup>
6869
<Import Project="$(BuildConfigPropsPath)Chakra.Build.targets" Condition="exists('$(BuildConfigPropsPath)Chakra.Build.targets')" />
6970
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
70-
</Project>
71+
</Project>

lib/Runtime/PlatformAgnostic/Platform/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ set(PL_SOURCE_FILES
55
Common/HiResTimer.cpp
66
Common/DateTime.cpp
77
Linux/NumbersUtility.cpp
8+
POSIX/ArraysUtility.cpp
89
Common/Thread.cpp
910
Common/Trace.cpp
1011
Common/SystemInfo.Common.cpp
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
//-------------------------------------------------------------------------------------------------------
2+
// Copyright (C) Microsoft. All rights reserved.
3+
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
4+
//-------------------------------------------------------------------------------------------------------
5+
6+
#include "Common.h"
7+
#include "ChakraPlatform.h"
8+
#include <locale.h>
9+
10+
namespace PlatformAgnostic
11+
{
12+
namespace Arrays
13+
{
14+
15+
static char16 commaSeparator = _u(',');
16+
static char16 semicolonSeparator = _u(';');
17+
18+
ArrayLocalization::ArrayLocalization()
19+
{
20+
char buffer[BufSize];
21+
char *old_locale = setlocale(LC_NUMERIC, NULL);
22+
23+
if (old_locale != NULL)
24+
{
25+
memcpy(buffer, old_locale, BufSize);
26+
27+
setlocale(LC_NUMERIC, "");
28+
}
29+
30+
struct lconv *locale_format = localeconv();
31+
if (locale_format != NULL)
32+
{
33+
// No specific list separator on Linux/macOS
34+
// Use this pattern to determine the list separator
35+
if (*locale_format->decimal_point == commaSeparator)
36+
{
37+
localeSeparator = semicolonSeparator;
38+
}
39+
else
40+
{
41+
localeSeparator = commaSeparator;
42+
}
43+
}
44+
45+
if (old_locale != NULL)
46+
{
47+
setlocale(LC_NUMERIC, buffer);
48+
}
49+
}
50+
51+
bool GetLocaleSeparator(char16* szSeparator, uint32* sepOutSize, uint32 sepBufSize)
52+
{
53+
ArrayLocalization arrayLocalization;
54+
//Append ' ' after separator
55+
szSeparator[*sepOutSize] = arrayLocalization.GetLocaleSeparator();
56+
szSeparator[++(*sepOutSize)] = ' ';
57+
szSeparator[++(*sepOutSize)] = '\0';
58+
59+
return true;
60+
}
61+
62+
} // namespace Arrays
63+
} // namespace PlatformAgnostic
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
//-------------------------------------------------------------------------------------------------------
2+
// Copyright (C) Microsoft. All rights reserved.
3+
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
4+
//-------------------------------------------------------------------------------------------------------
5+
6+
#include "RuntimePlatformAgnosticPch.h"
7+
#include "Common.h"
8+
#include "ChakraPlatform.h"
9+
10+
namespace PlatformAgnostic
11+
{
12+
namespace Arrays
13+
{
14+
// Potential candidate for optimization
15+
bool GetLocaleSeparator(char16* szSeparator, uint32* sepOutSize, uint32 sepBufSize)
16+
{
17+
char16 localeName[LOCALE_NAME_MAX_LENGTH] = { 0 };
18+
19+
int ret = GetUserDefaultLocaleName(localeName, _countof(localeName));
20+
21+
if (ret == 0)
22+
{
23+
AssertMsg(FALSE, "GetUserDefaultLocaleName failed");
24+
return false;
25+
}
26+
27+
*sepOutSize = GetLocaleInfoEx(localeName, LOCALE_SLIST, szSeparator, sepBufSize);
28+
29+
if (*sepOutSize == 0)
30+
{
31+
AssertMsg(FALSE, "GetLocaleInfo failed");
32+
return false;
33+
}
34+
else
35+
{
36+
// Append ' ' if necessary
37+
if (*sepOutSize < 2 || szSeparator[*sepOutSize - 2] != ' ')
38+
{
39+
szSeparator[*sepOutSize - 1] = ' ';
40+
szSeparator[*sepOutSize] = '\0';
41+
}
42+
}
43+
44+
return true;
45+
}
46+
47+
} // namespace Arrays
48+
} // namespace PlatformAgnostic

0 commit comments

Comments
 (0)