/*
 * 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 org.apache.sis.io.wkt;

import java.util.Arrays;
import java.util.Locale;
import java.io.Serializable;
import java.io.ObjectStreamException;
import java.text.NumberFormat;
import org.apache.sis.util.Localized;
import org.apache.sis.util.Workaround;
import org.apache.sis.util.CharSequences;
import org.apache.sis.util.resources.Errors;

import static org.apache.sis.util.ArgumentChecks.*;


/**
 * The set of symbols to use for <cite>Well Known Text</cite> (WKT) parsing and formatting.
 * The two constants defined in this class, namely {@link #SQUARE_BRACKETS} and {@link #CURLY_BRACKETS},
 * define the symbols for ISO 19162 compliant WKT formatting. Their properties are:
 *
 * <table class="sis">
 *   <caption>Standard WKT symbols</caption>
 *   <tr>
 *     <th>WKT aspect</th>
 *     <th>Standard value</th>
 *     <th>Comment</th>
 *   </tr>
 *   <tr>
 *     <td>Locale for number format:</td>
 *     <td>{@link Locale#ROOT}</td>
 *     <td></td>
 *   </tr>
 *   <tr>
 *     <td>Bracket symbols:</td>
 *     <td>{@code [}…{@code ]} or {@code (}…{@code )}</td>
 *     <td><span style="font-size: small"><b>Note:</b> the {@code […]} brackets are common in referencing WKT,
 *         while the {@code (…)} brackets are common in geometry WKT.</span></td>
 *   </tr>
 *   <tr>
 *     <td>Quote symbols:</td>
 *     <td>{@code "}…{@code "}</td>
 *     <td><span style="font-size: small"><b>Note:</b> Apache SIS accepts also {@code “…”} quotes
 *         for more readable {@code String} literals in Java code, but this is non-standard.</span></td>
 *   </tr>
 *   <tr>
 *     <td>Sequence symbols:</td>
 *     <td><code>{</code>…<code>}</code></td>
 *     <td></td>
 *   </tr>
 *   <tr>
 *     <td>Separator:</td>
 *     <td>{@code ,}</td>
 *     <td></td>
 *   </tr>
 * </table>
 *
 * Users can create their own {@code Symbols} instance for parsing or formatting a WKT with different symbols.
 *
 * @author  Martin Desruisseaux (IRD, Geomatys)
 * @version 1.0
 *
 * @see WKTFormat#getSymbols()
 * @see WKTFormat#setSymbols(Symbols)
 *
 * @since 0.4
 * @module
 */
public class Symbols implements Localized, Cloneable, Serializable {
    /**
     * For cross-version compatibility.
     */
    private static final long serialVersionUID = -1730166945430878916L;

    /**
     * Set to {@code true} if parsing and formatting of numbers in scientific notation is allowed.
     * The way to achieve that is currently a hack, because {@link NumberFormat} has no API for
     * managing that as of JDK 1.8.
     *
     * @todo See if a future version of JDK allows us to get ride of this ugly hack.
     */
    @Workaround(library = "JDK", version = "1.8")
    static final boolean SCIENTIFIC_NOTATION = true;

    /**
     * Separator between numbers in a sequence of numbers.
     * This is used for example between the coordinates of a point.
     */
    static final char NUMBER_SEPARATOR = ' ';

    /**
     * The prefix character for the value of a WKT fragment.
     */
    static final char FRAGMENT_VALUE = '$';

    /**
     * A set of symbols with values between square brackets, like {@code DATUM["WGS84"]}.
     * This instance defines:
     *
     * <ul>
     *   <li>{@link Locale#ROOT} for {@linkplain java.text.DecimalFormatSymbols decimal format symbols}.</li>
     *   <li>Square brackets by default, as in {@code DATUM["WGS84"]}, but accepting also curly brackets as in
     *       {@code DATUM("WGS84")}. Both are legal WKT.</li>
     *   <li>English quotation mark ({@code '"'}) by default, but accepting also “…” quotes
     *       for more readable {@link String} constants in Java code.</li>
     *   <li>Coma separator followed by a space ({@code ", "}).</li>
     * </ul>
     *
     * This is the most frequently used WKT format for referencing objects.
     */
    public static final Symbols SQUARE_BRACKETS = new Symbols(
            new int[] {'[', ']', '(', ')'}, new int[] {'"', '"', '“', '”'});

