You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@freemarker.apache.org by dd...@apache.org on 2022/12/30 23:26:35 UTC

[freemarker] branch 2.3-gae updated (14f651f5 -> 9e14cb0b)

This is an automated email from the ASF dual-hosted git repository.

ddekany pushed a change to branch 2.3-gae
in repository https://gitbox.apache.org/repos/asf/freemarker.git


    from 14f651f5 Further javadoc fixes/improvements related to CFormat-s/?c/?cn.
     new 21022a6c CFormat: Further API and javadoc cleanup
     new 9e14cb0b CFormat: Replace two Default23*CFormat classes with a single LegacyCFormat.

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../freemarker/core/AbstractJSONLikeFormat.java    |   9 +-
 .../freemarker/core/AbstractLegacyCFormat.java     | 108 -------------
 src/main/java/freemarker/core/CFormat.java         |  13 +-
 src/main/java/freemarker/core/Configurable.java    |  18 ++-
 .../java/freemarker/core/Default230CFormat.java    |  73 ---------
 .../java/freemarker/core/Default2321CFormat.java   |  72 ---------
 src/main/java/freemarker/core/Environment.java     |  27 ++--
 src/main/java/freemarker/core/JSONCFormat.java     |   2 +-
 src/main/java/freemarker/core/JavaCFormat.java     |   8 +-
 .../java/freemarker/core/JavaScriptCFormat.java    |   2 +-
 .../freemarker/core/JavaScriptOrJSONCFormat.java   |   2 +-
 src/main/java/freemarker/core/LegacyCFormat.java   | 173 +++++++++++++++++++++
 src/main/java/freemarker/core/XSCFormat.java       |   9 +-
 .../java/freemarker/core/_StandardCLanguages.java  |   3 +-
 .../java/freemarker/template/Configuration.java    |  28 ++--
 src/manual/en_US/book.xml                          |  88 +++++------
 .../freemarker/core/CTemplateNumberFormatTest.java |   2 +-
 src/test/java/freemarker/core/CustomCFormat.java   |   8 +-
 .../freemarker/template/ConfigurationTest.java     |  21 ++-
 19 files changed, 295 insertions(+), 371 deletions(-)
 delete mode 100644 src/main/java/freemarker/core/AbstractLegacyCFormat.java
 delete mode 100644 src/main/java/freemarker/core/Default230CFormat.java
 delete mode 100644 src/main/java/freemarker/core/Default2321CFormat.java
 create mode 100644 src/main/java/freemarker/core/LegacyCFormat.java


[freemarker] 02/02: CFormat: Replace two Default23*CFormat classes with a single LegacyCFormat.

Posted by dd...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ddekany pushed a commit to branch 2.3-gae
in repository https://gitbox.apache.org/repos/asf/freemarker.git

commit 9e14cb0b55bd2ae266af0b6a702e9f8ef50eb6f8
Author: ddekany <dd...@apache.org>
AuthorDate: Fri Dec 30 23:47:52 2022 +0100

    CFormat: Replace two Default23*CFormat classes with a single LegacyCFormat.
---
 .../freemarker/core/AbstractJSONLikeFormat.java    |   3 +-
 .../freemarker/core/AbstractLegacyCFormat.java     | 104 -------------
 src/main/java/freemarker/core/Configurable.java    |   5 +-
 .../java/freemarker/core/Default230CFormat.java    |  73 ---------
 .../java/freemarker/core/Default2321CFormat.java   |  72 ---------
 src/main/java/freemarker/core/Environment.java     |  25 +--
 src/main/java/freemarker/core/JavaCFormat.java     |   4 +-
 src/main/java/freemarker/core/LegacyCFormat.java   | 173 +++++++++++++++++++++
 src/main/java/freemarker/core/XSCFormat.java       |   3 +-
 .../java/freemarker/core/_StandardCLanguages.java  |   3 +-
 .../java/freemarker/template/Configuration.java    |  16 +-
 src/manual/en_US/book.xml                          |  80 +++++-----
 src/test/java/freemarker/core/CustomCFormat.java   |   4 +-
 .../freemarker/template/ConfigurationTest.java     |  21 ++-
 14 files changed, 253 insertions(+), 333 deletions(-)

diff --git a/src/main/java/freemarker/core/AbstractJSONLikeFormat.java b/src/main/java/freemarker/core/AbstractJSONLikeFormat.java
index ad6b7349..7f305ff4 100644
--- a/src/main/java/freemarker/core/AbstractJSONLikeFormat.java
+++ b/src/main/java/freemarker/core/AbstractJSONLikeFormat.java
@@ -37,7 +37,8 @@ public abstract class AbstractJSONLikeFormat extends CFormat {
             "Infinity", "-Infinity", "NaN",
             "Infinity", "-Infinity", "NaN");
 
