Ciao Sandro, Can you run the tests with debug on (hint: change setting in “build.properties” file) to see the specific failure in VersionTest, please?! It works fine on my laptop with Java 11+28
Thanks, ~Roger > On Oct 31, 2023, at 12:15 PM, smart...@apache.org wrote: > > Modified: pivot/trunk/core/src/org/apache/pivot/serialization/MacroReader.java > URL: > https://urldefense.proofpoint.com/v2/url?u=http-3A__svn.apache.org_viewvc_pivot_trunk_core_src_org_apache_pivot_serialization_MacroReader.java-3Frev-3D1913470-26r1-3D1913469-26r2-3D1913470-26view-3Ddiff&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=ciFvnfAumCmyGtAjZc8B1orUjkLV7Rx6BdJyk5LK39Y&e= > ============================================================================== > --- pivot/trunk/core/src/org/apache/pivot/serialization/MacroReader.java > (original) > +++ pivot/trunk/core/src/org/apache/pivot/serialization/MacroReader.java Tue > Oct 31 19:15:47 2023 > @@ -1,249 +1,249 @@ > -/* > - * 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 > - * > - * > https://urldefense.proofpoint.com/v2/url?u=http-3A__www.apache.org_licenses_LICENSE-2D2.0&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=JsT1BEqkGt4UKR-IgCZyv52z9E_LJmf1P7aQ1JdjYPc&e= > - * > - * 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.pivot.serialization; > - > -import java.io.IOException; > -import java.io.Reader; > -import java.util.ArrayDeque; > -import java.util.HashMap; > -import java.util.Map; > -import java.util.Queue; > - > - > -/** > - * This is a {@link Reader} that can be instantiated inline with any other > - * {@code Reader} to provide macro capabilities. > - * <p> We recognize <code>#define <i>NAME value</i></code> as definitions > - * as well as <code>#undef <i>NAME</i></code> to remove a previous > definition. > - * <p> The macro name must correspond to the Unicode naming conventions (see > - * {@link Character#isUnicodeIdentifierStart} and {@link > Character#isUnicodeIdentifierPart}). > - * <p> Macro substitutions are recognized as <code>${<i>NAME</i>}</code> > anywhere > - * in the underlying stream. Nested macros are supported, and are expanded > at the > - * point of definition, if defined, or at the point of expansion if defined > later. > - */ > -public final class MacroReader extends Reader { > - /** The input reader we are mapping. */ > - private Reader in; > - > - /** The map of our defined variables and their values. */ > - private Map<String, String> variableMap = new HashMap<>(); > - > - /** The lookahead queue, set either by one-character lookahead (such as > - * while recognizing "$NAME") or from macro expansion. > - */ > - private Queue<Integer> lookaheadQueue = new ArrayDeque<>(); > - > - /** The previous character read. */ > - private int lastCh = -1; > - > - /** > - * Construct a new macro reader on top of the given reader. > - * @param reader The input reader we are going to wrap. > - */ > - public MacroReader(final Reader reader) { > - > https://urldefense.proofpoint.com/v2/url?u=http-3A__this.in&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=tCqtw4Zer173jvAQ7R3582iktLGQSj7DhNxuOBhQHgs&e= > = reader; > - } > - > - @Override > - public void close() throws IOException { > - in.close(); > - } > - > - /** > - * Add the given character to the lookahead queue for reprocessing. > - * @param ch The character to queue. > - */ > - private void queue(final int ch) { > - if (ch != -1) { > - lookaheadQueue.add(ch); > - } > - } > - > - /** > - * Add all the characters of the given character sequence to the > - * lookahead queue for reprocessing. > - * @param seq The character sequence to be queued up again. > - */ > - private void queue(final CharSequence seq) { > - for (int i = 0; i < seq.length(); i++) { > - > https://urldefense.proofpoint.com/v2/url?u=http-3A__lookaheadQueue.ad&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=pYi5v2-hMn6hIVIK_DM3utri2qzyhPFrezlcvGYEbDc&e=d((int)https://urldefense.proofpoint.com/v2/url?u=http-3A__seq.ch&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=JFNS-28y5JdxsMAhVt_9dTHtoCZNnTwZvNNe5ZHKA4o&e=arAt(i)); > - } > - } > - > - /** > - * Parse out the next word in the stream (according to Unicode > - * Identifier semantics) as the macro name, skipping leading whitespace. > - * @return The next parsed "word" string. > - * @throws IOException for errors reading the stream. > - */ > - private String getNextWord() throws IOException { > - StringBuilder buf = new StringBuilder(); > - int ch; > - do { > - ch = getNextChar(true); > - } while (ch != -1 > &&https://urldefense.proofpoint.com/v2/url?u=http-3A__Character.is&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=GmS-qX7m3mzU6X3ggDRqu2PkDWhJ5_v7-XJsl8589gI&e=Whitespace(ch)); > - > - if (ch != -1) { > - buf.append((char) ch); > - while ((ch = getNextChar(true)) != -1 > - && ((buf.length() == 0 > &&https://urldefense.proofpoint.com/v2/url?u=http-3A__Character.is&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=GmS-qX7m3mzU6X3ggDRqu2PkDWhJ5_v7-XJsl8589gI&e=UnicodeIdentifierStart(ch)) > - || (buf.length() > 0 && > Character.isUnicodeIdentifierPart(ch)))) { > - buf.append((char) ch); > - } > - > - // Re-queue the character that terminated the word > - queue(ch); > - } > - return buf.toString(); > - } > - > - /** > - * Get the next character in the input stream, either from the > - * {@link #lookaheadQueue} if anything is queued, or by reading > - * from the underlying {@link Reader}. > - * <p> This is the heart of the processing that handles both > - * macro definition and expansion. > - * @param handleMacros set to {@code false} only when > - * invoking this method recursively > - * to ignore unknown macro commands > - * or undefined macros > - * @return The next character in the stream. > - * @throws IOException if there are errors reading the stream. > - */ > - private int getNextChar(final boolean handleMacros) throws IOException { > - int ret = -1; > - Integer queuedChar = lookaheadQueue.poll(); > - if (queuedChar != null) { > - ret = queuedChar.intValue(); > - } else { > - ret = in.read(); > - } > - > - if (handleMacros) { > - int ch; > - > - // Check for macro define or undefine (starting with "#" > - // at the beginning of a line) (unless we're recursing to > - // skip an unknown declaration keyword). > - if (ret == '#' && lastCh == '\n') { > - String keyword = getNextWord(); > - > - if (keyword.equalsIgnoreCase("undef")) { > - String name = getNextWord(); > - > - do { > - ch = getNextChar(false); > - } while (ch != -1 && ch != '\n'); > - > - variableMap.remove(name); > - > - return getNextChar(true); > - } else if (!keyword.equalsIgnoreCase("define")) { > - // Basically ignore any commands we don't understand > - // by simply queueing the text back to be read again > - // but with the flag set to ignore this command (so > - // we don't get into infinite recursion!) > - ch = getNextChar(false); > - queue(ret); > - queue(keyword); > - queue(ch); > - > - return getNextChar(false); > - } > - > - // Define a macro > - String name = getNextWord(); > - StringBuilder buf = new StringBuilder(); > - > - // Skip whitespace after the macro name > - do { > - ch = getNextChar(true); > - } while (ch != -1 && Character.isWhitespace(ch) && ch != > '\\' && ch != '\n'); > - > - queue(ch); > - > - do { > - while ((ch = getNextChar(true)) != -1 && ch != '\\' && > ch != '\n') { > - buf.append((char) ch); > - } > - > - // Check for line continuation character > - if (ch == '\\') { > - int next = getNextChar(true); > - if (next == '\n') { > - buf.append((char) next); > - } else { > - buf.append((char) ch); > - buf.append((char) next); > - } > - } > - } while (ch != -1 && ch != '\n'); > - > - variableMap.put(name, buf.toString()); > - > - return getNextChar(true); > - } else if (ret == '$') { > - // Check for macro expansion > - // Note: this allows for nested expansion > - int next = getNextChar(true); > - if (next == '{') { > - StringBuilder buf = new StringBuilder(); > - > - while ((ch = getNextChar(true)) != -1 && ch != '}') { > - buf.append((char) ch); > - } > - > - String expansion = variableMap.get(buf.toString()); > - if (expansion == null) { > - // If the macro is undefined, then we put back the > - // original text to be read again, but without > expansion > - queue(ret); > - queue(next); > - queue(buf); > - queue(ch); > - > - ret = getNextChar(false); > - } else { > - queue(expansion); > - > - // By allowing expansion here, we get recursive > expansion > - ret = getNextChar(true); > - } > - } else { > - queue(next); > - } > - } > - } > - > - return (lastCh = ret); > - } > - > - @Override > - public int read(final char[] cbuf, final int off, final int len) throws > IOException { > - int read = -1; > - for (int i = 0; i < len; i++) { > - int ch = getNextChar(true); > - if (ch == -1) { > - break; > - } > - read = i; > - cbuf[off + i] = (char) ch; > - } > - return (read == -1) ? read : read + 1; > - } > - > -} > +/* > + * 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 > + * > + * > https://urldefense.proofpoint.com/v2/url?u=http-3A__www.apache.org_licenses_LICENSE-2D2.0&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=JsT1BEqkGt4UKR-IgCZyv52z9E_LJmf1P7aQ1JdjYPc&e= > + * > + * 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. > + */ > +packagehttps://urldefense.proofpoint.com/v2/url?u=http-3A__org.apache.pivot.se&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=ATZhVF6ad-EMaY4FguU2C3Dplmho6Hh1ij2eFjO8OFY&e=rialization; > + > +importhttps://urldefense.proofpoint.com/v2/url?u=http-3A__java.io.IO&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=oeYi21_yPbOgOr5G2F7K7QwTFgsercN2xlzdkFMDFUQ&e=Exception; > +importhttps://urldefense.proofpoint.com/v2/url?u=http-3A__java.io.Re&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=PYI6xIIo5tlzwqhaxpg8a56bGh3pI0TectedoYgkq4o&e=ader; > +importhttps://urldefense.proofpoint.com/v2/url?u=http-3A__java.util.Ar&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=joMa2RR4U6PRS84V6VJPewd6_XNoEH0q6NFXTHG2qIk&e=rayDeque; > +import java.util.HashMap; > +importhttps://urldefense.proofpoint.com/v2/url?u=http-3A__java.util.Ma&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=mR7BaSdU-ZSpplp62NWG2zbcuyfYZYpPEGWLtGSl7Y4&e=p; > +import java.util.Queue; > + > + > +/** > + * This is a {@link Reader} that can be instantiated inline with any other > + * {@code Reader} to provide macro capabilities. > + * <p> We recognize <code>#define <i>NAME value</i></code> as definitions > + * as well as <code>#undef <i>NAME</i></code> to remove a previous > definition. > + * <p> The macro name must correspond to the Unicode naming conventions (see > + * {@link Character#isUnicodeIdentifierStart} and {@link > Character#isUnicodeIdentifierPart}). > + * <p> Macro substitutions are recognized as <code>${<i>NAME</i>}</code> > anywhere > + * in the underlying stream. Nested macros are supported, and are expanded > at the > + * point of definition, if defined, or at the point of expansion if defined > later. > + */ > +public final class MacroReader extends Reader { > + /** The input reader we are mapping. */ > + private Reader in; > + > + /** The map of our defined variables and their values. */ > + private Map<String, String> variableMap = new HashMap<>(); > + > + /** The lookahead queue, set either by one-character lookahead (such as > + * while recognizing "$NAME") or from macro expansion. > + */ > + private Queue<Integer> lookaheadQueue = new ArrayDeque<>(); > + > + /** The previous character read. */ > + private int lastCh = -1; > + > + /** > + * Construct a new macro reader on top of the given reader. > + * @param reader The input reader we are going to wrap. > + */ > + public MacroReader(final Reader reader) { > + > https://urldefense.proofpoint.com/v2/url?u=http-3A__this.in&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=tCqtw4Zer173jvAQ7R3582iktLGQSj7DhNxuOBhQHgs&e= > = reader; > + } > + > + @Override > + public void close() throws IOException { > + in.close(); > + } > + > + /** > + * Add the given character to the lookahead queue for reprocessing. > + * @param ch The character to queue. > + */ > + private void queue(final int ch) { > + if (ch != -1) { > + lookaheadQueue.add(ch); > + } > + } > + > + /** > + * Add all the characters of the given character sequence to the > + * lookahead queue for reprocessing. > + * @param seq The character sequence to be queued up again. > + */ > + private void queue(final CharSequence seq) { > + for (int i = 0; i < seq.length(); i++) { > + > https://urldefense.proofpoint.com/v2/url?u=http-3A__lookaheadQueue.ad&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=pYi5v2-hMn6hIVIK_DM3utri2qzyhPFrezlcvGYEbDc&e=d((int)https://urldefense.proofpoint.com/v2/url?u=http-3A__seq.ch&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=JFNS-28y5JdxsMAhVt_9dTHtoCZNnTwZvNNe5ZHKA4o&e=arAt(i)); > + } > + } > + > + /** > + * Parse out the next word in the stream (according to Unicode > + * Identifier semantics) as the macro name, skipping leading whitespace. > + * @return The next parsed "word" string. > + * @throws IOException for errors reading the stream. > + */ > + private String getNextWord() throws IOException { > + StringBuilder buf = new StringBuilder(); > + int ch; > + do { > + ch = getNextChar(true); > + } while (ch != -1 > &&https://urldefense.proofpoint.com/v2/url?u=http-3A__Character.is&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=GmS-qX7m3mzU6X3ggDRqu2PkDWhJ5_v7-XJsl8589gI&e=Whitespace(ch)); > + > + if (ch != -1) { > + buf.append((char) ch); > + while ((ch = getNextChar(true)) != -1 > + && ((buf.length() == 0 > &&https://urldefense.proofpoint.com/v2/url?u=http-3A__Character.is&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=GmS-qX7m3mzU6X3ggDRqu2PkDWhJ5_v7-XJsl8589gI&e=UnicodeIdentifierStart(ch)) > + || (buf.length() > 0 && > Character.isUnicodeIdentifierPart(ch)))) { > + buf.append((char) ch); > + } > + > + // Re-queue the character that terminated the word > + queue(ch); > + } > + return buf.toString(); > + } > + > + /** > + * Get the next character in the input stream, either from the > + * {@link #lookaheadQueue} if anything is queued, or by reading > + * from the underlying {@link Reader}. > + * <p> This is the heart of the processing that handles both > + * macro definition and expansion. > + * @param handleMacros set to {@code false} only when > + * invoking this method recursively > + * to ignore unknown macro commands > + * or undefined macros > + * @return The next character in the stream. > + * @throws IOException if there are errors reading the stream. > + */ > + private int getNextChar(final boolean handleMacros) throws IOException { > + int ret = -1; > + Integer queuedChar = lookaheadQueue.poll(); > + if (queuedChar != null) { > + ret = queuedChar.intValue(); > + } else { > + ret = in.read(); > + } > + > + if (handleMacros) { > + int ch; > + > + // Check for macro define or undefine (starting with "#" > + // at the beginning of a line) (unless we're recursing to > + // skip an unknown declaration keyword). > + if (ret == '#' && lastCh == '\n') { > + String keyword = getNextWord(); > + > + if (keyword.equalsIgnoreCase("undef")) { > + String name = getNextWord(); > + > + do { > + ch = getNextChar(false); > + } while (ch != -1 && ch != '\n'); > + > + variableMap.remove(name); > + > + return getNextChar(true); > + } else if (!keyword.equalsIgnoreCase("define")) { > + // Basically ignore any commands we don't understand > + // by simply queueing the text back to be read again > + // but with the flag set to ignore this command (so > + // we don't get into infinite recursion!) > + ch = getNextChar(false); > + queue(ret); > + queue(keyword); > + queue(ch); > + > + return getNextChar(false); > + } > + > + // Define a macro > + String name = getNextWord(); > + StringBuilder buf = new StringBuilder(); > + > + // Skip whitespace after the macro name > + do { > + ch = getNextChar(true); > + } while (ch != -1 && Character.isWhitespace(ch) && ch != > '\\' && ch != '\n'); > + > + queue(ch); > + > + do { > + while ((ch = getNextChar(true)) != -1 && ch != '\\' && > ch != '\n') { > + buf.append((char) ch); > + } > + > + // Check for line continuation character > + if (ch == '\\') { > + int next = getNextChar(true); > + if (next == '\n') { > + buf.append((char) next); > + } else { > + buf.append((char) ch); > + buf.append((char) next); > + } > + } > + } while (ch != -1 && ch != '\n'); > + > + variableMap.put(name, buf.toString()); > + > + return getNextChar(true); > + } else if (ret == '$') { > + // Check for macro expansion > + // Note: this allows for nested expansion > + int next = getNextChar(true); > + if (next == '{') { > + StringBuilder buf = new StringBuilder(); > + > + while ((ch = getNextChar(true)) != -1 && ch != '}') { > + buf.append((char) ch); > + } > + > + String expansion = variableMap.get(buf.toString()); > + if (expansion == null) { > + // If the macro is undefined, then we put back the > + // original text to be read again, but without > expansion > + queue(ret); > + queue(next); > + queue(buf); > + queue(ch); > + > + ret = getNextChar(false); > + } else { > + queue(expansion); > + > + // By allowing expansion here, we get recursive > expansion > + ret = getNextChar(true); > + } > + } else { > + queue(next); > + } > + } > + } > + > + return (lastCh = ret); > + } > + > + @Override > + public int read(final char[] cbuf, final int off, final int len) throws > IOException { > + int read = -1; > + for (int i = 0; i < len; i++) { > + int ch = getNextChar(true); > + if (ch == -1) { > + break; > + } > + read = i; > + cbuf[off + i] = (char) ch; > + } > + return (read == -1) ? read : read + 1; > + } > + > +} > > Propchange: > pivot/trunk/core/src/org/apache/pivot/serialization/MacroReader.java > ------------------------------------------------------------------------------ > svn:eol-style = native > > Modified: > pivot/trunk/core/src/org/apache/pivot/text/AttributedStringCharacterIterator.java > URL: > https://urldefense.proofpoint.com/v2/url?u=http-3A__svn.apache.org_viewvc_pivot_trunk_core_src_org_apache_pivot_text_AttributedStringCharacterIterator.java-3Frev-3D1913470-26r1-3D1913469-26r2-3D1913470-26view-3Ddiff&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=iuKbUu0Mv7cmgUXHAkVEc88Rk4y7x51cOesTA0Bsw40&e= > ============================================================================== > --- > pivot/trunk/core/src/org/apache/pivot/text/AttributedStringCharacterIterator.java > (original) > +++ > pivot/trunk/core/src/org/apache/pivot/text/AttributedStringCharacterIterator.java > Tue Oct 31 19:15:47 2023 > @@ -1,243 +1,243 @@ > -/* > - * 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 > - * > - * > https://urldefense.proofpoint.com/v2/url?u=http-3A__www.apache.org_licenses_LICENSE-2D2.0&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=JsT1BEqkGt4UKR-IgCZyv52z9E_LJmf1P7aQ1JdjYPc&e= > - * > - * 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.pivot.text; > - > -importhttps://urldefense.proofpoint.com/v2/url?u=http-3A__java.awt.Fo&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=OZxVZJZl4H19qbUs6rikjbOkM8DTkgSDJnEzyjP0rtM&e=nt; > -importhttps://urldefense.proofpoint.com/v2/url?u=http-3A__java.awt.fo&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=IV_PjRYqtWpHqeIg5Cc6ZMTspNotn1khu_P89K5R7ag&e=nt.TextAttribute; > -importhttps://urldefense.proofpoint.com/v2/url?u=http-3A__java.text.At&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=EWntGXPIZXe03Lvd5lwSge_1FACdz_K7jowKGcK_6k0&e=tributedCharacterIterator; > -importhttps://urldefense.proofpoint.com/v2/url?u=http-3A__java.text.At&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=EWntGXPIZXe03Lvd5lwSge_1FACdz_K7jowKGcK_6k0&e=tributedString; > -importhttps://urldefense.proofpoint.com/v2/url?u=http-3A__java.util.Ma&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=mR7BaSdU-ZSpplp62NWG2zbcuyfYZYpPEGWLtGSl7Y4&e=p; > -importhttps://urldefense.proofpoint.com/v2/url?u=http-3A__java.util.Se&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=vUJKWMT0ARE8Fhtigxy__s6M3MgRl_loNn8HbKDnCJE&e=t; > -import org.apache.pivot.util.Utils; > - > - > -/** > - * A sequence of text along with associated attributes, backed by a > - * {@link AttributedString}, which itself implements all of these > - * methods. > - */ > -public class AttributedStringCharacterIterator implements > AttributedCharacterIterator { > - private AttributedString storage = null; > - private int length = 0; > - > privatehttps://urldefense.proofpoint.com/v2/url?u=http-3A__AttributedCharacterIterator.At&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=2j7YAIPlD2vCpGlxfw8IECIrWpSpFevu2PwwtpPS1X4&e=tribute[] > attributes = null; > - private AttributedCharacterIterator iterator = null; > - > - public AttributedStringCharacterIterator() { > - > https://urldefense.proofpoint.com/v2/url?u=http-3A__this.st&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=SWQyw1dw-WtgsC4cQDrXq_05ZKk1drrzGTR1SnqhxhU&e=orage > = new AttributedString(""); > - this.length = 0; > - } > - > - public AttributedStringCharacterIterator(String text) { > - > https://urldefense.proofpoint.com/v2/url?u=http-3A__Utils.ch&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=gEZ93Gnwcla9SQ3n7yUYJKJX2agFKOan6gqtdwIZ6NA&e=eckNull(text, > "text"); > - > https://urldefense.proofpoint.com/v2/url?u=http-3A__this.st&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=SWQyw1dw-WtgsC4cQDrXq_05ZKk1drrzGTR1SnqhxhU&e=orage > = new AttributedString(text); > - } > - > - private void > addAttributehttps://urldefense.proofpoint.com/v2/url?u=http-3A__-28AttributedCharacterIterator.At&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=WQSrUgEBJAAEbZNRZ7qzXQYhOY9bR4phaqX_XHR_H7I&e=tribute > attribute, Object value) { > - if (this.length != 0) { > - > https://urldefense.proofpoint.com/v2/url?u=http-3A__this.storage.ad&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=t6uaygZpGv2GwPqtAA5TulyKI1QdTYLUs4b9wMt6ux8&e=dAttribute(attribute, > value); > - } > - } > - > - public AttributedStringCharacterIterator(CharSequence charSequence, Font > font) { > - > https://urldefense.proofpoint.com/v2/url?u=http-3A__this.st&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=SWQyw1dw-WtgsC4cQDrXq_05ZKk1drrzGTR1SnqhxhU&e=orage > = new > AttributedStringhttps://urldefense.proofpoint.com/v2/url?u=http-3A__-28charSequence.to&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=Lqzp9pfFFvnGYGOZ88tKAFaCVJS7C5c52QXIfp8DexM&e=String()); > - this.length = charSequence.length(); > - > addAttributehttps://urldefense.proofpoint.com/v2/url?u=http-3A__-28TextAttribute.FO&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=UCDykGntgw4piBQmy8GMqGpzwx9enf0hBQThj8i68us&e=NT, > font); > - } > - > - public AttributedStringCharacterIterator(CharSequence charSequence, int > beginIndex, Font font) { > - > https://urldefense.proofpoint.com/v2/url?u=http-3A__this.st&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=SWQyw1dw-WtgsC4cQDrXq_05ZKk1drrzGTR1SnqhxhU&e=orage > = new > AttributedStringhttps://urldefense.proofpoint.com/v2/url?u=http-3A__-28charSequence.su&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=-aGsRPgU4CeucABgu4cGzpPKshQcp8-B6EUazZGfBMk&e=bSequence(beginIndex, > charSequence.length()).toString()); > - this.length = charSequence.length() - beginIndex; > - > addAttributehttps://urldefense.proofpoint.com/v2/url?u=http-3A__-28TextAttribute.FO&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=UCDykGntgw4piBQmy8GMqGpzwx9enf0hBQThj8i68us&e=NT, > font); > - } > - > - public AttributedStringCharacterIterator(String text, int beginIndex, > int endIndex) { > - > https://urldefense.proofpoint.com/v2/url?u=http-3A__Utils.ch&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=gEZ93Gnwcla9SQ3n7yUYJKJX2agFKOan6gqtdwIZ6NA&e=eckNull(text, > "text"); > - > https://urldefense.proofpoint.com/v2/url?u=http-3A__this.st&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=SWQyw1dw-WtgsC4cQDrXq_05ZKk1drrzGTR1SnqhxhU&e=orage > = new > AttributedStringhttps://urldefense.proofpoint.com/v2/url?u=http-3A__-28text.su&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=Dfr-4za8tjnHQxVkvzud-HKgzv6yz8Df9RsBJvVmras&e=bstring(beginIndex, > endIndex)); > - this.length = endIndex - beginIndex; > - } > - > - public AttributedStringCharacterIterator(AttributedCharacterIterator > iter, int beginIndex, int endIndex) { > - > https://urldefense.proofpoint.com/v2/url?u=http-3A__this.st&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=SWQyw1dw-WtgsC4cQDrXq_05ZKk1drrzGTR1SnqhxhU&e=orage > = new AttributedString(iter, beginIndex, endIndex); > - this.length = endIndex - beginIndex; > - } > - > - public AttributedStringCharacterIterator(String > text,https://urldefense.proofpoint.com/v2/url?u=http-3A__AttributedCharacterIterator.At&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=2j7YAIPlD2vCpGlxfw8IECIrWpSpFevu2PwwtpPS1X4&e=tribute[] > attributes) { > - > https://urldefense.proofpoint.com/v2/url?u=http-3A__Utils.ch&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=gEZ93Gnwcla9SQ3n7yUYJKJX2agFKOan6gqtdwIZ6NA&e=eckNull(text, > "text"); > - > https://urldefense.proofpoint.com/v2/url?u=http-3A__this.st&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=SWQyw1dw-WtgsC4cQDrXq_05ZKk1drrzGTR1SnqhxhU&e=orage > = new AttributedString(text); > - this.length = text.length(); > - > https://urldefense.proofpoint.com/v2/url?u=http-3A__this.at&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=nDodAvEl6NSdE3I9mS5x2mS-D8_ArWHAsLM6ywwHmV8&e=tributes > = attributes; > - } > - > - public AttributedStringCharacterIterator(String text, int beginIndex, > int endIndex, > - > https://urldefense.proofpoint.com/v2/url?u=http-3A__AttributedCharacterIterator.At&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=2j7YAIPlD2vCpGlxfw8IECIrWpSpFevu2PwwtpPS1X4&e=tribute[] > attributes) { > - > https://urldefense.proofpoint.com/v2/url?u=http-3A__Utils.ch&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=gEZ93Gnwcla9SQ3n7yUYJKJX2agFKOan6gqtdwIZ6NA&e=eckNull(text, > "text"); > - > https://urldefense.proofpoint.com/v2/url?u=http-3A__this.st&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=SWQyw1dw-WtgsC4cQDrXq_05ZKk1drrzGTR1SnqhxhU&e=orage > = new > AttributedStringhttps://urldefense.proofpoint.com/v2/url?u=http-3A__-28text.su&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=Dfr-4za8tjnHQxVkvzud-HKgzv6yz8Df9RsBJvVmras&e=bstring(beginIndex, > endIndex)); > - this.length = endIndex - beginIndex; > - > https://urldefense.proofpoint.com/v2/url?u=http-3A__this.at&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=nDodAvEl6NSdE3I9mS5x2mS-D8_ArWHAsLM6ywwHmV8&e=tributes > = attributes; > - } > - > - private AttributedStringCharacterIterator(AttributedString > attributedString) { > - // TODO: maybe we should make a copy? instead of adding the > reference??? > - > https://urldefense.proofpoint.com/v2/url?u=http-3A__this.st&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=SWQyw1dw-WtgsC4cQDrXq_05ZKk1drrzGTR1SnqhxhU&e=orage > = attributedString; > - } > - > - // TODO: many more constructors needed, esp. those with attributes > already in place > - > - public void addUnderlineAttribute(boolean underline) { > - addAttribute(TextAttribute.UNDERLINE, > - underline ? TextAttribute.UNDERLINE_ON > :https://urldefense.proofpoint.com/v2/url?u=http-3A__Integer.va&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=OMFuaAuw4os_NyXtfuol3MutMqvMbSyI6MMhcRLbIi0&e=lueOf(-1)); > - } > - > - public void addStrikethroughAttribute(boolean strikethrough) { > - > addAttributehttps://urldefense.proofpoint.com/v2/url?u=http-3A__-28TextAttribute.ST&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=g8fV2gPPr-Adpj5t4oWbzb3pJvss9OOd5h0R0-10wH8&e=RIKETHROUGH, > - strikethrough > ?https://urldefense.proofpoint.com/v2/url?u=http-3A__TextAttribute.ST&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=lyG54zwCRtPo_FKazc4zyVxVPMG9_U0-E13opJbXt54&e=RIKETHROUGH_ON > : Boolean.FALSE); > - } > - > - // TODO: do we need more parameters here? for start position or > anything else? > - private AttributedCharacterIterator getIter() { > - > https://urldefense.proofpoint.com/v2/url?u=http-3A__Utils.ch&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=gEZ93Gnwcla9SQ3n7yUYJKJX2agFKOan6gqtdwIZ6NA&e=eckNullhttps://urldefense.proofpoint.com/v2/url?u=http-3A__-28this.st&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=YpZLlx-6xKGiLBeUZ7vPT-wTS_RI2MCek8N5rtfENxk&e=orage, > "source text"); > - > - if > https://urldefense.proofpoint.com/v2/url?u=http-3A__-28this.it&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=7OzRIXxxgBoK5dZiMzDIKsRPIuyp_E42POHSEk5ummo&e=erator > == null) { > - if > https://urldefense.proofpoint.com/v2/url?u=http-3A__-28this.at&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=7sjC0OZiCj1d3yQWuVjYnJ70zpLnHF_7u0GBjgVx9sg&e=tributes > != null) { > - > https://urldefense.proofpoint.com/v2/url?u=http-3A__this.it&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=y0YCgTblyyLlEELK6GF2gd4XwSFMWWp1-fEurwfGx2U&e=erator > > =https://urldefense.proofpoint.com/v2/url?u=http-3A__storage.ge&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=B262-Lu3b45JYiq8JTQUUxRxxcQUV-HY_K0ExJ-3_QA&e=tIterator(attributes); > - } else { > - > https://urldefense.proofpoint.com/v2/url?u=http-3A__this.it&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=y0YCgTblyyLlEELK6GF2gd4XwSFMWWp1-fEurwfGx2U&e=erator > > =https://urldefense.proofpoint.com/v2/url?u=http-3A__storage.ge&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=B262-Lu3b45JYiq8JTQUUxRxxcQUV-HY_K0ExJ-3_QA&e=tIterator(); > - } > - } > - > returnhttps://urldefense.proofpoint.com/v2/url?u=http-3A__this.it&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=y0YCgTblyyLlEELK6GF2gd4XwSFMWWp1-fEurwfGx2U&e=erator; > - } > - > - /** > - * Reset this iterator, meaning recreate the underlying iterator > - * on the next call. > - */ > - public void reset() { > - > https://urldefense.proofpoint.com/v2/url?u=http-3A__this.it&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=y0YCgTblyyLlEELK6GF2gd4XwSFMWWp1-fEurwfGx2U&e=erator > = null; > - } > - > - @Override > - public Set<Attribute> getAllAttributeKeys() { > - return getIter().getAllAttributeKeys(); > - } > - > - @Override > - public Object getAttribute(Attribute attribute) { > - return getIter().getAttribute(attribute); > - } > - > - @Override > - public Map<Attribute, Object> getAttributes() { > - return getIter().getAttributes(); > - } > - > - @Override > - public int getRunLimit() { > - return getIter().getRunLimit(); > - } > - > - @Override > - public int getRunLimit(Attribute attribute) { > - return getIter().getRunLimit(attribute); > - } > - > - @Override > - public int getRunLimit(Set<? extends Attribute> attributes) { > - return getIter().getRunLimit(attributes); > - } > - > - @Override > - public int getRunStart() { > - return getIter().getRunStart(); > - } > - > - @Override > - public int getRunStart(Attribute attribute) { > - return getIter().getRunStart(attribute); > - } > - > - @Override > - public int getRunStart(Set<? extends Attribute> attributes) { > - return getIter().getRunStart(attributes); > - } > - > - @Override > - public char first() { > - return getIter().first(); > - } > - > - @Override > - public char last() { > - return getIter().last(); > - } > - > - @Override > - public char current() { > - return getIter().current(); > - } > - > - @Override > - public char next() { > - return getIter().next(); > - } > - > - @Override > - public char previous() { > - return getIter().previous(); > - } > - > - @Override > - public char setIndex(int position) { > - return getIter().setIndex(position); > - } > - > - @Override > - public int getBeginIndex() { > - return getIter().getBeginIndex(); > - } > - > - @Override > - public int getEndIndex() { > - return getIter().getEndIndex(); > - } > - > - @Override > - public int getIndex() { > - return getIter().getIndex(); > - } > - > - @Override > - public Object clone() { > - AttributedStringCharacterIterator obj = new > AttributedStringCharacterIterator(this.storage); > - // Copy over the other fields > - obj.length = this.length; > - obj.attributes = this.attributes; > - return obj; > - } > - > - @Override > - public String toString() { > - AttributedCharacterIterator iter = storage.getIterator(); > - StringBuilder buf = new StringBuilder(iter.getEndIndex()); > - char ch = iter.first(); > - while (ch != DONE) { > - buf.append(ch); > - ch = iter.next(); > - } > - return buf.toString(); > - } > - > -} > +/* > + * 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 > + * > + * > https://urldefense.proofpoint.com/v2/url?u=http-3A__www.apache.org_licenses_LICENSE-2D2.0&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=JsT1BEqkGt4UKR-IgCZyv52z9E_LJmf1P7aQ1JdjYPc&e= > + * > + * 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.pivot.text; > + > +import java.awt.Font; > +import java.awt.font.TextAttribute; > +import java.text.AttributedCharacterIterator; > +import java.text.AttributedString; > +import java.util.Map; > +import java.util.Set; > +import org.apache.pivot.util.Utils; > + > + > +/** > + * A sequence of text along with associated attributes, backed by a > + * {@link AttributedString}, which itself implements all of these > + * methods. > + */ > +public class AttributedStringCharacterIterator implements > AttributedCharacterIterator { > + private AttributedString storage = null; > + private int length = 0; > + private AttributedCharacterIterator.Attribute[] attributes = null; > + private AttributedCharacterIterator iterator = null; > + > + public AttributedStringCharacterIterator() { > + this.storage = new AttributedString(""); > + this.length = 0; > + } > + > + public AttributedStringCharacterIterator(String text) { > + Utils.checkNull(text, "text"); > + this.storage = new AttributedString(text); > + } > + > + private void addAttribute(AttributedCharacterIterator.Attribute > attribute, Object value) { > + if (this.length != 0) { > + this.storage.addAttribute(attribute, value); > + } > + } > + > + public AttributedStringCharacterIterator(CharSequence charSequence, Font > font) { > + this.storage = new AttributedString(charSequence.toString()); > + this.length = charSequence.length(); > + addAttribute(TextAttribute.FONT, font); > + } > + > + public AttributedStringCharacterIterator(CharSequence charSequence, int > beginIndex, Font font) { > + this.storage = new > AttributedString(charSequence.subSequence(beginIndex, > charSequence.length()).toString()); > + this.length = charSequence.length() - beginIndex; > + addAttribute(TextAttribute.FONT, font); > + } > + > + public AttributedStringCharacterIterator(String text, int beginIndex, > int endIndex) { > + Utils.checkNull(text, "text"); > + this.storage = new AttributedString(text.substring(beginIndex, > endIndex)); > + this.length = endIndex - beginIndex; > + } > + > + public AttributedStringCharacterIterator(AttributedCharacterIterator > iter, int beginIndex, int endIndex) { > + this.storage = new AttributedString(iter, beginIndex, endIndex); > + this.length = endIndex - beginIndex; > + } > + > + public AttributedStringCharacterIterator(String text, > AttributedCharacterIterator.Attribute[] attributes) { > + Utils.checkNull(text, "text"); > + this.storage = new AttributedString(text); > + this.length = text.length(); > + this.attributes = attributes; > + } > + > + public AttributedStringCharacterIterator(String text, int beginIndex, > int endIndex, > + AttributedCharacterIterator.Attribute[] attributes) { > + Utils.checkNull(text, "text"); > + this.storage = new AttributedString(text.substring(beginIndex, > endIndex)); > + this.length = endIndex - beginIndex; > + this.attributes = attributes; > + } > + > + private AttributedStringCharacterIterator(AttributedString > attributedString) { > + // TODO: maybe we should make a copy? instead of adding the > reference??? > + this.storage = attributedString; > + } > + > + // TODO: many more constructors needed, esp. those with attributes > already in place > + > + public void addUnderlineAttribute(boolean underline) { > + addAttribute(TextAttribute.UNDERLINE, > + underline ? TextAttribute.UNDERLINE_ON : Integer.valueOf(-1)); > + } > + > + public void addStrikethroughAttribute(boolean strikethrough) { > + addAttribute(TextAttribute.STRIKETHROUGH, > + strikethrough ? TextAttribute.STRIKETHROUGH_ON : Boolean.FALSE); > + } > + > + // TODO: do we need more parameters here? for start position or > anything else? > + private AttributedCharacterIterator getIter() { > + Utils.checkNull(this.storage, "source text"); > + > + if (this.iterator == null) { > + if (this.attributes != null) { > + this.iterator = storage.getIterator(attributes); > + } else { > + this.iterator = storage.getIterator(); > + } > + } > + return this.iterator; > + } > + > + /** > + * Reset this iterator, meaning recreate the underlying iterator > + * on the next call. > + */ > + public void reset() { > + this.iterator = null; > + } > + > + @Override > + public Set<Attribute> getAllAttributeKeys() { > + return getIter().getAllAttributeKeys(); > + } > + > + @Override > + public Object getAttribute(Attribute attribute) { > + return getIter().getAttribute(attribute); > + } > + > + @Override > + public Map<Attribute, Object> getAttributes() { > + return getIter().getAttributes(); > + } > + > + @Override > + public int getRunLimit() { > + return getIter().getRunLimit(); > + } > + > + @Override > + public int getRunLimit(Attribute attribute) { > + return getIter().getRunLimit(attribute); > + } > + > + @Override > + public int getRunLimit(Set<? extends Attribute> attributes) { > + return getIter().getRunLimit(attributes); > + } > + > + @Override > + public int getRunStart() { > + return getIter().getRunStart(); > + } > + > + @Override > + public int getRunStart(Attribute attribute) { > + return getIter().getRunStart(attribute); > + } > + > + @Override > + public int getRunStart(Set<? extends Attribute> attributes) { > + return getIter().getRunStart(attributes); > + } > + > + @Override > + public char first() { > + return getIter().first(); > + } > + > + @Override > + public char last() { > + return getIter().last(); > + } > + > + @Override > + public char current() { > + return getIter().current(); > + } > + > + @Override > + public char next() { > + return getIter().next(); > + } > + > + @Override > + public char previous() { > + return getIter().previous(); > + } > + > + @Override > + public char setIndex(int position) { > + return getIter().setIndex(position); > + } > + > + @Override > + public int getBeginIndex() { > + return getIter().getBeginIndex(); > + } > + > + @Override > + public int getEndIndex() { > + return getIter().getEndIndex(); > + } > + > + @Override > + public int getIndex() { > + return getIter().getIndex(); > + } > + > + @Override > + public Object clone() { > + AttributedStringCharacterIterator obj = new > AttributedStringCharacterIterator(this.storage); > + // Copy over the other fields > + obj.length = this.length; > + obj.attributes = this.attributes; > + return obj; > + } > + > + @Override > + public String toString() { > + AttributedCharacterIterator iter = storage.getIterator(); > + StringBuilder buf = new StringBuilder(iter.getEndIndex()); > + char ch = iter.first(); > + while (ch != DONE) { > + buf.append(ch); > + ch = iter.next(); > + } > + return buf.toString(); > + } > + > +} > > Propchange: > pivot/trunk/core/src/org/apache/pivot/text/AttributedStringCharacterIterator.java > ------------------------------------------------------------------------------ > svn:eol-style = native > > Modified: pivot/trunk/core/src/org/apache/pivot/text/CharSpan.java > URL: > https://urldefense.proofpoint.com/v2/url?u=http-3A__svn.apache.org_viewvc_pivot_trunk_core_src_org_apache_pivot_text_CharSpan.java-3Frev-3D1913470-26r1-3D1913469-26r2-3D1913470-26view-3Ddiff&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=T7Qy0W3lp_zLJ3pp6AVKblacM8dpaWW6orjDZFoTPdI&e= > ============================================================================== > --- pivot/trunk/core/src/org/apache/pivot/text/CharSpan.java (original) > +++ pivot/trunk/core/src/org/apache/pivot/text/CharSpan.java Tue Oct 31 > 19:15:47 2023 > @@ -1,276 +1,276 @@ > -/* > - * 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 > - * > - * > https://urldefense.proofpoint.com/v2/url?u=http-3A__www.apache.org_licenses_LICENSE-2D2.0&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=JsT1BEqkGt4UKR-IgCZyv52z9E_LJmf1P7aQ1JdjYPc&e= > - * > - * 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.pivot.text; > - > -import org.apache.pivot.collections.Dictionary; > -import org.apache.pivot.collections.Sequence; > -import org.apache.pivot.json.JSONSerializer; > -import org.apache.pivot.serialization.SerializationException; > -import org.apache.pivot.util.Utils; > - > -/** > - * Immutable class representing a span of characters. The range includes all > values > - * in the interval <i><code>[start, start+length-1]</code></i> inclusive. > This is > - * the paradigm used in a lot of places (notably the text controls) to > indicate a selection. > - * <p> A zero-length span indicates a single caret position at the given > start. > - * <p> Negative lengths are not supported and will throw exceptions, as will > - * negative start positions. > - */ > -public final class CharSpan { > - /** The starting location of this span (zero-based). */ > - public final int start; > - /** The length of this span (non-negative). */ > - public final int length; > - > - /** The dictionary key used to retrieve the start location. */ > - public static final String START_KEY = "start"; > - /** The dictionary key used to retrieve the length. */ > - public static final String LENGTH_KEY = "length"; > - > - /** > - * A span of length zero, starting at position zero. > - */ > - public static final CharSpan ZERO = new CharSpan(); > - > - > - /** > - * Construct a default span of length zero at location zero. > - */ > - public CharSpan() { > - this(0); > - } > - > - /** > - * Construct a new char span of length zero at the given location. > - * > - * @param startValue The start of this char span. > - * @throws IllegalArgumentException if the value is negative. > - */ > - public CharSpan(final int startValue) { > - this(startValue, 0); > - } > - > - /** > - * Construct a new char span with the given values. > - * > - * @param startValue The start of this char span. > - * @param lengthValue The length of this char span. > - * @throws IllegalArgumentException if either value is negative. > - */ > - public CharSpan(final int startValue, final int lengthValue) { > - Utils.checkNonNegative(startValue, "start"); > - Utils.checkNonNegative(lengthValue, "length"); > - > - start = startValue; > - length = lengthValue; > - } > - > - /** > - * Construct a new char span from another one (a "copy constructor"). > - * > - * @param existingCharSpan An existing char span (which must not be > {@code null}). > - * @throws IllegalArgumentException if the given char span is {@code > null}. > - */ > - public CharSpan(final CharSpan existingCharSpan) { > - Utils.checkNull(existingCharSpan, "existingCharSpan"); > - > - start = existingCharSpan.start; > - length = existingCharSpan.length; > - } > - > - /** > - * Construct a new char span from the given dictionary which must contain > - * the {@link #START_KEY} and can also contain the {@link #LENGTH_KEY} > key. > - * > - * @param charSpanDictionary A dictionary containing start and length > values. > - * @throws IllegalArgumentException if the given char span is {@code > null}, > - * if the dictionary does not contain at least the start key, or if > either of > - * the dictionary values is negative. > - */ > - public CharSpan(final Dictionary<String, ?> charSpanDictionary) { > - Utils.checkNull(charSpanDictionary, "charSpanDictionary"); > - > - int startValue; > - int lengthValue = 0; > - > - if (charSpanDictionary.containsKey(START_KEY)) { > - startValue = charSpanDictionary.getInt(START_KEY); > - Utils.checkNonNegative(startValue, "start"); > - } else { > - throw new IllegalArgumentException(START_KEY + " is required."); > - } > - > - if (charSpanDictionary.containsKey(LENGTH_KEY)) { > - lengthValue = charSpanDictionary.getInt(LENGTH_KEY); > - Utils.checkNonNegative(lengthValue, "length"); > - } > - > - start = startValue; > - length = lengthValue; > - } > - > - /** > - * Construct a new char span from the given sequence with two > - * numeric values corresponding to the start and length values > - * respectively, or one numeric value corresponding to the start > - * value (length 0). > - * > - * @param charSpanSequence A sequence containing the start and length > values. > - * @throws IllegalArgumentException if the given char span is {@code > null}, or > - * zero length, or length is greater than two. > - */ > - public CharSpan(final Sequence<?> charSpanSequence) { > - Utils.checkNull(charSpanSequence, "charSpanSequence"); > - > - int startValue; > - int lengthValue = 0; > - int seqLength = charSpanSequence.getLength(); > - > - if (seqLength < 1 || seqLength > 2) { > - throw new IllegalArgumentException("CharSpan needs one or two > values in the sequence to construct."); > - } > - > - startValue = ((Number) charSpanSequence.get(0)).intValue(); > - Utils.checkNonNegative(startValue, "start"); > - > - if (seqLength == 2) { > - lengthValue = ((Number) charSpanSequence.get(1)).intValue(); > - Utils.checkNonNegative(lengthValue, "length"); > - } > - > - > - start = startValue; > - length = lengthValue; > - } > - > - /** > - * Returns the inclusive end value of this char span, which is the > - * <code>start + length - 1</code>. So, if the length is zero, > - * then the end will be less that the start. > - * > - * @return The computed inclusive end value of this char span. > - */ > - public int getEnd() { > - return start + length - 1; > - } > - > - /** > - * Returns a new {@link CharSpan} with the start value offset by the > given amount. > - * > - * @param offset The positive or negative amount by which to "move" this > - * char span (the start value). > - * @return A new {@link CharSpan} with the updated value. > - * @throws IllegalArgumentException if the updated start value goes > negative. > - */ > - public CharSpan offset(final int offset) { > - return (offset == 0) ? this : new CharSpan(this.start + offset, > this.length); > - } > - > - /** > - * Returns a new {@link CharSpan} with the length value offset by the > given amount > - * (either positive to lengthen the span or negative to shorten the > span). > - * > - * @param offset The positive or negative amount by which to "lengthen" > this > - * char span (the length value). > - * @return A new {@link CharSpan} with the updated value. > - * @throws IllegalArgumentException if the updated length value goes > negative. > - */ > - public CharSpan lengthen(final int offset) { > - return (offset == 0) ? this : new CharSpan(this.start, this.length + > offset); > - } > - > - @Override > - public boolean equals(final Object o) { > - boolean equal = false; > - > - if (o == this) { > - return true; > - } > - > - if (o instanceof CharSpan) { > - CharSpan span = (CharSpan) o; > - equal = (start == span.start && length == span.length); > - } > - > - return equal; > - } > - > - @Override > - public int hashCode() { > - return 31 * start + length; > - } > - > - @Override > - public String toString() { > - return getClass().getSimpleName() + " {start:" + start + ", length:" > + length + "}"; > - } > - > - /** > - * Convert a string into a char span. > - * <p> If the string value is a JSON map, then parse the map > - * and construct using the {@link #CharSpan(Dictionary)} method. > - * <p> If the string value is a JSON list, then parse the list > - * and construct using the first two values as start and end > - * respectively, using the {@link #CharSpan(int, int)} constructor. > - * <p> Also accepted is a simple list of two integer values > - * separated by comma or semicolon. > - * <p> Otherwise the string should be a single integer value > - * that will be used to construct the char span using the {@link > #CharSpan(int)} > - * constructor (just the start value, with a zero length). > - * > - * @param value The string value to decode into a new char span. > - * @return The decoded char span. > - * @throws IllegalArgumentException if the value is {@code null} or > empty, > - * if the string starts with <code>"{"</code> but it cannot be parsed as > - * a JSON map, if it starts with <code>"["</code> but cannot be parsed > - * as a JSON list, or cannot be recognized as a simple list of one or > - * two integers. > - */ > - public static CharSpan decode(final String value) { > - Utils.checkNullOrEmpty(value, "value"); > - > - CharSpan charSpan; > - if (value.startsWith("{")) { > - try { > - charSpan = new CharSpan(JSONSerializer.parseMap(value)); > - } catch (SerializationException exception) { > - throw new IllegalArgumentException(exception); > - } > - } else if (value.startsWith("[")) { > - try { > - charSpan = new CharSpan(JSONSerializer.parseList(value)); > - } catch (SerializationException exception) { > - throw new IllegalArgumentException(exception); > - } > - } else { > - String[] parts = value.split("\\s*[,;]\\s*"); > - try { > - if (parts.length == 2) { > - charSpan = new CharSpan(Integer.parseInt(parts[0]), > Integer.parseInt(parts[1])); > - } else if (parts.length == 1) { > - charSpan = new CharSpan(Integer.parseInt(value)); > - } else { > - throw new IllegalArgumentException("Unknown format for > CharSpan: " + value); > - } > - } catch (NumberFormatException ex) { > - throw new IllegalArgumentException(ex); > - } > - } > - > - return charSpan; > - } > -} > +/* > + * 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 > + * > + * > https://urldefense.proofpoint.com/v2/url?u=http-3A__www.apache.org_licenses_LICENSE-2D2.0&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=JsT1BEqkGt4UKR-IgCZyv52z9E_LJmf1P7aQ1JdjYPc&e= > + * > + * 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.pivot.text; > + > +import org.apache.pivot.collections.Dictionary; > +import org.apache.pivot.collections.Sequence; > +import org.apache.pivot.json.JSONSerializer; > +import org.apache.pivot.serialization.SerializationException; > +import org.apache.pivot.util.Utils; > + > +/** > + * Immutable class representing a span of characters. The range includes all > values > + * in the interval <i><code>[start, start+length-1]</code></i> inclusive. > This is > + * the paradigm used in a lot of places (notably the text controls) to > indicate a selection. > + * <p> A zero-length span indicates a single caret position at the given > start. > + * <p> Negative lengths are not supported and will throw exceptions, as will > + * negative start positions. > + */ > +public final class CharSpan { > + /** The starting location of this span (zero-based). */ > + public final int start; > + /** The length of this span (non-negative). */ > + public final int length; > + > + /** The dictionary key used to retrieve the start location. */ > + public static final String START_KEY = "start"; > + /** The dictionary key used to retrieve the length. */ > + public static final String LENGTH_KEY = "length"; > + > + /** > + * A span of length zero, starting at position zero. > + */ > + public static final CharSpan ZERO = new CharSpan(); > + > + > + /** > + * Construct a default span of length zero at location zero. > + */ > + public CharSpan() { > + this(0); > + } > + > + /** > + * Construct a new char span of length zero at the given location. > + * > + * @param startValue The start of this char span. > + * @throws IllegalArgumentException if the value is negative. > + */ > + public CharSpan(final int startValue) { > + this(startValue, 0); > + } > + > + /** > + * Construct a new char span with the given values. > + * > + * @param startValue The start of this char span. > + * @param lengthValue The length of this char span. > + * @throws IllegalArgumentException if either value is negative. > + */ > + public CharSpan(final int startValue, final int lengthValue) { > + Utils.checkNonNegative(startValue, "start"); > + Utils.checkNonNegative(lengthValue, "length"); > + > + start = startValue; > + length = lengthValue; > + } > + > + /** > + * Construct a new char span from another one (a "copy constructor"). > + * > + * @param existingCharSpan An existing char span (which must not be > {@code null}). > + * @throws IllegalArgumentException if the given char span is {@code > null}. > + */ > + public CharSpan(final CharSpan existingCharSpan) { > + Utils.checkNull(existingCharSpan, "existingCharSpan"); > + > + start = existingCharSpan.start; > + length = existingCharSpan.length; > + } > + > + /** > + * Construct a new char span from the given dictionary which must contain > + * the {@link #START_KEY} and can also contain the {@link #LENGTH_KEY} > key. > + * > + * @param charSpanDictionary A dictionary containing start and length > values. > + * @throws IllegalArgumentException if the given char span is {@code > null}, > + * if the dictionary does not contain at least the start key, or if > either of > + * the dictionary values is negative. > + */ > + public CharSpan(final Dictionary<String, ?> charSpanDictionary) { > + Utils.checkNull(charSpanDictionary, "charSpanDictionary"); > + > + int startValue; > + int lengthValue = 0; > + > + if (charSpanDictionary.containsKey(START_KEY)) { > + startValue = charSpanDictionary.getInt(START_KEY); > + Utils.checkNonNegative(startValue, "start"); > + } else { > + throw new IllegalArgumentException(START_KEY + " is required."); > + } > + > + if (charSpanDictionary.containsKey(LENGTH_KEY)) { > + lengthValue = charSpanDictionary.getInt(LENGTH_KEY); > + Utils.checkNonNegative(lengthValue, "length"); > + } > + > + start = startValue; > + length = lengthValue; > + } > + > + /** > + * Construct a new char span from the given sequence with two > + * numeric values corresponding to the start and length values > + * respectively, or one numeric value corresponding to the start > + * value (length 0). > + * > + * @param charSpanSequence A sequence containing the start and length > values. > + * @throws IllegalArgumentException if the given char span is {@code > null}, or > + * zero length, or length is greater than two. > + */ > + public CharSpan(final Sequence<?> charSpanSequence) { > + Utils.checkNull(charSpanSequence, "charSpanSequence"); > + > + int startValue; > + int lengthValue = 0; > + int seqLength = charSpanSequence.getLength(); > + > + if (seqLength < 1 || seqLength > 2) { > + throw new IllegalArgumentException("CharSpan needs one or two > values in the sequence to construct."); > + } > + > + startValue = ((Number) charSpanSequence.get(0)).intValue(); > + Utils.checkNonNegative(startValue, "start"); > + > + if (seqLength == 2) { > + lengthValue = ((Number) charSpanSequence.get(1)).intValue(); > + Utils.checkNonNegative(lengthValue, "length"); > + } > + > + > + start = startValue; > + length = lengthValue; > + } > + > + /** > + * Returns the inclusive end value of this char span, which is the > + * <code>start + length - 1</code>. So, if the length is zero, > + * then the end will be less that the start. > + * > + * @return The computed inclusive end value of this char span. > + */ > + public int getEnd() { > + return start + length - 1; > + } > + > + /** > + * Returns a new {@link CharSpan} with the start value offset by the > given amount. > + * > + * @param offset The positive or negative amount by which to "move" this > + * char span (the start value). > + * @return A new {@link CharSpan} with the updated value. > + * @throws IllegalArgumentException if the updated start value goes > negative. > + */ > + public CharSpan offset(final int offset) { > + return (offset == 0) ? this : new CharSpan(this.start + offset, > this.length); > + } > + > + /** > + * Returns a new {@link CharSpan} with the length value offset by the > given amount > + * (either positive to lengthen the span or negative to shorten the > span). > + * > + * @param offset The positive or negative amount by which to "lengthen" > this > + * char span (the length value). > + * @return A new {@link CharSpan} with the updated value. > + * @throws IllegalArgumentException if the updated length value goes > negative. > + */ > + public CharSpan lengthen(final int offset) { > + return (offset == 0) ? this : new CharSpan(this.start, this.length + > offset); > + } > + > + @Override > + public boolean equals(final Object o) { > + boolean equal = false; > + > + if (o == this) { > + return true; > + } > + > + if (o instanceof CharSpan) { > + CharSpan span = (CharSpan) o; > + equal = (start == span.start && length == span.length); > + } > + > + return equal; > + } > + > + @Override > + public int hashCode() { > + return 31 * start + length; > + } > + > + @Override > + public String toString() { > + return getClass().getSimpleName() + " {start:" + start + ", length:" > + length + "}"; > + } > + > + /** > + * Convert a string into a char span. > + * <p> If the string value is a JSON map, then parse the map > + * and construct using the {@link #CharSpan(Dictionary)} method. > + * <p> If the string value is a JSON list, then parse the list > + * and construct using the first two values as start and end > + * respectively, using the {@link #CharSpan(int, int)} constructor. > + * <p> Also accepted is a simple list of two integer values > + * separated by comma or semicolon. > + * <p> Otherwise the string should be a single integer value > + * that will be used to construct the char span using the {@link > #CharSpan(int)} > + * constructor (just the start value, with a zero length). > + * > + * @param value The string value to decode into a new char span. > + * @return The decoded char span. > + * @throws IllegalArgumentException if the value is {@code null} or > empty, > + * if the string starts with <code>"{"</code> but it cannot be parsed as > + * a JSON map, if it starts with <code>"["</code> but cannot be parsed > + * as a JSON list, or cannot be recognized as a simple list of one or > + * two integers. > + */ > + public static CharSpan decode(final String value) { > + Utils.checkNullOrEmpty(value, "value"); > + > + CharSpan charSpan; > + if (value.startsWith("{")) { > + try { > + charSpan = new CharSpan(JSONSerializer.parseMap(value)); > + } catch (SerializationException exception) { > + throw new IllegalArgumentException(exception); > + } > + } else if (value.startsWith("[")) { > + try { > + charSpan = new CharSpan(JSONSerializer.parseList(value)); > + } catch (SerializationException exception) { > + throw new IllegalArgumentException(exception); > + } > + } else { > + String[] parts = value.split("\\s*[,;]\\s*"); > + try { > + if (parts.length == 2) { > + charSpan = new CharSpan(Integer.parseInt(parts[0]), > Integer.parseInt(parts[1])); > + } else if (parts.length == 1) { > + charSpan = new CharSpan(Integer.parseInt(value)); > + } else { > + throw new IllegalArgumentException("Unknown format for > CharSpan: " + value); > + } > + } catch (NumberFormatException ex) { > + throw new IllegalArgumentException(ex); > + } > + } > + > + return charSpan; > + } > +} > > Propchange: pivot/trunk/core/src/org/apache/pivot/text/CharSpan.java > ------------------------------------------------------------------------------ > svn:eol-style = native > > Modified: pivot/trunk/core/src/org/apache/pivot/text/CompositeIterator.java > URL: > https://urldefense.proofpoint.com/v2/url?u=http-3A__svn.apache.org_viewvc_pivot_trunk_core_src_org_apache_pivot_text_CompositeIterator.java-3Frev-3D1913470-26r1-3D1913469-26r2-3D1913470-26view-3Ddiff&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=w5owCLsGtIHES9QK3uXCyAjUMFfOde0zJhf1TPWOHE4&e= > ============================================================================== > --- pivot/trunk/core/src/org/apache/pivot/text/CompositeIterator.java > (original) > +++ pivot/trunk/core/src/org/apache/pivot/text/CompositeIterator.java Tue Oct > 31 19:15:47 2023 > @@ -1,185 +1,185 @@ > -/* > - * 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 > - * > - * > https://urldefense.proofpoint.com/v2/url?u=http-3A__www.apache.org_licenses_LICENSE-2D2.0&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=JsT1BEqkGt4UKR-IgCZyv52z9E_LJmf1P7aQ1JdjYPc&e= > - * > - * 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.pivot.text; > - > -import java.text.AttributedCharacterIterator; > -import java.util.HashSet; > -import java.util.Map; > -import java.util.Set; > -import org.apache.pivot.collections.ArrayList; > -import org.apache.pivot.collections.List; > -import org.apache.pivot.util.Utils; > - > - > -/** > - * An {@link AttributedCharacterIterator} that implements iterating over > - * several (typically two or three) underlying iterators. The assumption > - * is that no attributes will ever cross the underlying iterator boundaries > - * (which is always the case for insertion of composed but uncommitted text > - * in the middle of two pieces of committed text (for instance). > - */ > -public class CompositeIterator implements AttributedCharacterIterator { > - > - private List<AttributedCharacterIterator> iterators = new ArrayList<>(); > - private int endIndex; > - private int currentIndex; > - private AttributedCharacterIterator currentIterator; > - private int currentIteratorDelta; > - > - /** > - * Constructs a CompositeIterator that iterates over the concatenation > - * of one or more iterators. > - * @param iterators The base iterators that this composite iterator > concatenates. > - */ > - public CompositeIterator(AttributedCharacterIterator... iterators) { > - int fullLength = 0; > - for (AttributedCharacterIterator iter : iterators) { > - int beginIndex = iter.getBeginIndex(); // inclusive > - int endIndex = iter.getEndIndex(); // exclusive > - int range = (endIndex - beginIndex); > - this.iterators.add(iter); > - fullLength += range; > - } > - this.endIndex = fullLength; > - setIndex0(0); > - } > - > - // CharacterIterator implementations > - > - public char first() { > - return setIndex0(0); > - } > - > - public char last() { > - if (endIndex == 0) { > - return setIndex0(endIndex); > - } else { > - return setIndex0(endIndex - 1); > - } > - } > - > - public char next() { > - if (currentIndex < endIndex) { > - return setIndex0(currentIndex + 1); > - } else { > - return DONE; > - } > - } > - > - public char previous() { > - if (currentIndex > 0) { > - return setIndex0(currentIndex - 1); > - } else { > - return DONE; > - } > - } > - > - public char current() { > - return currentIterator.setIndex(currentIndex - currentIteratorDelta); > - } > - > - public char setIndex(int position) { > - // Note: this is a (0 < position <= endIndex) check, since > "endIndex" is a valid value here > - > https://urldefense.proofpoint.com/v2/url?u=http-3A__Utils.ch&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=gEZ93Gnwcla9SQ3n7yUYJKJX2agFKOan6gqtdwIZ6NA&e=eckIndexBounds(position, > 0, endIndex); > - > - return setIndex0(position); > - } > - > - private char setIndex0(int position) { > - currentIndex = position; > - int cumLength = 0; > - for (AttributedCharacterIterator iter : iterators) { > - int beginIndex > =https://urldefense.proofpoint.com/v2/url?u=http-3A__iter.ge&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=3TD3ZxTTRi4wUiQ-6Xr8YYvjnQocaauqHLQHPi3WvGk&e=tBeginIndex(); > - int endIndex > =https://urldefense.proofpoint.com/v2/url?u=http-3A__iter.ge&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=3TD3ZxTTRi4wUiQ-6Xr8YYvjnQocaauqHLQHPi3WvGk&e=tEndIndex(); > - int range = endIndex - beginIndex; > - if (currentIndex < endIndex + cumLength) { > - currentIterator = iter; > - currentIteratorDelta = beginIndex + cumLength; > - // TODO: not sure this is going to be correct for > 2 > iterators > - return currentIterator.setIndex(currentIndex - > currentIteratorDelta); > - } > - cumLength += range; > - } > - return DONE; > - } > - > - public int getBeginIndex() { > - return 0; > - } > - > - public int getEndIndex() { > - return endIndex; > - } > - > - public int getIndex() { > - return currentIndex; > - } > - > - // AttributedCharacterIterator implementations > - > - public int getRunStart() { > - return currentIterator.getRunStart() + currentIteratorDelta; > - } > - > - public int getRunLimit() { > - return currentIterator.getRunLimit() + currentIteratorDelta; > - } > - > - public int getRunStart(Attribute attribute) { > - return currentIterator.getRunStart(attribute) + currentIteratorDelta; > - } > - > - public int getRunLimit(Attribute attribute) { > - return currentIterator.getRunLimit(attribute) + currentIteratorDelta; > - } > - > - public int getRunStart(Set<? extends Attribute> attributes) { > - return currentIterator.getRunStart(attributes) + > currentIteratorDelta; > - } > - > - public int getRunLimit(Set<? extends Attribute> attributes) { > - return currentIterator.getRunLimit(attributes) + > currentIteratorDelta; > - } > - > - public Map<Attribute, Object> getAttributes() { > - return currentIterator.getAttributes(); > - } > - > - public Set<Attribute> getAllAttributeKeys() { > - Set<Attribute> keys = new HashSet<>(); > - for (AttributedCharacterIterator iter : iterators) { > - keys.addAll(iter.getAllAttributeKeys()); > - } > - return keys; > - } > - > - public Object getAttribute(Attribute attribute) { > - return currentIterator.getAttribute(attribute); > - } > - > - // Object implementations > - > - public Object clone() { > - try { > - CompositeIterator other = (CompositeIterator) super.clone(); > - return other; > - } catch (CloneNotSupportedException e) { > - throw new InternalError(); > - } > - } > - > -} > +/* > + * 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 > + * > + * > https://urldefense.proofpoint.com/v2/url?u=http-3A__www.apache.org_licenses_LICENSE-2D2.0&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=JsT1BEqkGt4UKR-IgCZyv52z9E_LJmf1P7aQ1JdjYPc&e= > + * > + * 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.pivot.text; > + > +import java.text.AttributedCharacterIterator; > +import java.util.HashSet; > +import java.util.Map; > +import java.util.Set; > +import org.apache.pivot.collections.ArrayList; > +import org.apache.pivot.collections.List; > +import org.apache.pivot.util.Utils; > + > + > +/** > + * An {@link AttributedCharacterIterator} that implements iterating over > + * several (typically two or three) underlying iterators. The assumption > + * is that no attributes will ever cross the underlying iterator boundaries > + * (which is always the case for insertion of composed but uncommitted text > + * in the middle of two pieces of committed text (for instance). > + */ > +public class CompositeIterator implements AttributedCharacterIterator { > + > + private List<AttributedCharacterIterator> iterators = new ArrayList<>(); > + private int endIndex; > + private int currentIndex; > + private AttributedCharacterIterator currentIterator; > + private int currentIteratorDelta; > + > + /** > + * Constructs a CompositeIterator that iterates over the concatenation > + * of one or more iterators. > + * @param iterators The base iterators that this composite iterator > concatenates. > + */ > + public CompositeIterator(AttributedCharacterIterator... iterators) { > + int fullLength = 0; > + for (AttributedCharacterIterator iter : iterators) { > + int beginIndex = iter.getBeginIndex(); // inclusive > + int endIndex = iter.getEndIndex(); // exclusive > + int range = (endIndex - beginIndex); > + this.iterators.add(iter); > + fullLength += range; > + } > + this.endIndex = fullLength; > + setIndex0(0); > + } > + > + // CharacterIterator implementations > + > + public char first() { > + return setIndex0(0); > + } > + > + public char last() { > + if (endIndex == 0) { > + return setIndex0(endIndex); > + } else { > + return setIndex0(endIndex - 1); > + } > + } > + > + public char next() { > + if (currentIndex < endIndex) { > + return setIndex0(currentIndex + 1); > + } else { > + return DONE; > + } > + } > + > + public char previous() { > + if (currentIndex > 0) { > + return setIndex0(currentIndex - 1); > + } else { > + return DONE; > + } > + } > + > + public char current() { > + return currentIterator.setIndex(currentIndex - currentIteratorDelta); > + } > + > + public char setIndex(int position) { > + // Note: this is a (0 < position <= endIndex) check, since > "endIndex" is a valid value here > + > https://urldefense.proofpoint.com/v2/url?u=http-3A__Utils.ch&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=gEZ93Gnwcla9SQ3n7yUYJKJX2agFKOan6gqtdwIZ6NA&e=eckIndexBounds(position, > 0, endIndex); > + > + return setIndex0(position); > + } > + > + private char setIndex0(int position) { > + currentIndex = position; > + int cumLength = 0; > + for (AttributedCharacterIterator iter : iterators) { > + int beginIndex > =https://urldefense.proofpoint.com/v2/url?u=http-3A__iter.ge&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=3TD3ZxTTRi4wUiQ-6Xr8YYvjnQocaauqHLQHPi3WvGk&e=tBeginIndex(); > + int endIndex > =https://urldefense.proofpoint.com/v2/url?u=http-3A__iter.ge&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=3TD3ZxTTRi4wUiQ-6Xr8YYvjnQocaauqHLQHPi3WvGk&e=tEndIndex(); > + int range = endIndex - beginIndex; > + if (currentIndex < endIndex + cumLength) { > + currentIterator = iter; > + currentIteratorDelta = beginIndex + cumLength; > + // TODO: not sure this is going to be correct for > 2 > iterators > + return currentIterator.setIndex(currentIndex - > currentIteratorDelta); > + } > + cumLength += range; > + } > + return DONE; > + } > + > + public int getBeginIndex() { > + return 0; > + } > + > + public int getEndIndex() { > + return endIndex; > + } > + > + public int getIndex() { > + return currentIndex; > + } > + > + // AttributedCharacterIterator implementations > + > + public int getRunStart() { > + return currentIterator.getRunStart() + currentIteratorDelta; > + } > + > + public int getRunLimit() { > + return currentIterator.getRunLimit() + currentIteratorDelta; > + } > + > + public int getRunStart(Attribute attribute) { > + return currentIterator.getRunStart(attribute) + currentIteratorDelta; > + } > + > + public int getRunLimit(Attribute attribute) { > + return currentIterator.getRunLimit(attribute) + currentIteratorDelta; > + } > + > + public int getRunStart(Set<? extends Attribute> attributes) { > + return currentIterator.getRunStart(attributes) + > currentIteratorDelta; > + } > + > + public int getRunLimit(Set<? extends Attribute> attributes) { > + return currentIterator.getRunLimit(attributes) + > currentIteratorDelta; > + } > + > + public Map<Attribute, Object> getAttributes() { > + return currentIterator.getAttributes(); > + } > + > + public Set<Attribute> getAllAttributeKeys() { > + Set<Attribute> keys = new HashSet<>(); > + for (AttributedCharacterIterator iter : iterators) { > + keys.addAll(iter.getAllAttributeKeys()); > + } > + return keys; > + } > + > + public Object getAttribute(Attribute attribute) { > + return currentIterator.getAttribute(attribute); > + } > + > + // Object implementations > + > + public Object clone() { > + try { > + CompositeIterator other = (CompositeIterator) super.clone(); > + return other; > + } catch (CloneNotSupportedException e) { > + throw new InternalError(); > + } > + } > + > +} > > Propchange: pivot/trunk/core/src/org/apache/pivot/text/CompositeIterator.java > ------------------------------------------------------------------------------ > svn:eol-style = native > > Modified: pivot/trunk/core/src/org/apache/pivot/util/BooleanResult.java > URL: > https://urldefense.proofpoint.com/v2/url?u=http-3A__svn.apache.org_viewvc_pivot_trunk_core_src_org_apache_pivot_util_BooleanResult.java-3Frev-3D1913470-26r1-3D1913469-26r2-3D1913470-26view-3Ddiff&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=gH8zl1jumjR4HHfUldD3HkLa_CByMFcE1oWzv77YYfk&e= > ============================================================================== > --- pivot/trunk/core/src/org/apache/pivot/util/BooleanResult.java (original) > +++ pivot/trunk/core/src/org/apache/pivot/util/BooleanResult.java Tue Oct 31 > 19:15:47 2023 > @@ -1,108 +1,108 @@ > -/* > - * 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 > - * > - * > https://urldefense.proofpoint.com/v2/url?u=http-3A__www.apache.org_licenses_LICENSE-2D2.0&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=JsT1BEqkGt4UKR-IgCZyv52z9E_LJmf1P7aQ1JdjYPc&e= > - * > - * 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.pivot.util; > - > -/** > - * An object holding a boolean value that can be used with a {@code forEach} > - * or lambda expressionm, where the value used during the iteration must be > - * final or effectively final. > - */ > -public class BooleanResult { > - /** > - * The current boolean value. > - */ > - private boolean result; > - > - /** > - * Construct one of these and set the initial value to the given value. > - * > - * @param initialValue The initial boolean value. > - */ > - public BooleanResult(final boolean initialValue) { > - result = initialValue; > - } > - > - /** > - * Construct one of these and set the initial boolean value to > - * {@code false}. > - */ > - public BooleanResult() { > - this(false); > - } > - > - /** > - * Update the saved value by <code>OR</code>ing this new value > - * with the saved value. > - * > - * @param value The new value to OR into the saved one. > - */ > - public void or(final boolean value) { > - result |= value; > - } > - > - /** > - * Update the saved value by <code>AND</code>ing this new value > - * with the saved value. > - * > - * @param value The new value to AND into the saved one. > - */ > - public void and(final boolean value) { > - result &= value; > - } > - > - /** > - * Update the saved value by <code>XOR</code>ing this new value > - * with the saved value. > - * > - * @param value The new value to XOR into the saved one. > - */ > - public void xor(final boolean value) { > - result ^= value; > - } > - > - /** > - * Negate the saved value. > - */ > - public void not() { > - result = !result; > - } > - > - /** > - * Clear the boolean result to the default value > - * of {@code false}. > - */ > - public void clear() { > - result = false; > - } > - > - /** > - * Set the result value to the given value. > - * > - * @param value The new value to set. > - */ > - public void set(final boolean value) { > - result = value; > - } > - > - /** > - * @return The final boolean value. > - */ > - public boolean get() { > - return result; > - } > - > -} > +/* > + * 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 > + * > + * > https://urldefense.proofpoint.com/v2/url?u=http-3A__www.apache.org_licenses_LICENSE-2D2.0&d=DwICaQ&c=euGZstcaTDllvimEN8b7jXrwqOf-v5A_CdpgnVfiiMM&r=JYLg0shOavzSp2WxYFFvMuhqXdAQzkMRPf_4HQmFZZ4&m=ZD2EJ8O0uwRqKcvQB00kZgO_-rNffcWuekw2AxdmjCFAtLId6k-8CNUg65ig2brw&s=JsT1BEqkGt4UKR-IgCZyv52z9E_LJmf1P7aQ1JdjYPc&e= > + * > + * 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.pivot.util; > + > +/** > + * An object holding a boolean value that can be used with a {@code forEach} > + * or lambda expressionm, where the value used during the iteration must be > + * final or effectively final. > + */ > +public class BooleanResult { > + /** > + * The current boolean value. > + */ > + private boolean result; > + > + /** > + * Construct one of these and set the initial value to the given value. > + * > + * @param initialValue The initial boolean value. > + */ > + public BooleanResult(final boolean initialValue) { > + result = initialValue; > + } > + > + /** > + * Construct one of these and set the initial boolean value to > + * {@code false}. > + */ > + public BooleanResult() { > + this(false); > + } > + > + /** > + * Update the saved value by <code>OR</code>ing this new value > + * with the saved value. > + * > + * @param value The new value to OR into the saved one. > + */ > + public void or(final boolean value) { > + result |= value; > + } > + > + /** > + * Update the saved value by <code>AND</code>ing this new value > + * with the saved value. > + * > + * @param value The new value to AND into the saved one. > + */ > + public void and(final boolean value) { > + result &= value; > + } > + > + /** > + * Update the saved value by <code>XOR</code>ing this new value > + * with the saved value. > + * > + * @param value The new value to XOR into the saved one. > + */ > + public void xor(final boolean value) { > + result ^= value; > + } > + > + /** > + * Negate the saved value. > + */ > + public void not() { > + result = !result; > + } > + > + /** > + * Clear the boolean result to the default value > + * of {@code false}. > + */ > + public void clear() { > + result = false; > + } > + > + /** > + * Set the result value to the given value. > + * > + * @param value The new value to set. > + */ > + public void set(final boolean value) { > + result = value; > + } > + > + /** > + * @return The final boolean value. > + */ > + public boolean get() { > + return result; > + } > + > +} > > Propchange: pivot/trunk/core/src/org/apache/pivot/util/BooleanResult.java > ------------------------------------------------------------------------------ > svn:eol-style = native > >