    /**
     * A set of symbols with values between parentheses, like {@code DATUM("WGS84")}.
     * This instance is identical to {@link #SQUARE_BRACKETS} except that the default
     * brackets are the curly ones instead than the square ones (but both are still
     * accepted at parsing time).
     *
     * <p>This format is rare with referencing objects but common with geometry objects.</p>
     */
    public static final Symbols CURLY_BRACKETS = new Symbols(
            new int[] {'(', ')', '[', ']'}, SQUARE_BRACKETS.quotes);

    /**
     * The locale of {@linkplain java.text.DecimalFormatSymbols decimal format symbols} or other symbols.
     *
     * @see #getLocale()
     */
    private Locale locale;

    /**
     * List of characters (as Unicode code points) acceptable as opening or closing brackets.
     * The array shall comply to the following restrictions:
     *
     * <ul>
     *   <li>The characters at index 0 and 1 are the preferred opening and closing brackets respectively.</li>
     *   <li>For each even index <var>i</var>, {@code brackets[i+1]} is the closing bracket matching {@code brackets[i]}.</li>
     * </ul>
     *
     * @see #getOpeningBracket(int)
     * @see #getClosingBracket(int)
     */
    private int[] brackets;

    /**
     * List of characters (as Unicode code point) used for opening or closing a quoted text.
     * The array shall comply to the following restrictions:
     *
     * <ul>
     *   <li>The characters at index 0 and 1 are the preferred opening and closing quotes respectively.</li>
     *   <li>For each even index <var>i</var>, {@code quotes[i+1]} is the closing quote matching {@code quotes[i]}.</li>
     * </ul>
     *
     * Both opening and closing quotes are usually {@code '"'}.
     */
    private int[] quotes;

    /**
     * The preferred closing quote character ({@code quotes[1]}) as a string.
     * We use the closing quote because this is the character that the parser
     * will look for determining the text end.
     *
     * @see #getQuote()
     * @see #readResolve()
     */
    private transient String quote;

    /**
     * The character (as Unicode code point) used for opening ({@code openSequence})
     * or closing ({@code closeSequence}) an array or enumeration.
     */
    private int openSequence, closeSequence;

    /**
     * The string used as a separator in a list of values. This is usually {@code ", "},
     * but may be different if a non-English locale is used for formatting numbers.
     */
    private String separator;

    /**
     * Same value than {@link #separator} but without leading and trailing spaces.
     */
    private transient String trimmedSeparator;

    /**
     * {@code true} if this instance shall be considered as immutable.
     */
    private boolean isImmutable;

    /**
     * Creates a new set of WKT symbols initialized to a copy of the given symbols.
     *
     * @param symbols  the symbols to copy.
     */
    public Symbols(final Symbols symbols) {
        ensureNonNull("symbols", symbols);
        locale           = symbols.locale;
        brackets         = symbols.brackets;
        quotes           = symbols.quotes;
        quote            = symbols.quote;
        openSequence     = symbols.openSequence;
        closeSequence    = symbols.closeSequence;
        separator        = symbols.separator;
        trimmedSeparator = symbols.trimmedSeparator;
    }

    /**
     * Constructor reserved to {@link #SQUARE_BRACKETS} and {@link #CURLY_BRACKETS} constants.
     * The given array is stored by reference - it is not cloned.
     */
    private Symbols(final int[] brackets, final int[] quotes) {
        this.locale           = Locale.ROOT;
        this.brackets         = brackets;
        this.quotes           = quotes;
        this.quote            = "\"";
        this.openSequence     = '{';
        this.closeSequence    = '}';
        this.separator        = ", ";
        this.trimmedSeparator = ",";
        this.isImmutable      = true;
    }

