Skip to content

Commit 661db39

Browse files
author
Miloslav Metelka
committed
[GR-12895] Proper implementation of the Sys.localeconv.
PullRequest: fastr/1974
2 parents 291d948 + 295b52c commit 661db39

File tree

3 files changed

+93
-5
lines changed

3 files changed

+93
-5
lines changed

com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LocaleFunctions.java

Lines changed: 77 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@
3636
import java.nio.charset.Charset;
3737
import java.text.DecimalFormat;
3838
import java.text.DecimalFormatSymbols;
39+
import java.text.NumberFormat;
40+
import java.util.Currency;
41+
import java.util.Locale;
3942

4043
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
4144
import com.oracle.truffle.api.dsl.Specialization;
@@ -127,10 +130,80 @@ public abstract static class LocaleConv extends RBuiltinNode.Arg0 {
127130
@Specialization
128131
@TruffleBoundary
129132
protected Object localeconv() {
130-
DecimalFormat format = (DecimalFormat) DecimalFormat.getInstance();
131-
DecimalFormatSymbols symbols = format.getDecimalFormatSymbols();
132-
char sep = symbols.getDecimalSeparator();
133-
return RDataFactory.createList(new Object[]{sep}, RDataFactory.createStringVectorFromScalar("decimal_point"));
133+
RLocale.ContextStateImpl stateRLocale = RContext.getInstance().stateRLocale;
134+
Locale numericLocale = stateRLocale.getLocale(RLocale.NUMERIC);
135+
Locale monetaryLocale = stateRLocale.getLocale(RLocale.MONETARY);
136+
NumberFormat numericFormat = NumberFormat.getNumberInstance(numericLocale);
137+
NumberFormat monetaryFormat = NumberFormat.getInstance(monetaryLocale);
138+
DecimalFormatSymbols decimalSymbols = DecimalFormatSymbols.getInstance(numericLocale);
139+
DecimalFormatSymbols monetarySymbols = DecimalFormatSymbols.getInstance(monetaryLocale);
140+
Currency currency = monetarySymbols.getCurrency();
141+
142+
int len = 18;
143+
int i = 0;
144+
String[] values = new String[len];
145+
String[] names = new String[len];
146+
names[i] = "decimal_point";
147+
values[i++] = String.valueOf(decimalSymbols.getDecimalSeparator());
148+
names[i] = "thousands_sep"; // for non-monetary quantities
149+
values[i++] = numericFormat.isGroupingUsed() ? String.valueOf(decimalSymbols.getGroupingSeparator()) : "";
150+
names[i] = "grouping";
151+
StringBuilder grouping = new StringBuilder(2);
152+
if (numericFormat.isGroupingUsed() && (numericFormat instanceof DecimalFormat)) {
153+
int groupingSize = ((DecimalFormat) numericFormat).getGroupingSize();
154+
for (int j = 2; j > 0; j--) {
155+
grouping.append((char) groupingSize);
156+
}
157+
grouping.setLength(0);
158+
}
159+
values[i++] = grouping.toString();
160+
names[i] = "int_curr_symbol";
161+
values[i++] = monetarySymbols.getInternationalCurrencySymbol() + ' '; // Appears
162+
// space-terminated
163+
// in GNU-R
164+
names[i] = "currency_symbol";
165+
values[i++] = monetarySymbols.getCurrencySymbol();
166+
names[i] = "mon_decimal_point";
167+
values[i++] = String.valueOf(monetarySymbols.getMonetaryDecimalSeparator());
168+
names[i] = "mon_thousands_sep";
169+
values[i++] = String.valueOf(monetarySymbols.getGroupingSeparator());
170+
names[i] = "mon_grouping";
171+
if (monetaryFormat.isGroupingUsed() && (monetaryFormat instanceof DecimalFormat)) {
172+
int groupingSize = ((DecimalFormat) monetaryFormat).getGroupingSize();
173+
for (int j = 2; j > 0; j--) {
174+
grouping.append((char) groupingSize);
175+
}
176+
grouping.setLength(0);
177+
}
178+
values[i++] = grouping.toString();
179+
names[i] = "positive_sign";
180+
values[i++] = ""; // TODO not found a corresponding java method yet
181+
names[i] = "negative_sign";
182+
values[i++] = String.valueOf(monetarySymbols.getMinusSign());
183+
names[i] = "int_frac_digits";
184+
values[i++] = String.valueOf(currency.getDefaultFractionDigits());
185+
names[i] = "frac_digits";
186+
values[i++] = String.valueOf(currency.getDefaultFractionDigits());
187+
names[i] = "p_cs_precedes"; // "1" if currency symbol precedes positive value or "0"
188+
// otherwise
189+
values[i++] = "1"; // No corresponding java method found yet - best match found:
190+
// (DecimalFormat.getPositivePrefix() != null)
191+
names[i] = "p_sep_by_space"; // "1" if a space separates currency symbol from a positive
192+
// value or "0" otherwise
193+
values[i++] = "0"; // No corresponding java method found yet
194+
names[i] = "n_cs_precedes"; // "1" if currency symbol precedes negative value or "0"
195+
// otherwise
196+
values[i++] = "1"; // No corresponding java method found yet
197+
names[i] = "n_sep_by_space"; // "1" if a space separates currency symbol from a negative
198+
// value or "0" otherwise
199+
values[i++] = "0"; // No corresponding java method found yet
200+
names[i] = "p_sign_posn"; // value indicating the positioning of the positive sign for a
201+
// non-negative internationally formatted monetary quantity
202+
values[i++] = "1"; // No corresponding java method found yet
203+
names[i] = "n_sign_posn"; // value indicating the positioning of the negative sign for a
204+
// negative internationally formatted monetary quantity
205+
values[i++] = "1"; // No corresponding java method found yet
206+
return RDataFactory.createStringVector(values, true, RDataFactory.createStringVector(names, true));
134207
}
135208
}
136209

