From 554fd8c5195424bdbcabf5de30fdc183aba391bd Mon Sep 17 00:00:00 2001 From: upstream source tree Date: Sun, 15 Mar 2015 20:14:05 -0400 Subject: obtained gcc-4.6.4.tar.bz2 from upstream website; verified gcc-4.6.4.tar.bz2.sig; imported gcc-4.6.4 source tree from verified upstream tarball. downloading a git-generated archive based on the 'upstream' tag should provide you with a source tree that is binary identical to the one extracted from the above tarball. if you have obtained the source via the command 'git clone', however, do note that line-endings of files in your working directory might differ from line-endings of the respective files in the upstream repository. --- .../gnu/xml/transform/AbstractNumberNode.java | 330 +++++++++++++++++++++ 1 file changed, 330 insertions(+) create mode 100644 libjava/classpath/gnu/xml/transform/AbstractNumberNode.java (limited to 'libjava/classpath/gnu/xml/transform/AbstractNumberNode.java') diff --git a/libjava/classpath/gnu/xml/transform/AbstractNumberNode.java b/libjava/classpath/gnu/xml/transform/AbstractNumberNode.java new file mode 100644 index 000000000..6e478bdc4 --- /dev/null +++ b/libjava/classpath/gnu/xml/transform/AbstractNumberNode.java @@ -0,0 +1,330 @@ +/* AbstractNumberNode.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package gnu.xml.transform; + +import gnu.java.lang.CPStringBuilder; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import javax.xml.namespace.QName; +import javax.xml.transform.TransformerException; +import org.w3c.dom.Document; +import org.w3c.dom.DocumentFragment; +import org.w3c.dom.Node; +import org.w3c.dom.Text; +import gnu.xml.xpath.Expr; + +/** + * A template node representing the XSL number instruction. + * + * @author Chris Burdess + */ +abstract class AbstractNumberNode + extends TemplateNode +{ + + static final int ALPHABETIC = 0; + static final int TRADITIONAL = 1; + + final TemplateNode format; + final String lang; + final int letterValue; + final String groupingSeparator; + final int groupingSize; + + AbstractNumberNode(TemplateNode format, String lang, + int letterValue, String groupingSeparator, + int groupingSize) + { + this.format = format; + this.lang = lang; + this.letterValue = letterValue; + this.groupingSeparator = groupingSeparator; + this.groupingSize = groupingSize; + } + + void doApply(Stylesheet stylesheet, QName mode, + Node context, int pos, int len, + Node parent, Node nextSibling) + throws TransformerException + { + Document doc = (parent instanceof Document) ? (Document) parent : + parent.getOwnerDocument(); + DocumentFragment fragment = doc.createDocumentFragment(); + format.apply(stylesheet, mode, context, pos, len, fragment, null); + String f = Expr._string(context, Collections.singleton(fragment)); + String value = format(f, compute(stylesheet, context, pos, len)); + Text text = doc.createTextNode(value); + if (nextSibling != null) + { + parent.insertBefore(text, nextSibling); + } + else + { + parent.appendChild(text); + } + // xsl:number doesn't process children + if (next != null) + { + next.apply(stylesheet, mode, + context, pos, len, + parent, nextSibling); + } + } + + String format(String format, int[] number) + { + if (number.length == 0) + { + return ""; + } + int start = 0, end = 0, len = format.length(); // region of format + // Tokenize + List tokens = new ArrayList((number.length * 2) + 1); + List types = new ArrayList(tokens.size()); + while (end < len) + { + while (end < len && !isAlphanumeric(format.charAt(end))) + { + end++; + } + if (end > start) + { + tokens.add(format.substring(start, end)); + types.add(Boolean.FALSE); + } + start = end; + while (end < len && isAlphanumeric(format.charAt(end))) + { + end++; + } + if (end > start) + { + tokens.add(format.substring(start, end)); + types.add(Boolean.TRUE); + } + start = end; + } + // Process tokens + CPStringBuilder buf = new CPStringBuilder(); + len = tokens.size(); + int pos = 0; + for (int i = 0; i < len; i++) + { + String token = (i < 0) ? "." : (String) tokens.get(i); + boolean alpha = (i < 0) ? true : + ((Boolean) types.get(i)).booleanValue(); + if (!alpha) + { + buf.append(token); + } + else + { + if (pos < number.length) + { + format(buf, number[pos++], token); + if (((i + 1 == len) || (i + 2 == len)) && + (pos < number.length)) + { + // More numbers than tokens, reuse last token + i -= 2; + } + } + if (pos == number.length && i < (len - 2)) + { + // No more numbers. Skip to the end... + i = len - 2; + if (((Boolean) types.get(i + 1)).booleanValue()) + { + // number formatting token, ignore + i++; + } + } + } + } + //System.err.println("format: '"+format+"' "+asList(number)+" = '"+buf.toString()+"'"); + return buf.toString(); + } + + /*List asList(int[] number) + { + List l = new ArrayList(); + for (int i = 0; i < number.length; i++) + l.add(new Integer(number[i])); + return l; + }*/ + + void format(CPStringBuilder buf, int number, String formatToken) + { + int len = formatToken.length(); + char c = formatToken.charAt(len - 1); + if (Character.digit(c, 10) == 1) + { + // Check preceding characters + for (int i = len - 2; i >= 0; i--) + { + if (formatToken.charAt(i) != (c - 1)) + { + format(buf, number, "1"); + return; + } + } + // Decimal representation + String val = Integer.toString(number); + for (int d = len - val.length(); d > 0; d--) + { + buf.append('0'); + } + buf.append(val); + } + else if ("A".equals(formatToken)) + { + buf.append(alphabetic('@', number)); + } + else if ("a".equals(formatToken)) + { + buf.append(alphabetic('`', number)); + } + else if ("i".equals(formatToken)) + { + buf.append(roman(false, number)); + } + else if ("I".equals(formatToken)) + { + buf.append(roman(true, number)); + } + else + { + // Unknown numbering sequence + format(buf, number, "1"); + } + } + + static final boolean isAlphanumeric(char c) + { + switch (Character.getType(c)) + { + case Character.DECIMAL_DIGIT_NUMBER: // Nd + case Character.LETTER_NUMBER: // Nl + case Character.OTHER_NUMBER: // No + case Character.UPPERCASE_LETTER: // Lu + case Character.LOWERCASE_LETTER: // Ll + case Character.TITLECASE_LETTER: // Lt + case Character.MODIFIER_LETTER: // Lm + case Character.OTHER_LETTER: // Lo + return true; + default: + return false; + } + } + + static final String alphabetic(char offset, int number) + { + CPStringBuilder buf = new CPStringBuilder(); + while (number > 0) + { + int r = number % 26; + number = number / 26; + buf.insert(0, (char) (offset + r)); + } + return buf.toString(); + } + + static final int[] roman_numbers = {1, 5, 10, 50, 100, 500, 1000}; + static final char[] roman_chars = {'i', 'v', 'x', 'l', 'c', 'd', 'm'}; + + static final String roman(boolean upper, int number) + { + CPStringBuilder buf = new CPStringBuilder(); + for (int pos = roman_numbers.length - 1; pos >= 0; pos -= 2) + { + int f = number / roman_numbers[pos]; + if (f != 0) + { + number = number % (f * roman_numbers[pos]); + } + if (f > 4 && f < 9) + { + buf.append(roman_chars[pos + 1]); + f -= 5; + } + if (f == 4) + { + buf.append(roman_chars[pos]); + buf.append(roman_chars[pos + 1]); + } + else if (f == 9) + { + buf.append(roman_chars[pos]); + buf.append(roman_chars[pos + 2]); + } + else + { + for (; f > 0; f--) + { + buf.append(roman_chars[pos]); + } + } + } + return upper ? buf.toString().toUpperCase() : buf.toString(); + } + + abstract int[] compute(Stylesheet stylesheet, Node context, int pos, int len) + throws TransformerException; + + public boolean references(QName var) + { + if (format.references(var)) + { + return true; + } + return super.references(var); + } + + public String toString() + { + CPStringBuilder buf = new CPStringBuilder("number"); + buf.append('['); + buf.append("format="); + buf.append(format); + buf.append(']'); + return buf.toString(); + } + +} -- cgit v1.2.3