    /**
     * Throws an exception if this set of symbols is immutable.
     */
    final void checkWritePermission() throws UnsupportedOperationException {
        if (isImmutable) {
            throw new UnsupportedOperationException(Errors.format(Errors.Keys.UnmodifiableObject_1, "Symbols"));
        }
    }

    /**
     * Returns the default set of symbols.
     * This is currently set to {@link #SQUARE_BRACKETS}.
     *
     * @return the default set of symbols.
     */
    public static Symbols getDefault() {
        return SQUARE_BRACKETS;
    }

    /**
     * Returns the locale for formatting dates and numbers.
     * The default value is {@link Locale#ROOT}.
     *
     * <div class="section">Relationship between {@code Symbols} locale and {@code WKTFormat} locale</div>
     * The {@code WKTFormat.getLocale(Locale.DISPLAY)} property specifies the language to use when
     * formatting {@link org.opengis.util.InternationalString} instances and can be set to any value.
     * On the contrary, the {@code Locale} property of this {@code Symbols} class controls
     * the decimal format symbols and is very rarely set to an other locale than {@code Locale.ROOT}.
     *
     * @return the locale for dates and numbers.
     *
     * @see WKTFormat#getLocale(Locale.Category)
     */
    @Override
    public final Locale getLocale() {
        return locale;
    }

    /**
     * Sets the locale of decimal format symbols or other symbols.
     * Note that any non-English locale is likely to produce WKT that do not conform to ISO 19162.
     * Such WKT can be used for human reading, but not for data export.
     *
     * @param  locale  the new symbols locale.
     */
    public void setLocale(final Locale locale) {
        checkWritePermission();
        ensureNonNull("locale", locale);
        this.locale = locale;
    }

    /**
     * Implementation of {@link #matchingBracket(int)} and {@link #matchingQuote(int)}.
     */
    private static int matching(final int[] chars, final int c) {
        for (int i = 0; i < chars.length; i += 2) {
            if (chars[i] == c) {
                return chars[i + 1];
            }
        }
        return -1;
    }

    /**
     * If the given character is an opening bracket, returns the matching closing bracket.
     * Otherwise returns -1.
     */
    final int matchingBracket(final int c) {
        return matching(brackets, c);
    }

    /**
     * Returns the number of paired brackets. For example if the WKT parser accepts both the
     * {@code […]} and {@code (…)} bracket pairs, then this method returns 2.
     *
     * @return the number of bracket pairs.
     *
     * @see #getOpeningBracket(int)
     * @see #getClosingBracket(int)
     */
    public final int getNumPairedBrackets() {
        return brackets.length >>> 1;
    }

    /**
     * Returns the opening bracket character at the given index.
     * Index 0 stands for the default bracket used at formatting time.
     * All other index are for optional brackets accepted at parsing time.
     *
     * @param  index  index of the opening bracket to get, from 0 to {@link #getNumPairedBrackets()} exclusive.
     * @return the opening bracket at the given index, as a Unicode code point.
     * @throws IndexOutOfBoundsException if the given index is out of bounds.
     */
    public final int getOpeningBracket(final int index) {
        return brackets[index << 1];
    }

    /**
     * Returns the closing bracket character at the given index.
     * Index 0 stands for the default bracket used at formatting time.
     * All other index are for optional brackets accepted at parsing time.
     *
     * @param  index  index of the closing bracket to get, from 0 to {@link #getNumPairedBrackets()} exclusive.
     * @return the closing bracket at the given index, as a Unicode code point.
     * @throws IndexOutOfBoundsException if the given index is out of bounds.
     */
    public final int getClosingBracket(final int index) {
        return brackets[(index << 1) | 1];
    }