com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1915,6 +1915,15 @@ character(0)
19151915
##com.oracle.truffle.r.test.builtins.TestBuiltin_Syssetenv.testSyssetenv5#Ignored.SideEffects#
19161916
#argv <- structure(list(TZ = 'EST5EDT'), .Names = 'TZ');do.call('Sys.setenv', argv)
19171917

1918+
##com.oracle.truffle.r.test.builtins.TestBuiltin_Syssetlocale.testSyslocaleconv#
1919+
#names(Sys.localeconv())
1920+
[1] "decimal_point" "thousands_sep" "grouping"
1921+
[4] "int_curr_symbol" "currency_symbol" "mon_decimal_point"
1922+
[7] "mon_thousands_sep" "mon_grouping" "positive_sign"
1923+
[10] "negative_sign" "int_frac_digits" "frac_digits"
1924+
[13] "p_cs_precedes" "p_sep_by_space" "n_cs_precedes"
1925+
[16] "n_sep_by_space" "p_sign_posn" "n_sign_posn"
1926+
19181927
##com.oracle.truffle.r.test.builtins.TestBuiltin_Syssetlocale.testSyssetlocale1#
19191928
#argv <- list(3L, 'C'); Sys.setlocale(argv[[1]], argv[[2]])
19201929
Error in Sys.setlocale(argv[[1]], argv[[2]]) :

com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Syssetlocale.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
1515
*
1616
* Copyright (c) 2014, Purdue University
17-
* Copyright (c) 2014, 2018, Oracle and/or its affiliates
17+
* Copyright (c) 2014, 2019, Oracle and/or its affiliates
1818
*
1919
* All rights reserved.
2020
*/
@@ -45,4 +45,10 @@ public void testSyssetlocaleInvalidArgs() {
4545
assertEval("Sys.setlocale(4, 42)");
4646
assertEval("Sys.setlocale('3L', 'C')");
4747
}
48+
49+
@Test
50+
public void testSyslocaleconv() {
51+
assertEval("names(Sys.localeconv())");
52+
}
53+
4854
}

0 commit comments

Comments
 (0)