-    private static final DecimalFormat LEGACY_NUMBER_FORMAT_PROTOTYPE = (DecimalFormat) Default230CFormat.LEGACY_NUMBER_FORMAT_PROTOTYPE.clone();
+    private static final DecimalFormat LEGACY_NUMBER_FORMAT_PROTOTYPE
+            = (DecimalFormat) LegacyCFormat.LEGACY_NUMBER_FORMAT_PROTOTYPE_2_3_0.clone();
     static {
         DecimalFormatSymbols symbols = LEGACY_NUMBER_FORMAT_PROTOTYPE.getDecimalFormatSymbols();
         symbols.setInfinity("Infinity");
diff --git a/src/main/java/freemarker/core/AbstractLegacyCFormat.java b/src/main/java/freemarker/core/AbstractLegacyCFormat.java
deleted file mode 100644
index c564d144..00000000
--- a/src/main/java/freemarker/core/AbstractLegacyCFormat.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package freemarker.core;
-
-import freemarker.template.TemplateException;
-import freemarker.template.TemplateModelException;
-import freemarker.template.TemplateNumberModel;
-import freemarker.template.utility.StringUtil;
-import freemarker.template.utility.StringUtil.JsStringEncCompatibility;
-import freemarker.template.utility.StringUtil.JsStringEncQuotation;
-
-/**
- * Super class of {@link CFormat}-s that merely exist to mimic old {@code ?c} behavior for backward compatibility.
- *
- * <p><b>Experimental class!</b> This class is too new, and might will change over time. Therefore, for now
- * constructor and most methods are not exposed outside FreeMarker, and so you can't create a custom implementation.
- * The class itself and some members are exposed as they are needed for configuring FreeMarker.
- *
- * @since 2.3.32
- * @see AbstractJSONLikeFormat
- */
-public abstract class AbstractLegacyCFormat extends CFormat {
-    // Visibility is not "protected" to avoid external implementations while this class is experimental.
-    AbstractLegacyCFormat() {
-    }
-
-    @Override
-    final String formatString(String s, Environment env) throws TemplateException {
-        return StringUtil.jsStringEnc(
-                s, JsStringEncCompatibility.JAVA_SCRIPT_OR_JSON, JsStringEncQuotation.QUOTATION_MARK);
-    }
-
-    @Override
-    final TemplateNumberFormat getTemplateNumberFormat(Environment env) {
-        return new LegacyCTemplateNumberFormat(env);
-    }
-
-    @Override
-    String getTrueString() {
-        return "true";
-    }
-
-    @Override
-    String getFalseString() {
-        return "false";
-    }
-
-    @Override
-    final String getNullString() {
-        return "null";
-    }
-
-    final class LegacyCTemplateNumberFormat extends JavaTemplateNumberFormat {
-
-        public LegacyCTemplateNumberFormat(Environment env) {
-            super(getLegacyNumberFormat(env), Environment.COMPUTER_FORMAT_STRING);
-        }
-
-        @Override
-        public String formatToPlainText(TemplateNumberModel numberModel) throws UnformattableValueException,
-                TemplateModelException {
-            Number number = TemplateFormatUtil.getNonNullNumber(numberModel);
-            return format(number);
-        }
-
-        @Override
-        public boolean isLocaleBound() {
-            return false;
-        }
-
-        @Override
-        String format(Number number) throws UnformattableValueException {
-            if (number instanceof Integer || number instanceof Long) {
-                // Accelerate these fairly common cases
-                return number.toString();
-            }
-            return super.format(number);
-        }
-
-        @Override
-        public String getDescription() {
-            return "LegacyC(" + super.getDescription() + ")";
-        }
-
-    }
-
-}
diff --git a/src/main/java/freemarker/core/Configurable.java b/src/main/java/freemarker/core/Configurable.java
index bb6ef998..0e03b220 100644
--- a/src/main/java/freemarker/core/Configurable.java
+++ b/src/main/java/freemarker/core/Configurable.java
@@ -702,8 +702,7 @@ public class Configurable {
      * {@code "c"} {@link #setBooleanFormat(String) boolean_format}.
      *
      * <p>The default value depends on {@link Configuration#Configuration(Version) incompatible_improvements}.
-     * If that's 2.3.32 or higher, then it's {@code "JavaScript or JSON"}. For lower it's {@code "default 2.3.31"} or
-     * {@code "default 2.3.0"}.
+     * If that's 2.3.32 or higher, then it's {@code "JavaScript or JSON"}, otherwise it's {@code "legacy"}.
      *
      * @since 2.3.32
      */
@@ -2196,7 +2195,7 @@ public class Configurable {
      *       <br>String value: {@code "default"} (case insensitive) for the default (on {@link Configuration} only), or
      *       one of the predefined values {@code "JavaScript or JSON"}, {@code "JSON"},
      *       {@code "JavaScript"}, {@code "Java"}, {@code "XS"},
-     *       {@code "default 2.3.0"}, {@code "default 2.3.21"}, or
+     *       {@code "legacy"}, or
      *       {@code "default"} (only allowed for {@link Configuration} instances) for the default value,
      *       or an <a href="#fm_obe">object builder expression</a> that gives a {@link CFormat} object.
      *
diff --git a/src/main/java/freemarker/core/Default230CFormat.java b/src/main/java/freemarker/core/Default230CFormat.java
deleted file mode 100644
index 88749766..00000000
--- a/src/main/java/freemarker/core/Default230CFormat.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package freemarker.core;
-
-import java.text.DecimalFormat;
-import java.text.DecimalFormatSymbols;
-import java.text.NumberFormat;
-import java.util.Locale;
-
-import freemarker.template.Configuration;
-import freemarker.template.Version;
-
-/**
- * Corresponds to the behavior of {@code ?c} if
- * {@link Configuration#Configuration(Version) incompatible_improvements} is less than
- * {@linkplain Configuration#VERSION_2_3_21 2.3.21}.
- * The only good reason for using this is strict backward-compatibility.
- *
- * <p><b>Experimental class!</b> This class is too new, and might will change over time. Therefore, for now
- * constructor and most methods are not exposed outside FreeMarker, and so you can't create a custom implementation.
- * The class itself and some members are exposed as they are needed for configuring FreeMarker.
- *
- * @see Default2321CFormat
- * @see JSONCFormat
- *
- * @since 2.3.32
- */
-public final class Default230CFormat extends AbstractLegacyCFormat {
-    public static final Default230CFormat INSTANCE = new Default230CFormat();
-    public static final String NAME = "default 2.3.0";
-
-    /**
-     * "c" number format as it was before Incompatible Improvements 2.3.21.
-     */
-    static final DecimalFormat LEGACY_NUMBER_FORMAT_PROTOTYPE = new DecimalFormat(
-            "0.################",
-            new DecimalFormatSymbols(Locale.US));
-    static {
-        LEGACY_NUMBER_FORMAT_PROTOTYPE.setGroupingUsed(false);
-        LEGACY_NUMBER_FORMAT_PROTOTYPE.setDecimalSeparatorAlwaysShown(false);
-    }
-
-    private Default230CFormat() {
-    }
-
-    @Override
-    NumberFormat getLegacyNumberFormat(Environment env) {
-        // Note: DecimalFormat-s aren't thread-safe, so you must clone the static field value.
-        return (NumberFormat) LEGACY_NUMBER_FORMAT_PROTOTYPE.clone();
-    }
-
-    @Override
-    public String getName() {
-        return NAME;
-    }
-}
diff --git a/src/main/java/freemarker/core/Default2321CFormat.java b/src/main/java/freemarker/core/Default2321CFormat.java
deleted file mode 100644
index c466769a..00000000
--- a/src/main/java/freemarker/core/Default2321CFormat.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package freemarker.core;
-
-import java.text.DecimalFormat;
-import java.text.DecimalFormatSymbols;
-import java.text.NumberFormat;
-
-import freemarker.template.Configuration;
-import freemarker.template.Version;
-
-/**
- * Corresponds to the behavior of {@code ?c} if
- * {@link Configuration#Configuration(Version) incompatible_improvements} is between
- * {@linkplain Configuration#VERSION_2_3_21 2.3.21} and {@linkplain Configuration#VERSION_2_3_31 2.3.31}.
- * The only good reason for using this is strict backward-compatibility.
- *
- * <p><b>Experimental class!</b> This class is too new, and might will change over time. Therefore, for now
- * constructor and most methods are not exposed outside FreeMarker, and so you can't create a custom implementation.
- * The class itself and some members are exposed as they are needed for configuring FreeMarker.
- *
- * @see Default230CFormat
- * @see JSONCFormat
- *
- * @since 2.3.32
- */
-public final class Default2321CFormat extends AbstractLegacyCFormat {
-    public static final Default2321CFormat INSTANCE = new Default2321CFormat();
-    public static final String NAME = "default 2.3.21";
-
-    /**
-     * "c" number format as it was starting from Incompatible Improvements 2.3.21.
-     */
-    private static final DecimalFormat LEGACY_NUMBER_FORMAT_PROTOTYPE = (DecimalFormat) Default230CFormat.LEGACY_NUMBER_FORMAT_PROTOTYPE.clone();
-    static {
-        DecimalFormatSymbols symbols = LEGACY_NUMBER_FORMAT_PROTOTYPE.getDecimalFormatSymbols();
-        symbols.setInfinity("INF");
-        symbols.setNaN("NaN");
-        LEGACY_NUMBER_FORMAT_PROTOTYPE.setDecimalFormatSymbols(symbols);
-    }
-
-    private Default2321CFormat() {
-    }
-
-    @Override
-    NumberFormat getLegacyNumberFormat(Environment env) {
-        // Note: DecimalFormat-s aren't thread-safe, so you must clone the static field value.
-        return (NumberFormat) LEGACY_NUMBER_FORMAT_PROTOTYPE.clone();
-    }
-
-    @Override
-    public String getName() {
-        return NAME;
-    }
-}
diff --git a/src/main/java/freemarker/core/Environment.java b/src/main/java/freemarker/core/Environment.java
index c5be9e17..a56d9ddf 100644
--- a/src/main/java/freemarker/core/Environment.java
+++ b/src/main/java/freemarker/core/Environment.java
@@ -1679,7 +1679,13 @@ public final class Environment extends Configurable {
     @Deprecated
     public NumberFormat getCNumberFormat() {
         if (cNumberFormat == null) {
-            cNumberFormat = getCFormatWithPre2331IcIBug().getLegacyNumberFormat(this);
+            CFormat cFormat = getCFormat();
+            if (cFormat == LegacyCFormat.INSTANCE && configuration.getIncompatibleImprovements().intValue() < _VersionInts.V_2_3_31) {
+                // Emulate old bug
+                cNumberFormat = ((LegacyCFormat) cFormat).getLegacyNumberFormat(_VersionInts.V_2_3_20);
+            } else {
+                cNumberFormat = cFormat.getLegacyNumberFormat(this);
+            }
         }
         return cNumberFormat;
     }
@@ -1705,20 +1711,17 @@ public final class Environment extends Configurable {
      */
     private TemplateNumberFormat getCTemplateNumberFormatWithPre2331IcIBug() {
         if (cTemplateNumberFormatWithPre2331IcIBug == null) {
-            cTemplateNumberFormatWithPre2331IcIBug = getCFormatWithPre2331IcIBug().getTemplateNumberFormat(this);
+            CFormat cFormat = getCFormat();
+            if (cFormat == LegacyCFormat.INSTANCE && configuration.getIncompatibleImprovements().intValue() < _VersionInts.V_2_3_31) {
+                // Emulate old bug
+                cTemplateNumberFormatWithPre2331IcIBug = ((LegacyCFormat) cFormat).getTemplateNumberFormat(_VersionInts.V_2_3_20);
+            } else {
+                cTemplateNumberFormatWithPre2331IcIBug = cFormat.getTemplateNumberFormat(this);
+            }
         }
         return cTemplateNumberFormatWithPre2331IcIBug;
     }
 
-    private CFormat getCFormatWithPre2331IcIBug() {
-        CFormat cFormat = getCFormat();
-        if (cFormat == Default2321CFormat.INSTANCE
-                && configuration.getIncompatibleImprovements().intValue() < _VersionInts.V_2_3_31) {
-            return Default230CFormat.INSTANCE;
-        }
-        return cFormat;
-    }
-
     @Override
     public void setCFormat(CFormat cFormat) {
         CFormat prevCFormat = getCFormat();
diff --git a/src/main/java/freemarker/core/JavaCFormat.java b/src/main/java/freemarker/core/JavaCFormat.java
index 020378e0..64c6feb9 100644
--- a/src/main/java/freemarker/core/JavaCFormat.java
+++ b/src/main/java/freemarker/core/JavaCFormat.java
@@ -39,7 +39,9 @@ public final class JavaCFormat extends CFormat {
             "Double.POSITIVE_INFINITY", "Double.NEGATIVE_INFINITY", "Double.NaN",
             "Float.POSITIVE_INFINITY", "Float.NEGATIVE_INFINITY", "Float.NaN");
 
-    private static final DecimalFormat LEGACY_NUMBER_FORMAT_PROTOTYPE = (DecimalFormat) Default230CFormat.LEGACY_NUMBER_FORMAT_PROTOTYPE.clone();
+    private static final DecimalFormat LEGACY_NUMBER_FORMAT_PROTOTYPE
+            = (DecimalFormat) LegacyCFormat.LEGACY_NUMBER_FORMAT_PROTOTYPE_2_3_0.clone();
+
     static {
         DecimalFormatSymbols symbols = LEGACY_NUMBER_FORMAT_PROTOTYPE.getDecimalFormatSymbols();
         symbols.setInfinity("Double.POSITIVE_INFINITY");
diff --git a/src/main/java/freemarker/core/LegacyCFormat.java b/src/main/java/freemarker/core/LegacyCFormat.java
new file mode 100644
index 00000000..1f3d5886
--- /dev/null
+++ b/src/main/java/freemarker/core/LegacyCFormat.java
@@ -0,0 +1,173 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package freemarker.core;
+
+import java.text.DecimalFormat;
+import java.text.DecimalFormatSymbols;
+import java.text.NumberFormat;
+import java.util.Locale;
+
+import freemarker.template.Configuration;
+import freemarker.template.TemplateException;
+import freemarker.template.TemplateModelException;
+import freemarker.template.TemplateNumberModel;
+import freemarker.template.Version;
+import freemarker.template._VersionInts;
+import freemarker.template.utility.StringUtil;
+
+/**
+ * Corresponds to the behavior of {@code ?c} before {@linkplain Configuration#VERSION_2_3_32 2.3.32} (when there
+ * were no {@link CFormat}-s yet). This only exists for strict backward-compatibility, otherwise avoid this, mostly
+ * because its number-to-string conversion sometimes do rounding, and infinity and NaN formatting has some glitches.
+ * This is the default of {@link Configurable#setCFormat(CFormat) c_format} if
+ * {@link Configuration#Configuration(Version) incompatible_improvements} is less than 2.3.32.
+ *
+ * <p>If {@link Configuration#Configuration(Version) incompatible_improvements} is at least
+ * 2.3.21, then infinity is formatted as {@code INF}, and NaN as
+ * {@code NaN}. If it's less, then infinity is formatted to the infinity character (U+221E), and NaN to the
+ * UNICODE replacement character (U+FFFD). But, because of an old bug that we emulate, this only applies to the behavior
+ * of {@code ?c}/{@code ?cn}, and not to the {@code "c"} and {@code "computer"}
+ * {@link Configurable#setNumberFormat(String) number_format}.
+ * The last uses the pre-2.3.21 format before {@link Configuration#Configuration(Version) incompatible_improvements}
+ * 2.3.31.
+ *
+ * <p><b>Experimental class!</b> This class is too new, and might will change over time. Therefore, for now
+ * constructor and most methods are not exposed outside FreeMarker, and so you can't create a custom implementation.
+ * The class itself and some members are exposed as they are needed for configuring FreeMarker.
+ *
+ * @see JavaScriptOrJSONCFormat
+ *
+ * @since 2.3.32
+ */
+public final class LegacyCFormat extends CFormat {
+    public static final LegacyCFormat INSTANCE = new LegacyCFormat();
+    public static final String NAME = "legacy";
+
+    /**
+     * "c" number format as it was before Incompatible Improvements 2.3.21.
+     */
+    static final DecimalFormat LEGACY_NUMBER_FORMAT_PROTOTYPE_2_3_0 = new DecimalFormat(
+            "0.################",
+            new DecimalFormatSymbols(Locale.US));
+    static {
+        LEGACY_NUMBER_FORMAT_PROTOTYPE_2_3_0.setGroupingUsed(false);
+        LEGACY_NUMBER_FORMAT_PROTOTYPE_2_3_0.setDecimalSeparatorAlwaysShown(false);
+    }
+
+    /**
+     * "c" number format as it was starting from Incompatible Improvements 2.3.21.
+     */
+    private static final DecimalFormat LEGACY_NUMBER_FORMAT_PROTOTYPE_2_3_21 = (DecimalFormat) LEGACY_NUMBER_FORMAT_PROTOTYPE_2_3_0.clone();
+    static {
+        DecimalFormatSymbols symbols = LEGACY_NUMBER_FORMAT_PROTOTYPE_2_3_21.getDecimalFormatSymbols();
+        symbols.setInfinity("INF");
+        symbols.setNaN("NaN");
+        LEGACY_NUMBER_FORMAT_PROTOTYPE_2_3_21.setDecimalFormatSymbols(symbols);
+    }
+
+    private LegacyCFormat() {
+    }
+
+    @Override
+    final String formatString(String s, Environment env) throws TemplateException {
+        return StringUtil.jsStringEnc(
+                s, StringUtil.JsStringEncCompatibility.JAVA_SCRIPT_OR_JSON, StringUtil.JsStringEncQuotation.QUOTATION_MARK);
+    }
+
+    @Override
+    final TemplateNumberFormat getTemplateNumberFormat(Environment env) {
+        return getTemplateNumberFormat(env.getConfiguration().getIncompatibleImprovements().intValue());
+    }
+
+    TemplateNumberFormat getTemplateNumberFormat(int iciVersion) {
+        return new LegacyCTemplateNumberFormat(getLegacyNumberFormat(iciVersion));
+    }
+
+    @Override
+    String getTrueString() {
+        return "true";
+    }
+
+    @Override
+    String getFalseString() {
+        return "false";
+    }
+
+    @Override
+    final String getNullString() {
+        return "null";
+    }
+
+    @Override
+    NumberFormat getLegacyNumberFormat(Environment env) {
+        // Note: DecimalFormat-s aren't thread-safe, so you must clone the static field value.
+        return getLegacyNumberFormat(env.getConfiguration().getIncompatibleImprovements().intValue());
+    }
+
+    NumberFormat getLegacyNumberFormat(int iciVersion) {
+        NumberFormat numberFormatPrototype;
+        if (iciVersion < _VersionInts.V_2_3_21) {
+            numberFormatPrototype = LEGACY_NUMBER_FORMAT_PROTOTYPE_2_3_0;
+        } else {
+            numberFormatPrototype = LEGACY_NUMBER_FORMAT_PROTOTYPE_2_3_21;
+        }
+        return (NumberFormat) numberFormatPrototype.clone();
+    }
+
+    @Override
+    public String getName() {
+        return NAME;
+    }
+
+    static final class LegacyCTemplateNumberFormat extends JavaTemplateNumberFormat {
+
+        public LegacyCTemplateNumberFormat(NumberFormat numberFormat) {
+            super(numberFormat, Environment.COMPUTER_FORMAT_STRING);
+        }
+
+        @Override
+        public String formatToPlainText(TemplateNumberModel numberModel) throws UnformattableValueException,
+                TemplateModelException {
+            Number number = TemplateFormatUtil.getNonNullNumber(numberModel);
+            return format(number);
+        }
+
+        @Override
+        public boolean isLocaleBound() {
+            return false;
+        }
+
+        @Override
+        String format(Number number) throws UnformattableValueException {
+            if (number instanceof Integer || number instanceof Long) {
+                // Accelerate these fairly common cases
+                return number.toString();
+            }
+            return super.format(number);
+        }
+
+        @Override
+        public String getDescription() {
+            return "LegacyC(" + super.getDescription() + ")";
+        }
+
+    }
+
+}
diff --git a/src/main/java/freemarker/core/XSCFormat.java b/src/main/java/freemarker/core/XSCFormat.java
index 016f8f27..49c4165b 100644
--- a/src/main/java/freemarker/core/XSCFormat.java
+++ b/src/main/java/freemarker/core/XSCFormat.java
@@ -47,7 +47,8 @@ public final class XSCFormat extends CFormat {
             "INF", "-INF", "NaN",
             "INF", "-INF", "NaN");
 
-    private static final DecimalFormat LEGACY_NUMBER_FORMAT_PROTOTYPE = (DecimalFormat) Default230CFormat.LEGACY_NUMBER_FORMAT_PROTOTYPE.clone();
+    private static final DecimalFormat LEGACY_NUMBER_FORMAT_PROTOTYPE
+            = (DecimalFormat) LegacyCFormat.LEGACY_NUMBER_FORMAT_PROTOTYPE_2_3_0.clone();
     static {
         DecimalFormatSymbols symbols = LEGACY_NUMBER_FORMAT_PROTOTYPE.getDecimalFormatSymbols();
         symbols.setInfinity("INF");
diff --git a/src/main/java/freemarker/core/_StandardCLanguages.java b/src/main/java/freemarker/core/_StandardCLanguages.java
index 9dec5a1b..9a22e7ca 100644
--- a/src/main/java/freemarker/core/_StandardCLanguages.java
+++ b/src/main/java/freemarker/core/_StandardCLanguages.java
@@ -33,8 +33,7 @@ final class StandardCFormats {
         addStandardCFormat(JavaScriptCFormat.INSTANCE);
         addStandardCFormat(JavaCFormat.INSTANCE);
         addStandardCFormat(XSCFormat.INSTANCE);
-        addStandardCFormat(Default230CFormat.INSTANCE);
-        addStandardCFormat(Default2321CFormat.INSTANCE);
+        addStandardCFormat(LegacyCFormat.INSTANCE);
     }
 
     private static void addStandardCFormat(CFormat cFormat) {
diff --git a/src/main/java/freemarker/template/Configuration.java b/src/main/java/freemarker/template/Configuration.java
index 540294bd..7d4933c4 100644
--- a/src/main/java/freemarker/template/Configuration.java
+++ b/src/main/java/freemarker/template/Configuration.java
@@ -63,13 +63,12 @@ import freemarker.core.CFormat;
 import freemarker.core.CSSOutputFormat;
 import freemarker.core.CombinedMarkupOutputFormat;
 import freemarker.core.Configurable;
-import freemarker.core.Default230CFormat;
-import freemarker.core.Default2321CFormat;
 import freemarker.core.Environment;
 import freemarker.core.HTMLOutputFormat;
 import freemarker.core.JSONOutputFormat;
 import freemarker.core.JavaScriptOrJSONCFormat;
 import freemarker.core.JavaScriptOutputFormat;
+import freemarker.core.LegacyCFormat;
 import freemarker.core.MarkupOutputFormat;
 import freemarker.core.OutputFormat;
 import freemarker.core.ParseException;
@@ -959,8 +958,7 @@ public class Configuration extends Configurable implements Cloneable, ParserConf
      *         {@code "computer"} {@link Configurable#setNumberFormat(String) number_format}) changes, if the
      *         {@link #setCFormat(CFormat) c_format} setting was left on its default. The default of
      *         {@link #setCFormat(CFormat) c_format} changes to {@link JavaScriptOrJSONCFormat#INSTANCE}, from
-     *         {@link Default2321CFormat#INSTANCE} (or from {@link Default230CFormat#INSTANCE}, depending on the
-     *         previous Incompatible Improvement value), and that's what contains the changes:</p>
+     *         {@link LegacyCFormat#INSTANCE}, and that's what contains the changes:</p>
      *         <ul>
      *           <li><p>Changes affecting non-whole numbers, and whole numbers with over 100 digits:
      *             Formatting is now lossless, so it potentially shows much more decimals.
@@ -2512,13 +2510,9 @@ public class Configuration extends Configurable implements Cloneable, ParserConf
     }
 
     static CFormat getDefaultCFormat(Version incompatibleImprovements) {
-        if (incompatibleImprovements.intValue() >= _VersionInts.V_2_3_32) {
-            return JavaScriptOrJSONCFormat.INSTANCE;
-        }
-        if (incompatibleImprovements.intValue() >= _VersionInts.V_2_3_21) {
-            return Default2321CFormat.INSTANCE;
-        }
-        return Default230CFormat.INSTANCE;
+        return incompatibleImprovements.intValue() >= _VersionInts.V_2_3_32
+                ? JavaScriptOrJSONCFormat.INSTANCE
+                : LegacyCFormat.INSTANCE;
     }
 
     /**
diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml
index 06f82070..2f9d3b7d 100644
--- a/src/manual/en_US/book.xml
+++ b/src/manual/en_US/book.xml
@@ -6120,17 +6120,11 @@ To prove that "s" didn't contain the value in escaped form:
           </listitem>
 
           <listitem>
-            <para><literal>"default 2.3.0"</literal>: Default for backward
-            compatibility if the <link
+            <para><literal>"legacy"</literal>: Default for backward
+            compatibility when the <link
             linkend="pgui_config_incompatible_improvements"><literal>incompatible_improvements</literal>
-            setting</link> is less than 2.3.21. Avoid!</para>
-          </listitem>
-
-          <listitem>
-            <para><literal>"default 2.3.21"</literal>: Default for backward
-            compatibility if the <link
-            linkend="pgui_config_incompatible_improvements"><literal>incompatible_improvements</literal>
-            setting</link> is equal or greater than 2.3.21. Avoid!</para>
+            setting</link> is less than 2.3.32. Avoid! Can have rounding
+            losses, and formatting glitches for infinity and NaN.</para>
           </listitem>
         </itemizedlist>
 
@@ -13494,12 +13488,11 @@ GreEN mouse
 
           <itemizedlist>
             <listitem>
-              <para><quote>JSON</quote>, <quote>default 2.3.0</quote>, and
-              <quote>default 2.3.21</quote>: Gives a JSON string literal, that
-              is, it will be surrounded with quotation marks
-              (<literal>"</literal>), and will be escaped using backslash
-              (<literal>\</literal>) where needed. For the exact escaping
-              rules see <link linkend="ref_builtin_json_string">the
+              <para><quote>JSON</quote>, <quote>legacy</quote>: Gives a JSON
+              string literal, that is, it will be surrounded with quotation
+              marks (<literal>"</literal>), and will be escaped using
+              backslash (<literal>\</literal>) where needed. For the exact
+              escaping rules see <link linkend="ref_builtin_json_string">the
               <literal>json_string</literal> built-in</link>.</para>
             </listitem>
 
@@ -16036,18 +16029,18 @@ rif: foo XYr baar</programlisting>
 
               <itemizedlist>
                 <listitem>
-                  <para>For all non-deprecated <literal>c_format</literal>-s
-                  that are built into FreeMarker: There's no rounding.</para>
+                  <para>For all that are built into FreeMarker, except
+                  <quote>legacy</quote> <literal>c_format </literal>: There's
+                  no rounding.</para>
                 </listitem>
 
                 <listitem>
-                  <para>For the deprecated <literal>c_format</literal>-s,
-                  <quote>default 2.3.0</quote>, and <quote>default
-                  2.3.21</quote>: The numbers are limited to 16 digits after
-                  the decimal dot, so rounding can occur. The these formats
-                  never use exponential form either, so the decimal point
-                  place is fixed. Thus, for example, 1E-17 will be formatted
-                  as <literal>0</literal>. </para>
+                  <para>For the deprecated <literal>c_format</literal>,
+                  <quote>legacy</quote>: The numbers are limited to 16 digits
+                  after the decimal dot, so rounding can occur. The these
+                  formats never use exponential form either, so the decimal
+                  point place is fixed. Thus, for example, 1E-17 will be
+                  formatted as <literal>0</literal>.</para>
                 </listitem>
               </itemizedlist>
             </listitem>
@@ -16079,14 +16072,19 @@ rif: foo XYr baar</programlisting>
 
                 <listitem>
                   <para>For <literal>c_format</literal> <quote>XS</quote>, and
-                  also for the deprecated <literal>c_format</literal>,
-                  <quote>default 2.3.21</quote>: <literal>INF</literal>,
-                  <literal>-INF</literal>, and <literal>NaN</literal>.</para>
+                  also if <link
+                  linkend="pgui_config_incompatible_improvements"><literal>incompatible_improvements</literal>
+                  setting</link> is at least 2.3.21, for
+                  <literal>c_format</literal>, <quote>legacy</quote>:
+                  <literal>INF</literal>, <literal>-INF</literal>, and
+                  <literal>NaN</literal>.</para>
                 </listitem>
 
                 <listitem>
-                  <para>For the deprecated <literal>c_format</literal>,
-                  <quote>default 2.3.0</quote>: Gives what
+                  <para>For <literal>c_format</literal> <quote>legacy</quote>,
+                  if <link
+                  linkend="pgui_config_incompatible_improvements"><literal>incompatible_improvements</literal>
+                  setting</link> is less than 2.3.21: Gives what
                   <literal>java.text.DecimalFormat</literal> does with US
                   locale, which are <literal>∞</literal>,
                   <literal>-∞</literal>, and <literal>�</literal> (U+FFFD,
@@ -16096,10 +16094,9 @@ rif: foo XYr baar</programlisting>
             </listitem>
 
             <listitem>
-              <para>Exponential form is used by all non-deprecated
-              <literal>c_format</literal>-s that are built into FreeMarker
-              (but not by the deprecated <quote>default 2.3.0</quote>, and
-              <quote>default 2.3.21</quote>):</para>
+              <para>Exponential form is used by all
+              <literal>c_format</literal>-s that are built into FreeMarker,
+              except <quote>legacy</quote>:</para>
 
               <itemizedlist>
                 <listitem>
@@ -16231,8 +16228,8 @@ rif: foo XYr baar</programlisting>
           <itemizedlist>
             <listitem>
               <para>For <quote>JSON</quote>, <quote>Java</quote>,
-              <quote>JavaScript</quote>, <quote>default 2.3.0</quote>,
-              <quote>default 2.3.21</quote>: <literal>null</literal></para>
+              <quote>JavaScript</quote>, and <quote>legacy</quote>:
+              <literal>null</literal></para>
             </listitem>
 
             <listitem>
@@ -30075,12 +30072,13 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
                   <para>If you set the <link
                   linkend="pgui_config_incompatible_improvements_how_to_set"><literal>incompatible_improvements</literal>
                   setting</link> to 2.3.32, the default of
-                  <literal>c_format</literal> changes to
-                  <literal>JSON</literal>, which is a format that most targets
-                  can parse (because we just format simple values, not lists
-                  and maps). With lower
+                  <literal>c_format</literal> changes from
+                  <literal>"legacy"</literal> to <literal>"JavaScript or
+                  JSON"</literal>, which is a format that most targets can
+                  parse (because we just format simple values, not lists and
+                  maps). With lower
                   <literal>incompatible_improvements</literal>, the default
-                  value is a <literal>c_format</literal> that emulates the old
+                  value is <literal>"legacy"</literal> that emulates the old
                   behavior of <literal>?c</literal> (where you can lose
                   numerical prevision, etc.), so it's recommended to set it to
                   something else.</para>
diff --git a/src/test/java/freemarker/core/CustomCFormat.java b/src/test/java/freemarker/core/CustomCFormat.java
index 86658b0d..9ec224b8 100644
--- a/src/test/java/freemarker/core/CustomCFormat.java
+++ b/src/test/java/freemarker/core/CustomCFormat.java
@@ -36,8 +36,8 @@ class CustomCFormat extends CFormat {
             "M:INF", "M:NINF", "M:NaN",
             "M:INF", "M:NINF", "M:NaN");
 
-    private static final DecimalFormat LEGACY_NUMBER_FORMAT_PROTOTYPE =
-            (DecimalFormat) Default230CFormat.LEGACY_NUMBER_FORMAT_PROTOTYPE.clone();
+    private static final DecimalFormat LEGACY_NUMBER_FORMAT_PROTOTYPE
+            = (DecimalFormat) LegacyCFormat.LEGACY_NUMBER_FORMAT_PROTOTYPE_2_3_0.clone();
 
     static {
         DecimalFormatSymbols symbols = LEGACY_NUMBER_FORMAT_PROTOTYPE.getDecimalFormatSymbols();
diff --git a/src/test/java/freemarker/template/ConfigurationTest.java b/src/test/java/freemarker/template/ConfigurationTest.java
index 3a6dea5b..756b3fae 100644
--- a/src/test/java/freemarker/template/ConfigurationTest.java
+++ b/src/test/java/freemarker/template/ConfigurationTest.java
@@ -61,8 +61,6 @@ import freemarker.core.Configurable.SettingValueAssignmentException;
 import freemarker.core.Configurable.UnknownSettingException;
 import freemarker.core.ConfigurableTest;
 import freemarker.core.CustomHTMLOutputFormat;
-import freemarker.core.Default230CFormat;
-import freemarker.core.Default2321CFormat;
 import freemarker.core.DefaultTruncateBuiltinAlgorithm;
 import freemarker.core.DummyOutputFormat;
 import freemarker.core.Environment;
@@ -74,6 +72,7 @@ import freemarker.core.JSONCFormat;
 import freemarker.core.JavaCFormat;
 import freemarker.core.JavaScriptCFormat;
 import freemarker.core.JavaScriptOrJSONCFormat;
+import freemarker.core.LegacyCFormat;
 import freemarker.core.MarkupOutputFormat;
 import freemarker.core.OptInTemplateClassResolver;
 import freemarker.core.OutputFormat;
@@ -190,13 +189,13 @@ public class ConfigurationTest extends TestCase {
         assertFalse(((DefaultObjectWrapper) cfg.getObjectWrapper()).getPreferIndexedReadMethod());
 
         cfg = new Configuration(Configuration.VERSION_2_3_0);
-        assertSame(Default230CFormat.INSTANCE, cfg.getCFormat());
+        assertSame(LegacyCFormat.INSTANCE, cfg.getCFormat());
         cfg.setIncompatibleImprovements(Configuration.VERSION_2_3_20);
-        assertSame(Default230CFormat.INSTANCE, cfg.getCFormat());
+        assertSame(LegacyCFormat.INSTANCE, cfg.getCFormat());
         cfg.setIncompatibleImprovements(Configuration.VERSION_2_3_21);
-        assertSame(Default2321CFormat.INSTANCE, cfg.getCFormat());
+        assertSame(LegacyCFormat.INSTANCE, cfg.getCFormat());
         cfg.setIncompatibleImprovements(Configuration.VERSION_2_3_31);
-        assertSame(Default2321CFormat.INSTANCE, cfg.getCFormat());
+        assertSame(LegacyCFormat.INSTANCE, cfg.getCFormat());
         cfg.setIncompatibleImprovements(Configuration.VERSION_2_3_32);
         assertSame(JavaScriptOrJSONCFormat.INSTANCE, cfg.getCFormat());
         cfg.setCFormat(JavaScriptOrJSONCFormat.INSTANCE); // Same as default, but explicitly set now
@@ -1921,17 +1920,17 @@ public class ConfigurationTest extends TestCase {
     public void testCFormat() throws TemplateException {
         Configuration cfg = new Configuration(Configuration.VERSION_2_3_21);
 
-        assertSame(Default2321CFormat.INSTANCE, cfg.getCFormat());
-        cfg.setSetting(Configuration.C_FORMAT_KEY_SNAKE_CASE, Default230CFormat.NAME);
-        assertSame(Default230CFormat.INSTANCE, cfg.getCFormat());
+        assertSame(LegacyCFormat.INSTANCE, cfg.getCFormat());
+        cfg.setSetting(Configuration.C_FORMAT_KEY_SNAKE_CASE, LegacyCFormat.NAME);
+        assertSame(LegacyCFormat.INSTANCE, cfg.getCFormat());
         cfg.setSetting(Configuration.C_FORMAT_KEY_CAMEL_CASE, JSONCFormat.NAME);
         assertSame(JSONCFormat.INSTANCE, cfg.getCFormat());
 
         cfg.setSetting(Configuration.C_FORMAT_KEY_CAMEL_CASE, "default");
-        cfg.setSetting(Configuration.C_FORMAT_KEY_SNAKE_CASE, Default2321CFormat.NAME);
+        cfg.setSetting(Configuration.C_FORMAT_KEY_SNAKE_CASE, LegacyCFormat.NAME);
 
         for (CFormat standardCFormat : new CFormat[] {
-                        Default230CFormat.INSTANCE, Default2321CFormat.INSTANCE,
+                        LegacyCFormat.INSTANCE,
                         JSONCFormat.INSTANCE, JavaScriptCFormat.INSTANCE, JavaCFormat.INSTANCE,
                         XSCFormat.INSTANCE
                 }) {


[freemarker] 01/02: CFormat: Further API and javadoc cleanup

Posted by dd...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ddekany pushed a commit to branch 2.3-gae
in repository https://gitbox.apache.org/repos/asf/freemarker.git

commit 21022a6cffc32cc7bb2b6e8d1ccb8de657015956
Author: ddekany <dd...@apache.org>
AuthorDate: Fri Dec 30 20:05:46 2022 +0100

    CFormat: Further API and javadoc cleanup
---
 .../java/freemarker/core/AbstractJSONLikeFormat.java     |  8 ++++----
 src/main/java/freemarker/core/AbstractLegacyCFormat.java | 14 +++++---------
 src/main/java/freemarker/core/CFormat.java               | 13 +++++++------
 src/main/java/freemarker/core/Configurable.java          | 13 +++++++++----
 src/main/java/freemarker/core/Default230CFormat.java     |  6 +++---
 src/main/java/freemarker/core/Default2321CFormat.java    |  6 +++---
 src/main/java/freemarker/core/Environment.java           |  6 +++---
 src/main/java/freemarker/core/JSONCFormat.java           |  2 +-
 src/main/java/freemarker/core/JavaCFormat.java           |  6 +++---
 src/main/java/freemarker/core/JavaScriptCFormat.java     |  2 +-
 .../java/freemarker/core/JavaScriptOrJSONCFormat.java    |  2 +-
 src/main/java/freemarker/core/XSCFormat.java             |  8 ++++----
 src/main/java/freemarker/template/Configuration.java     | 16 +++++++++-------
 src/manual/en_US/book.xml                                |  8 ++++----
 .../java/freemarker/core/CTemplateNumberFormatTest.java  |  2 +-
 src/test/java/freemarker/core/CustomCFormat.java         |  6 +++---
 16 files changed, 61 insertions(+), 57 deletions(-)

diff --git a/src/main/java/freemarker/core/AbstractJSONLikeFormat.java b/src/main/java/freemarker/core/AbstractJSONLikeFormat.java
index 190ce697..ad6b7349 100644
--- a/src/main/java/freemarker/core/AbstractJSONLikeFormat.java
+++ b/src/main/java/freemarker/core/AbstractJSONLikeFormat.java
@@ -26,7 +26,7 @@ import java.text.NumberFormat;
 /**
  * Defines the methods in {@link CFormat} that are the same for all JSON-like languages.
  *
- * <p><b>Experimental class!</b> This class is too new, and might will change over time. Therefore, for now the
+ * <p><b>Experimental class!</b> This class is too new, and might will change over time. Therefore, for now
  * constructor and most methods are not exposed outside FreeMarker, and so you can't create a custom implementation.
  * The class itself and some members are exposed as they are needed for configuring FreeMarker.
  *
@@ -37,7 +37,7 @@ public abstract class AbstractJSONLikeFormat extends CFormat {
             "Infinity", "-Infinity", "NaN",
             "Infinity", "-Infinity", "NaN");
 
-    private static final DecimalFormat LEGACY_NUMBER_FORMAT_PROTOTYPE = (DecimalFormat) Default230CFormat.INSTANCE.getLegacyNumberFormat().clone();
+    private static final DecimalFormat LEGACY_NUMBER_FORMAT_PROTOTYPE = (DecimalFormat) Default230CFormat.LEGACY_NUMBER_FORMAT_PROTOTYPE.clone();
     static {
         DecimalFormatSymbols symbols = LEGACY_NUMBER_FORMAT_PROTOTYPE.getDecimalFormatSymbols();
         symbols.setInfinity("Infinity");
@@ -65,12 +65,12 @@ public abstract class AbstractJSONLikeFormat extends CFormat {
     }
 
     @Override
-    final TemplateNumberFormat getTemplateNumberFormat() {
+    final TemplateNumberFormat getTemplateNumberFormat(Environment env) {
         return TEMPLATE_NUMBER_FORMAT;
     }
 
     @Override
-    NumberFormat getLegacyNumberFormat() {
+    NumberFormat getLegacyNumberFormat(Environment env) {
         return (NumberFormat) LEGACY_NUMBER_FORMAT_PROTOTYPE.clone();
     }
 }
diff --git a/src/main/java/freemarker/core/AbstractLegacyCFormat.java b/src/main/java/freemarker/core/AbstractLegacyCFormat.java
index bdf7577d..c564d144 100644
--- a/src/main/java/freemarker/core/AbstractLegacyCFormat.java
+++ b/src/main/java/freemarker/core/AbstractLegacyCFormat.java
@@ -19,8 +19,6 @@
 
 package freemarker.core;
 
-import java.text.NumberFormat;
-
 import freemarker.template.TemplateException;
 import freemarker.template.TemplateModelException;
 import freemarker.template.TemplateNumberModel;
@@ -31,7 +29,7 @@ import freemarker.template.utility.StringUtil.JsStringEncQuotation;
 /**
  * Super class of {@link CFormat}-s that merely exist to mimic old {@code ?c} behavior for backward compatibility.
  *
- * <p><b>Experimental class!</b> This class is too new, and might will change over time. Therefore, for now the
+ * <p><b>Experimental class!</b> This class is too new, and might will change over time. Therefore, for now
  * constructor and most methods are not exposed outside FreeMarker, and so you can't create a custom implementation.
  * The class itself and some members are exposed as they are needed for configuring FreeMarker.
  *
@@ -50,8 +48,8 @@ public abstract class AbstractLegacyCFormat extends CFormat {
     }
 
     @Override
-    final TemplateNumberFormat getTemplateNumberFormat() {
-        return new LegacyCTemplateNumberFormat();
+    final TemplateNumberFormat getTemplateNumberFormat(Environment env) {
+        return new LegacyCTemplateNumberFormat(env);
     }
 
     @Override
@@ -69,12 +67,10 @@ public abstract class AbstractLegacyCFormat extends CFormat {
         return "null";
     }
 
-    abstract NumberFormat getLegacyNumberFormat();
-
     final class LegacyCTemplateNumberFormat extends JavaTemplateNumberFormat {
 
-        public LegacyCTemplateNumberFormat() {
-            super(getLegacyNumberFormat(), Environment.COMPUTER_FORMAT_STRING);
+        public LegacyCTemplateNumberFormat(Environment env) {
+            super(getLegacyNumberFormat(env), Environment.COMPUTER_FORMAT_STRING);
         }
 
         @Override
diff --git a/src/main/java/freemarker/core/CFormat.java b/src/main/java/freemarker/core/CFormat.java
index d9d0cca8..1b92f607 100644
--- a/src/main/java/freemarker/core/CFormat.java
+++ b/src/main/java/freemarker/core/CFormat.java
@@ -28,9 +28,9 @@ import freemarker.template.TemplateException;
  * {@code "c"} and {@code "computer"} {@link Configurable#setNumberFormat(String) number_format}, and
  * the {@code "c"} {@link Configurable#setBooleanFormat(String) boolean_format}.
  * A {@link CFormat} currently defines how numbers, booleans, and strings are converted to text that defines a similar
- * value in some computer language (or other computer-parsed syntax) that the {@link CFormat} is made for.
+ * value in a certain computer language (or other computer-parsed syntax).
  *
- * <p><b>Experimental class!</b> This class is too new, and might will change over time. Therefore, for now the
+ * <p><b>Experimental class!</b> This class is too new, and might will change over time. Therefore, for now
  * constructor and most methods are not exposed outside FreeMarker, and so you can't create a custom implementation.
  * The class itself and some members are exposed as they are needed for configuring FreeMarker.
  *
@@ -50,17 +50,18 @@ public abstract class CFormat {
      * which is mutable, or not thread-safe, then it's not returned, but a clone or copy of it. The caller of this
      * method is not responsible for do any such cloning or copying.
      */
-    abstract TemplateNumberFormat getTemplateNumberFormat();
+    abstract TemplateNumberFormat getTemplateNumberFormat(Environment env);
 
     /**
-     * Similar to {@link #getTemplateNumberFormat()}, but only exist to serve the deprecated
+     * Similar to {@link #getTemplateNumberFormat(Environment)}, but only exist to serve the deprecated
      * {@link Environment#getCNumberFormat()} method. We don't expect the result of the formatting to be the same as
      * with the {@link TemplateNumberFormat}, but this method should make some effort to be similar.
      *
-     * @deprecated Use {@link #getTemplateNumberFormat()} instead, except in {@link Environment#getCNumberFormat()}.
+     * @deprecated Use {@link #getTemplateNumberFormat(Environment)} instead, except in
+     * {@link Environment#getCNumberFormat()}.
      */
     @Deprecated
-    abstract NumberFormat getLegacyNumberFormat();
+    abstract NumberFormat getLegacyNumberFormat(Environment env);
 
     /**
      * Format a {@link String} to a string literal.
diff --git a/src/main/java/freemarker/core/Configurable.java b/src/main/java/freemarker/core/Configurable.java
index 6da2b48c..bb6ef998 100644
--- a/src/main/java/freemarker/core/Configurable.java
+++ b/src/main/java/freemarker/core/Configurable.java
@@ -857,13 +857,18 @@ public class Configurable {
     }
 
     /**
-     * Sets the default number format used to convert numbers to strings. Currently, this is one of these:
+     * Sets the number format used to convert numbers to strings. Currently, this is one of these:
      * <ul>
-     *   <li>{@code "number"}: The number format returned by {@link NumberFormat#getNumberInstance(Locale)}</li>
+     *   <li>{@code "number"}: The number format returned by {@link NumberFormat#getNumberInstance(Locale)}. This is the
+     *       default.</li>
+     *   <li>{@code "c"} (recognized since 2.3.32): The number format used by FTL's {@code c} built-in (like in
+     *       {@code someNumber?c}). So with this <code>${someNumber}</code> will output the same as
+     *       <code>${someNumber?c}</code>. This should only be used if the template solely generates source code,
+     *       configuration file, or other content that's nor read by normal users. If the template contains parts that's
+     *       read by normal users (like typical a web page), you are not supposed to use this.</li>
+     *   <li>{@code "computer"}: The old (deprecated) name for {@code "c"}. Recognized by all FreeMarker versions.</li>
      *   <li>{@code "currency"}: The number format returned by {@link NumberFormat#getCurrencyInstance(Locale)}</li>
      *   <li>{@code "percent"}: The number format returned by {@link NumberFormat#getPercentInstance(Locale)}</li>
-     *   <li>{@code "c"} (recognized since 2.3.32), or {@code "computer"} (same as {@code "c"}, but also recognized by
-     *       older versions): The number format used by FTL's {@code c} built-in (like in {@code someNumber?c}).</li>
      *   <li>{@link java.text.DecimalFormat} pattern (like {@code "0.##"}). This syntax is extended by FreeMarker
      *       so that you can specify options like the rounding mode and the symbols used after a 2nd semicolon. For
      *       example, {@code ",000;; roundingMode=halfUp groupingSeparator=_"} will format numbers like {@code ",000"}
diff --git a/src/main/java/freemarker/core/Default230CFormat.java b/src/main/java/freemarker/core/Default230CFormat.java
index 2a247844..88749766 100644
--- a/src/main/java/freemarker/core/Default230CFormat.java
+++ b/src/main/java/freemarker/core/Default230CFormat.java
@@ -33,7 +33,7 @@ import freemarker.template.Version;
  * {@linkplain Configuration#VERSION_2_3_21 2.3.21}.
  * The only good reason for using this is strict backward-compatibility.
  *
- * <p><b>Experimental class!</b> This class is too new, and might will change over time. Therefore, for now the
+ * <p><b>Experimental class!</b> This class is too new, and might will change over time. Therefore, for now
  * constructor and most methods are not exposed outside FreeMarker, and so you can't create a custom implementation.
  * The class itself and some members are exposed as they are needed for configuring FreeMarker.
  *
@@ -49,7 +49,7 @@ public final class Default230CFormat extends AbstractLegacyCFormat {
     /**
      * "c" number format as it was before Incompatible Improvements 2.3.21.
      */
-    private static final DecimalFormat LEGACY_NUMBER_FORMAT_PROTOTYPE = new DecimalFormat(
+    static final DecimalFormat LEGACY_NUMBER_FORMAT_PROTOTYPE = new DecimalFormat(
             "0.################",
             new DecimalFormatSymbols(Locale.US));
     static {
@@ -61,7 +61,7 @@ public final class Default230CFormat extends AbstractLegacyCFormat {
     }
 
     @Override
-    NumberFormat getLegacyNumberFormat() {
+    NumberFormat getLegacyNumberFormat(Environment env) {
         // Note: DecimalFormat-s aren't thread-safe, so you must clone the static field value.
         return (NumberFormat) LEGACY_NUMBER_FORMAT_PROTOTYPE.clone();
     }
diff --git a/src/main/java/freemarker/core/Default2321CFormat.java b/src/main/java/freemarker/core/Default2321CFormat.java
index 34258892..c466769a 100644
--- a/src/main/java/freemarker/core/Default2321CFormat.java
+++ b/src/main/java/freemarker/core/Default2321CFormat.java
@@ -32,7 +32,7 @@ import freemarker.template.Version;
  * {@linkplain Configuration#VERSION_2_3_21 2.3.21} and {@linkplain Configuration#VERSION_2_3_31 2.3.31}.
  * The only good reason for using this is strict backward-compatibility.
  *
- * <p><b>Experimental class!</b> This class is too new, and might will change over time. Therefore, for now the
+ * <p><b>Experimental class!</b> This class is too new, and might will change over time. Therefore, for now
  * constructor and most methods are not exposed outside FreeMarker, and so you can't create a custom implementation.
  * The class itself and some members are exposed as they are needed for configuring FreeMarker.
  *
@@ -48,7 +48,7 @@ public final class Default2321CFormat extends AbstractLegacyCFormat {
     /**
      * "c" number format as it was starting from Incompatible Improvements 2.3.21.
      */
-    private static final DecimalFormat LEGACY_NUMBER_FORMAT_PROTOTYPE = (DecimalFormat) Default230CFormat.INSTANCE.getLegacyNumberFormat().clone();
+    private static final DecimalFormat LEGACY_NUMBER_FORMAT_PROTOTYPE = (DecimalFormat) Default230CFormat.LEGACY_NUMBER_FORMAT_PROTOTYPE.clone();
     static {
         DecimalFormatSymbols symbols = LEGACY_NUMBER_FORMAT_PROTOTYPE.getDecimalFormatSymbols();
         symbols.setInfinity("INF");
@@ -60,7 +60,7 @@ public final class Default2321CFormat extends AbstractLegacyCFormat {
     }
 
     @Override
-    NumberFormat getLegacyNumberFormat() {
+    NumberFormat getLegacyNumberFormat(Environment env) {
         // Note: DecimalFormat-s aren't thread-safe, so you must clone the static field value.
         return (NumberFormat) LEGACY_NUMBER_FORMAT_PROTOTYPE.clone();
     }
diff --git a/src/main/java/freemarker/core/Environment.java b/src/main/java/freemarker/core/Environment.java
index 6a00a788..c5be9e17 100644
--- a/src/main/java/freemarker/core/Environment.java
+++ b/src/main/java/freemarker/core/Environment.java
@@ -1679,7 +1679,7 @@ public final class Environment extends Configurable {
     @Deprecated
     public NumberFormat getCNumberFormat() {
         if (cNumberFormat == null) {
-            cNumberFormat = getCFormatWithPre2331IcIBug().getLegacyNumberFormat();
+            cNumberFormat = getCFormatWithPre2331IcIBug().getLegacyNumberFormat(this);
         }
         return cNumberFormat;
     }
@@ -1694,7 +1694,7 @@ public final class Environment extends Configurable {
      */
     public TemplateNumberFormat getCTemplateNumberFormat() {
         if (cTemplateNumberFormat == null) {
-            cTemplateNumberFormat = getCFormat().getTemplateNumberFormat();
+            cTemplateNumberFormat = getCFormat().getTemplateNumberFormat(this);
         }
         return cTemplateNumberFormat;
     }
@@ -1705,7 +1705,7 @@ public final class Environment extends Configurable {
      */
     private TemplateNumberFormat getCTemplateNumberFormatWithPre2331IcIBug() {
         if (cTemplateNumberFormatWithPre2331IcIBug == null) {
-            cTemplateNumberFormatWithPre2331IcIBug = getCFormatWithPre2331IcIBug().getTemplateNumberFormat();
+            cTemplateNumberFormatWithPre2331IcIBug = getCFormatWithPre2331IcIBug().getTemplateNumberFormat(this);
         }
         return cTemplateNumberFormatWithPre2331IcIBug;
     }
diff --git a/src/main/java/freemarker/core/JSONCFormat.java b/src/main/java/freemarker/core/JSONCFormat.java
index de102676..40b0cc72 100644
--- a/src/main/java/freemarker/core/JSONCFormat.java
+++ b/src/main/java/freemarker/core/JSONCFormat.java
@@ -28,7 +28,7 @@ import freemarker.template.utility.StringUtil.JsStringEncQuotation;
  * {@value #NAME} {@link CFormat}; to be used when generating JSON (and not JavaScript), except, in most cases
  * {@link JavaScriptOrJSONCFormat} is recommended over this.
  *
- * <p><b>Experimental class!</b> This class is too new, and might will change over time. Therefore, for now the
+ * <p><b>Experimental class!</b> This class is too new, and might will change over time. Therefore, for now
  * most methods are not exposed outside FreeMarker. The class itself and some members are exposed as they are needed for
  * configuring FreeMarker.
  *
diff --git a/src/main/java/freemarker/core/JavaCFormat.java b/src/main/java/freemarker/core/JavaCFormat.java
index 023044df..020378e0 100644
--- a/src/main/java/freemarker/core/JavaCFormat.java
+++ b/src/main/java/freemarker/core/JavaCFormat.java
@@ -39,7 +39,7 @@ public final class JavaCFormat extends CFormat {
             "Double.POSITIVE_INFINITY", "Double.NEGATIVE_INFINITY", "Double.NaN",
             "Float.POSITIVE_INFINITY", "Float.NEGATIVE_INFINITY", "Float.NaN");
 
-    private static final DecimalFormat LEGACY_NUMBER_FORMAT_PROTOTYPE = (DecimalFormat) Default230CFormat.INSTANCE.getLegacyNumberFormat().clone();
+    private static final DecimalFormat LEGACY_NUMBER_FORMAT_PROTOTYPE = (DecimalFormat) Default230CFormat.LEGACY_NUMBER_FORMAT_PROTOTYPE.clone();
     static {
         DecimalFormatSymbols symbols = LEGACY_NUMBER_FORMAT_PROTOTYPE.getDecimalFormatSymbols();
         symbols.setInfinity("Double.POSITIVE_INFINITY");
@@ -51,7 +51,7 @@ public final class JavaCFormat extends CFormat {
     }
 
     @Override
-    TemplateNumberFormat getTemplateNumberFormat() {
+    TemplateNumberFormat getTemplateNumberFormat(Environment env) {
         return TEMPLATE_NUMBER_FORMAT;
     }
 
@@ -76,7 +76,7 @@ public final class JavaCFormat extends CFormat {
     }
 
     @Override
-    NumberFormat getLegacyNumberFormat() {
+    NumberFormat getLegacyNumberFormat(Environment env) {
         return (NumberFormat) LEGACY_NUMBER_FORMAT_PROTOTYPE.clone();
     }
 
diff --git a/src/main/java/freemarker/core/JavaScriptCFormat.java b/src/main/java/freemarker/core/JavaScriptCFormat.java
index ce5daab8..5dd7cbcd 100644
--- a/src/main/java/freemarker/core/JavaScriptCFormat.java
+++ b/src/main/java/freemarker/core/JavaScriptCFormat.java
@@ -28,7 +28,7 @@ import freemarker.template.utility.StringUtil.JsStringEncQuotation;
  * {@value #NAME} {@link CFormat}, to be used when generating JavaScript (and not JSON), except, in most cases
  * {@link JavaScriptOrJSONCFormat} is recommended over this.
  *
- * <p><b>Experimental class!</b> This class is too new, and might will change over time. Therefore, for now the
+ * <p><b>Experimental class!</b> This class is too new, and might will change over time. Therefore, for now
  * most methods are not exposed outside FreeMarker. The class itself and some members are exposed as they are needed for
  * configuring FreeMarker.
  *
diff --git a/src/main/java/freemarker/core/JavaScriptOrJSONCFormat.java b/src/main/java/freemarker/core/JavaScriptOrJSONCFormat.java
index 039db400..7c80c474 100644
--- a/src/main/java/freemarker/core/JavaScriptOrJSONCFormat.java
+++ b/src/main/java/freemarker/core/JavaScriptOrJSONCFormat.java
@@ -35,7 +35,7 @@ import freemarker.template.utility.StringUtil.JsStringEncQuotation;
  * {@link Configuration#Configuration(Version) incompatible_improvements}
  * {@linkplain Configuration#VERSION_2_3_32 2.3.32}.
  *
- * <p><b>Experimental class!</b> This class is too new, and might will change over time. Therefore, for now the
+ * <p><b>Experimental class!</b> This class is too new, and might will change over time. Therefore, for now
  * most methods are not exposed outside FreeMarker. The class itself and some members are exposed as they are needed for
  * configuring FreeMarker.
  *
diff --git a/src/main/java/freemarker/core/XSCFormat.java b/src/main/java/freemarker/core/XSCFormat.java
index 9d602c09..016f8f27 100644
--- a/src/main/java/freemarker/core/XSCFormat.java
+++ b/src/main/java/freemarker/core/XSCFormat.java
@@ -33,7 +33,7 @@ import freemarker.template.TemplateException;
  * XML-escaping is the duty of the auto-escaping facility of FreeMarker, and not of the {@link CFormat}, so that's not
  * done here either.)
  *
- * <p><b>Experimental class!</b> This class is too new, and might will change over time. Therefore, for now the
+ * <p><b>Experimental class!</b> This class is too new, and might will change over time. Therefore, for now
  * most methods are not exposed outside FreeMarker. The class itself and some members are exposed as they are needed for
  * configuring FreeMarker.
  *
@@ -47,7 +47,7 @@ public final class XSCFormat extends CFormat {
             "INF", "-INF", "NaN",
             "INF", "-INF", "NaN");
 
-    private static final DecimalFormat LEGACY_NUMBER_FORMAT_PROTOTYPE = (DecimalFormat) Default230CFormat.INSTANCE.getLegacyNumberFormat().clone();
+    private static final DecimalFormat LEGACY_NUMBER_FORMAT_PROTOTYPE = (DecimalFormat) Default230CFormat.LEGACY_NUMBER_FORMAT_PROTOTYPE.clone();
     static {
         DecimalFormatSymbols symbols = LEGACY_NUMBER_FORMAT_PROTOTYPE.getDecimalFormatSymbols();
         symbols.setInfinity("INF");
@@ -56,7 +56,7 @@ public final class XSCFormat extends CFormat {
     }
 
     @Override
-    NumberFormat getLegacyNumberFormat() {
+    NumberFormat getLegacyNumberFormat(Environment env) {
         return (NumberFormat) LEGACY_NUMBER_FORMAT_PROTOTYPE.clone();
     }
 
@@ -64,7 +64,7 @@ public final class XSCFormat extends CFormat {
     }
 
     @Override
-    TemplateNumberFormat getTemplateNumberFormat() {
+    TemplateNumberFormat getTemplateNumberFormat(Environment env) {
         return TEMPLATE_NUMBER_FORMAT;
     }
 
diff --git a/src/main/java/freemarker/template/Configuration.java b/src/main/java/freemarker/template/Configuration.java
index 05385ea7..540294bd 100644
--- a/src/main/java/freemarker/template/Configuration.java
+++ b/src/main/java/freemarker/template/Configuration.java
@@ -955,12 +955,14 @@ public class Configuration extends Configurable implements Cloneable, ParserConf
      *     2.3.32 (or higher):
      *     <ul>
      *       <li><p>
-     *         The number formatting of {@code ?c}, {@code ?cn}, and if the {@code "c"} and {@code "computer"}
-     *         {@link Configurable#setNumberFormat(String) number_format} changes, if the
-     *         {@link #setCFormat(CFormat) c_format} was left on its default (because the default of that changes to
-     *         {@link JavaScriptOrJSONCFormat#INSTANCE}, from {@link Default2321CFormat#INSTANCE}):
+     *         The number formatting of {@code ?c}, {@code ?cn} (and thus also of the {@code "c"}, and
+     *         {@code "computer"} {@link Configurable#setNumberFormat(String) number_format}) changes, if the
+     *         {@link #setCFormat(CFormat) c_format} setting was left on its default. The default of
+     *         {@link #setCFormat(CFormat) c_format} changes to {@link JavaScriptOrJSONCFormat#INSTANCE}, from
+     *         {@link Default2321CFormat#INSTANCE} (or from {@link Default230CFormat#INSTANCE}, depending on the
+     *         previous Incompatible Improvement value), and that's what contains the changes:</p>
      *         <ul>
-     *           <li><p>Changes affecting non-whole numbers, and for whole numbers with over 100 digits:
+     *           <li><p>Changes affecting non-whole numbers, and whole numbers with over 100 digits:
      *             Formatting is now lossless, so it potentially shows much more decimals.
      *             It now uses exponential format (like 1.2E-7 instead of 0.00000012) for numbers whose absolute value
      *             is less than 1E-6 (0.000001), and for whole numbers whose absolute value is at least 1E101 (so over
@@ -968,8 +970,8 @@ public class Configuration extends Configurable implements Cloneable, ParserConf
      *             ({@code double}/{@code Double}}, or {@code float}/{@code Float}) numbers, when their absolute value
      *             is too big for the floating point type to store them precisely (so if the intent was to store some
      *             ID-s, they are likely corrupted anyway, as the type skips some whole numbers).</p></li>
-     *           <li><p>Changes floating point infinity format from {@code INF} to {@code Infinity}, which is the
-     *             JavaScript and JSON syntax. If you generate XML with XSD-style number syntax (which uses
+     *           <li><p>Changes affecting floating point infinity: Output changes from {@code INF} to {@code Infinity},
+     *             which is the JavaScript and JSON syntax. If you generate XML with XSD-style number syntax (which uses
      *             {@code INF}), but you want the other number formatting changes (recommended), then set
      *             {@link #setCFormat(CFormat) c_format} to {@link XSCFormat#INSTANCE}/{@code "XS"}.</p></li>
      *         </ul>
diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml
index 33079432..06f82070 100644
--- a/src/manual/en_US/book.xml
+++ b/src/manual/en_US/book.xml
@@ -30064,8 +30064,8 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
                   linkend="gloss.c_format"><literal>c_format</literal></link>
                   (also settable via the <link
                   linkend="ref.directive.setting"><literal>setting</literal>
-                  directive</link>). This specifies what format to use when
-                  formatting for computer consumption, like
+                  directive</link>). This specifies what syntax to use when
+                  formatting values for computer consumption/parser, like
                   <literal>"JSON"</literal>. Most prominently, this affects
                   the <link linkend="ref_builtin_c"><literal>c</literal>
                   built-in</link>, hence the name. See valid setting values,
@@ -30170,9 +30170,9 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
                   <literal>number_format</literal> setting (also when
                   formatting with
                   <literal>?string(<replaceable>format</replaceable>)</literal>),
-                  now <quote>c</quote> can be used instead of
+                  now <literal>"c"</literal> can be used instead of
                   <quote>computer</quote>. Both has the same effect on
-                  formatting, but <quote>c</quote> is preferred from now
+                  formatting, but <literal>"c"</literal> is preferred from now
                   on.</para>
                 </listitem>
               </itemizedlist>
diff --git a/src/test/java/freemarker/core/CTemplateNumberFormatTest.java b/src/test/java/freemarker/core/CTemplateNumberFormatTest.java
index d20be03b..081f21ae 100644
--- a/src/test/java/freemarker/core/CTemplateNumberFormatTest.java
+++ b/src/test/java/freemarker/core/CTemplateNumberFormatTest.java
@@ -102,7 +102,7 @@ public class CTemplateNumberFormatTest {
 
     private void testFormat(Number n, String expectedResult) throws TemplateModelException,
         TemplateValueFormatException {
-        TemplateNumberFormat cTemplateNumberFormat = JSONCFormat.INSTANCE.getTemplateNumberFormat();
+        TemplateNumberFormat cTemplateNumberFormat = JSONCFormat.INSTANCE.getTemplateNumberFormat(null);
         String actualResult = (String) cTemplateNumberFormat.format(new SimpleNumber(n));
         assertFormatResult(n, actualResult, expectedResult);
         if (!actualResult.equals("NaN") && !actualResult.equals("0") && !actualResult.startsWith("-")) {
diff --git a/src/test/java/freemarker/core/CustomCFormat.java b/src/test/java/freemarker/core/CustomCFormat.java
index 18573cb5..86658b0d 100644
--- a/src/test/java/freemarker/core/CustomCFormat.java
+++ b/src/test/java/freemarker/core/CustomCFormat.java
@@ -37,7 +37,7 @@ class CustomCFormat extends CFormat {
             "M:INF", "M:NINF", "M:NaN");
 
     private static final DecimalFormat LEGACY_NUMBER_FORMAT_PROTOTYPE =
-            (DecimalFormat) Default230CFormat.INSTANCE.getLegacyNumberFormat().clone();
+            (DecimalFormat) Default230CFormat.LEGACY_NUMBER_FORMAT_PROTOTYPE.clone();
 
     static {
         DecimalFormatSymbols symbols = LEGACY_NUMBER_FORMAT_PROTOTYPE.getDecimalFormatSymbols();
@@ -47,12 +47,12 @@ class CustomCFormat extends CFormat {
     }
 
     @Override
-    TemplateNumberFormat getTemplateNumberFormat() {
+    TemplateNumberFormat getTemplateNumberFormat(Environment env) {
         return TEMPLATE_NUMBER_FORMAT;
     }
 
     @Override
-    NumberFormat getLegacyNumberFormat() {
+    NumberFormat getLegacyNumberFormat(Environment env) {
         return (NumberFormat) LEGACY_NUMBER_FORMAT_PROTOTYPE.clone();
     }