    /**
     * Sets the opening and closing brackets to the given pairs.
     * Each string shall contain exactly two code points (usually two characters).
     * The first code point is taken as the opening bracket, and the second code point as the closing bracket.
     *
     * <div class="note"><b>Example:</b>
     * The following code will instruct the WKT formatter to use the (…) pair of brackets at formatting time,
     * but still accept the more common […] pair of brackets at parsing time:
     *
     * {@preformat java
     *   symbols.setPairedBrackets("()", "[]");
     * }</div>
     *
     * @param  preferred     the preferred pair of opening and closing quotes, used at formatting time.
     * @param  alternatives  alternative pairs of opening and closing quotes accepted at parsing time.
     */
    public void setPairedBrackets(final String preferred, final String... alternatives) {
        checkWritePermission();
        brackets = toCodePoints(preferred, alternatives);
    }

    /**
     * If the given character is an opening quote, returns the matching closing quote.
     * Otherwise returns -1.
     */
    final int matchingQuote(final int c) {
        return matching(quotes, c);
    }

    /**
     * Returns the number of paired quotes. For example if the WKT parser accepts both the
     * {@code "…"} and {@code “…”} quote pairs, then this method returns 2.
     *
     * @return the number of quote pairs.
     *
     * @see #getOpeningQuote(int)
     * @see #getClosingQuote(int)
     */
    public final int getNumPairedQuotes() {
        return quotes.length >>> 1;
    }

    /**
     * Returns the opening quote character at the given index.
     * Index 0 stands for the default quote used at formatting time, which is usually {@code '"'}.
     * All other index are for optional quotes accepted at parsing time.
     *
     * @param  index  index of the opening quote to get, from 0 to {@link #getNumPairedQuotes()} exclusive.
     * @return the opening quote at the given index, as a Unicode code point.
     * @throws IndexOutOfBoundsException if the given index is out of bounds.
     */
    public final int getOpeningQuote(final int index) {
        return quotes[index << 1];
    }

    /**
     * Returns the closing quote character at the given index.
     * Index 0 stands for the default quote used at formatting time, which is usually {@code '"'}.
     * All other index are for optional quotes accepted at parsing time.
     *
     * @param  index  index of the closing quote to get, from 0 to {@link #getNumPairedQuotes()} exclusive.
     * @return the closing quote at the given index, as a Unicode code point.
     * @throws IndexOutOfBoundsException if the given index is out of bounds.
     */
    public final int getClosingQuote(final int index) {
        return quotes[(index << 1) | 1];
    }

    /**
     * Returns the preferred closing quote character as a string. This is the quote to double if it
     * appears in a Unicode string to format. We check for the closing quote because this is the one
     * that the parser will look for determining the text end.
     */
    final String getQuote() {
        return quote;
    }

    /**
     * Sets the opening and closing quotes to the given pairs.
     * Each string shall contain exactly two code points (usually two characters).
     * The first code point is taken as the opening quote, and the second code point as the closing quote.
     *
     * <div class="note"><b>Example:</b>
     * The following code will instruct the WKT formatter to use the prettier “…” quotation marks at formatting time
     * (especially useful for {@code String} constants in Java code), but still accept the standard "…" quotation marks
     * at parsing time:
     *
     * {@preformat java
     *   symbols.setPairedQuotes("“”", "\"\"");
     * }</div>
     *
     * @param  preferred     the preferred pair of opening and closing quotes, used at formatting time.
     * @param  alternatives  alternative pairs of opening and closing quotes accepted at parsing time.
     */
    public void setPairedQuotes(final String preferred, final String... alternatives) {
        checkWritePermission();
        quotes = toCodePoints(preferred, alternatives);
        quote = preferred.substring(Character.charCount(quotes[0])).trim();
    }

    /**
     * Packs the given pairs of bracket or quotes in a single array of code points.
     * This method also verifies arguments validity.
     */
    private static int[] toCodePoints(final String preferred, final String[] alternatives) {
        ensureNonEmpty("preferred", preferred);
        final int n = (alternatives != null) ? alternatives.length : 0;
        final int[] array = new int[(n+1) * 2];
        String name = "preferred";
        String pair = preferred;
        int i=0, j=0;
        while (true) {
            if (pair.codePointCount(0, pair.length()) != 2) {
                throw new IllegalArgumentException(Errors.format(Errors.Keys.IllegalArgumentValue_2, name, pair));
            }
            final int c = pair.codePointAt(0);
            ensureValidQuoteOrBracket(name, array[j++] = c);
            ensureValidQuoteOrBracket(name, array[j++] = pair.codePointAt(Character.charCount(c)));
            if (i >= n) {
                break;
            }
            ensureNonNullElement(name = "alternatives", i, pair = alternatives[i++]);
        }
        return array;
    }

    /**
     * Ensures that the given code point is a valid Unicode code point but not a Unicode identifier part.
     */
    private static void ensureValidQuoteOrBracket(final String name, final int code) {
        ensureValidUnicodeCodePoint(name, code);
        if (Character.isUnicodeIdentifierPart(code) || Character.isSpaceChar(code) || code == FRAGMENT_VALUE) {
            throw new IllegalArgumentException(Errors.format(Errors.Keys.IllegalCharacter_2,
                    name, String.valueOf(Character.toChars(code))));
        }
    }

    /**
     * Returns the character used for opening a sequence of values.
     * This is usually <code>'{'</code>.
     *
     * @return the character used for opening a sequence of values, as a Unicode code point.
     */
    public final int getOpenSequence() {
        return openSequence;
    }

    /**
     * Returns the character used for closing a sequence of values.
     * This is usually <code>'}'</code>.
     *
     * @return the character used for closing a sequence of values, as a Unicode code point.
     */
    public final int getCloseSequence() {
        return closeSequence;
    }

    /**
     * Sets the characters used for opening and closing a sequence of values.
     *
     * @param  openSequence   the character for opening a sequence of values, as a Unicode code point.
     * @param  closeSequence  the character for closing a sequence of values, as a Unicode code point.
     */
    public void setSequenceBrackets(final int openSequence, final int closeSequence) {
        checkWritePermission();
        ensureValidQuoteOrBracket("openSequence",  openSequence);
        ensureValidQuoteOrBracket("closeSequence", closeSequence);
        this.openSequence  = openSequence;
        this.closeSequence = closeSequence;
    }

    /**
     * Returns the string used as a separator in a list of values. This is usually {@code ", "},
     * but may be different if a non-English locale is used for formatting numbers.
     *
     * @return the string used as a separator in a list of values.
     */
    public final String getSeparator() {
        return separator;
    }

    /**
     * Sets the string to use as a separator in a list of values.
     * The given string will be used "as-is" at formatting time,
     * but leading and trailing spaces will be ignored at parsing time.
     *
     * @param  separator  the new string to use as a separator in a list of values.
     */
    public void setSeparator(final String separator) {
        checkWritePermission();
        final String s = CharSequences.trimWhitespaces(separator.trim());
        ensureNonEmpty("separator", s);
        this.separator = separator;
        trimmedSeparator = s;
    }

    /**
     * Returns the separator without trailing spaces.
     */
    final String trimmedSeparator() {
        return trimmedSeparator;
    }

    /**
     * Returns the value of {@link #getSeparator()} without trailing spaces,
     * followed by the system line separator.
     */
    final String separatorNewLine() {
        final String separator = getSeparator();
        return separator.substring(0, CharSequences.skipTrailingWhitespaces(separator, 0, separator.length()))
                .concat(System.lineSeparator());
    }

    /**
     * Creates a new number format to use for parsing and formatting. Each {@link WKTFormat} will
     * create its own instance, since {@link NumberFormat}s are not guaranteed to be thread-safe.
     *
     * <div class="section">Scientific notation</div>
     * The {@link NumberFormat} created here does not use scientific notation. This is okay for many
     * WKT formatting purpose since Earth ellipsoid axis lengths in metres are large enough for trigging
     * scientific notation, while we want to express them as normal numbers with centimetre precision.
     * However this is problematic for small numbers like 1E-5. Callers may need to adjust the precision
     * depending on the kind of numbers (length or angle) to format.
     */
    final NumberFormat createNumberFormat() {
        final NumberFormat format = NumberFormat.getNumberInstance(locale);
        format.setGroupingUsed(false);
        return format;
    }

    /**
     * Returns {@code true} if the formatter should use scientific notation for the given value.
     * We use scientific notation if the number magnitude is too high or too low. The threshold values used here
     * may be different than the threshold values used in the standard {@link StringBuilder#append(double)} method.
     * In particular, we use a higher threshold for large numbers because ellipsoid axis lengths are above the JDK
     * threshold when the axis length is given in feet (about 2.1E+7) while we still want to format them as usual numbers.
     *
     * Note that we perform this special formatting only if the 'NumberFormat' is not localized (which is the usual case).
     *
     * @param  abs  the absolute value of the number to format.
     */
    final boolean useScientificNotation(final double abs) {
        return SCIENTIFIC_NOTATION && (abs < 1E-3 || abs >= 1E+9) && locale == Locale.ROOT;
    }

    /**
     * Returns {@code true} if the given WKT contains at least one instance of the given element.
     * Invoking this method is equivalent to invoking {@link String#contains(CharSequence)} except
     * for the following:
     *
     * <ul>
     *   <li>The search is case-insensitive.</li>
     *   <li>Characters between {@linkplain #getOpeningQuote(int) opening quotes} and
     *       {@linkplain #getClosingQuote(int) closing quotes} are ignored.</li>
     *   <li>The element found in the given WKT can not be preceded by other
     *       {@linkplain Character#isUnicodeIdentifierPart(int) Unicode identifier characters}.</li>
     *   <li>The element found in the given WKT must be followed, ignoring space, by an
     *       {@linkplain #getOpeningBracket(int) opening bracket}.</li>
     * </ul>
     *
     * The purpose of this method is to guess some characteristics about the encoded object without
     * the cost of a full WKT parsing.
     *
     * @param  wkt      the WKT to inspect.
     * @param  element  the element to search for.
     * @return {@code true} if the given WKT contains at least one instance of the given element.
     */
    public boolean containsElement(final CharSequence wkt, final String element) {
        ensureNonNull("wkt", wkt);
        ensureNonEmpty("element", element);
        if (!CharSequences.isUnicodeIdentifier(element)) {
            throw new IllegalArgumentException(Errors.format(Errors.Keys.NotAUnicodeIdentifier_1, element));
        }
        return containsElement(wkt, element, 0);
    }

    /**
     * Returns {@code true} if the given WKT contains at least one instance of the {@code AXIS[…]} element.
     * Invoking this method is equivalent to invoking
     * <code>{@linkplain #containsElement(CharSequence, String) containsElement}(wkt, "AXIS")</code>.
     *
     * <div class="section">Use case</div>
     * The check for axis elements is of particular interest because the axis order is a frequent cause
     * of confusion when processing geographic data. Some applications just ignore any declared axis order
     * in favor of their own hard-coded (<var>longitude</var>, <var>latitude</var>) axis order.
     * Consequently, the presence of {@code AXIS[…]} elements in a WKT is an indication that the encoded
     * object may not be understood as intended by some external software products.
     *
     * @param  wkt  the WKT to inspect.
     * @return {@code true} if the given WKT contains at least one instance of the {@code AXIS[…]} element.
     */
    public boolean containsAxis(final CharSequence wkt) {
        ensureNonNull("wkt", wkt);
        return containsElement(wkt, "AXIS", 0);
    }

    /**
     * Implementation of {@link #containsElement(CharSequence, String)} without verification of argument validity.
     *
     * @param  wkt      the WKT to inspect.
     * @param  element  the element to search. Must contains only uppercase letters.
     * @param  offset   the index to start the search from.
     */
    private boolean containsElement(final CharSequence wkt, final String element, int offset) {
        final int[] quotes = this.quotes;
        final int length = wkt.length();
        boolean isQuoting = false;
        int closeQuote = 0;
        while (offset < length) {
            int c = Character.codePointAt(wkt, offset);
            if (closeQuote != 0) {
                if (c == closeQuote) {
                    isQuoting = false;
                }
            } else for (int i=0; i<quotes.length; i+=2) {
                if (c == quotes[i]) {
                    closeQuote = quotes[i | 1];
                    isQuoting = true;
                    break;
                }
            }
            if (!isQuoting && Character.isUnicodeIdentifierStart(c)) {
                /*
                 * Found the beginning of a Unicode identifier.
                 * Check if this is the identifier we were looking for.
                 */
                if (CharSequences.regionMatches(wkt, offset, element, true)) {
                    offset = CharSequences.skipLeadingWhitespaces(wkt, offset + element.length(), length);
                    if (offset >= length) {
                        break;
                    }
                    c = Character.codePointAt(wkt, offset);
                    if (matchingBracket(c) >= 0) {
                        return true;
                    }
                } else {
                    /*
                     * Not the identifier we were looking for. Skip the whole identifier.
                     */
                    do {
                        offset += Character.charCount(c);
                        if (offset >= length) {
                            return false;
                        }
                        c = Character.codePointAt(wkt, offset);
                    } while (Character.isUnicodeIdentifierPart(c));
                }
            }
            offset += Character.charCount(c);
        }
        return false;
    }

    /**
     * Returns an immutable copy of this set of symbols, or {@code this} if this instance is already immutable.
     */
    final Symbols immutable() {
        if (isImmutable) {
            return this;
        }
        final Symbols clone = clone();
        clone.isImmutable = true;
        return clone;
    }

    /**
     * Returns a clone of this {@code Symbols}.
     *
     * @return a clone of this {@code Symbols}.
     */
    @Override
    public Symbols clone() {
        final Symbols clone;
        try {
            clone = (Symbols) super.clone();
        } catch (CloneNotSupportedException e) {
            throw new AssertionError(e);
        }
        /*
         * No needs to copy the arrays, because their content are never modified.
         * Instead, the setter methods create new arrays.
         */
        clone.isImmutable = false;
        return clone;
    }

    /**
     * Compares this {@code Symbols} with the given object for equality.
     *
     * @param  other  the object to compare with this {@code Symbols}.
     * @return {@code true} if both objects are equal.
     */
    @Override
    public boolean equals(final Object other) {
        if (other instanceof Symbols) {
            final Symbols that = (Symbols) other;
            return Arrays.equals(brackets, that.brackets) &&
                   Arrays.equals(quotes, that.quotes) &&
                   // no need to compare 'quote' because it is computed from 'quotes'.
                   openSequence  == that.openSequence &&
                   closeSequence == that.closeSequence &&
                   separator.equals(that.separator) &&
                   locale.equals(that.locale);
        }
        return false;
    }

    /**
     * Returns a hash code value for this object.
     *
     * @return a hash code value.
     */
    @Override
    public int hashCode() {
        return Arrays.deepHashCode(new Object[] {brackets, quotes, openSequence, closeSequence, separator, locale});
    }

    /**
     * Invoked on deserialization for replacing the deserialized instance by the constant instance.
     * This method also opportunistically recompute the {@link #quote} field if no replacement is done.
     *
     * @return the object to use after deserialization.
     * @throws ObjectStreamException required by specification but should never be thrown.
     */
    final Object readResolve() throws ObjectStreamException {
        if (isImmutable) {
            if (equals(SQUARE_BRACKETS)) return SQUARE_BRACKETS;
            if (equals(CURLY_BRACKETS))  return CURLY_BRACKETS;
        }
        quote = String.valueOf(Character.toChars(quotes[1]));
        trimmedSeparator = CharSequences.trimWhitespaces(separator.trim());
        return this;
    }
}
