From 22c91bc256a30df03db359ab7de5616683a30b17 Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Fri, 25 Sep 2009 14:50:45 +0000 Subject: Some more XML work as I prepare to deal with th... Some more XML work as I prepare to deal with the almost unfixable XML equality situation (sure, I can be equal to four different classes and their four different hashcodes, why do you ask?) --- src/dotnet-library/scala/xml/path/Expression.scala | 1 - src/library/scala/xml/MetaData.scala | 38 +++++------------ src/library/scala/xml/PrettyPrinter.scala | 9 ++-- src/library/scala/xml/ProcInstr.scala | 41 ++++-------------- src/library/scala/xml/Text.scala | 11 +++-- src/library/scala/xml/TextBuffer.scala | 34 ++++++--------- src/library/scala/xml/Unparsed.scala | 3 +- src/library/scala/xml/UnprefixedAttribute.scala | 14 ++----- src/library/scala/xml/path/Expression.scala | 49 ---------------------- src/library/scala/xml/pull/XMLEvent.scala | 1 + .../scala/xml/transform/BasicTransformer.scala | 2 +- 11 files changed, 46 insertions(+), 157 deletions(-) delete mode 100644 src/dotnet-library/scala/xml/path/Expression.scala delete mode 100644 src/library/scala/xml/path/Expression.scala diff --git a/src/dotnet-library/scala/xml/path/Expression.scala b/src/dotnet-library/scala/xml/path/Expression.scala deleted file mode 100644 index 00e8ca63f5..0000000000 --- a/src/dotnet-library/scala/xml/path/Expression.scala +++ /dev/null @@ -1 +0,0 @@ -/* Expression.scala does not exist for the dotnet target */ diff --git a/src/library/scala/xml/MetaData.scala b/src/library/scala/xml/MetaData.scala index 95a1bbbf69..280f2b7871 100644 --- a/src/library/scala/xml/MetaData.scala +++ b/src/library/scala/xml/MetaData.scala @@ -29,28 +29,20 @@ object MetaData { @tailrec def concatenate(attribs: MetaData, new_tail: MetaData): MetaData = if (attribs eq Null) new_tail - else concatenate(attribs.next, attribs.copy(new_tail)) + else concatenate(attribs.next, attribs copy new_tail) /** * returns normalized MetaData, with all duplicates removed and namespace prefixes resolved to * namespace URIs via the given scope. */ def normalize(attribs: MetaData, scope: NamespaceBinding): MetaData = { - import collection.mutable.HashSet - def iterate(md: MetaData, normalized_attribs: MetaData, map: HashSet[String]): MetaData = { - if (md eq Null) - normalized_attribs - else { - val universal_key = getUniversalKey(md, scope) - if (map.contains(universal_key)) - iterate(md.next, normalized_attribs, map) - else { - map += universal_key - iterate(md.next, md.copy(normalized_attribs), map) - } - } + def iterate(md: MetaData, normalized_attribs: MetaData, set: Set[String]): MetaData = { + lazy val key = getUniversalKey(md, scope) + if (md eq Null) normalized_attribs + else if (set(key)) iterate(md.next, normalized_attribs, set) + else iterate(md.next, md copy normalized_attribs, set + key) } - iterate(attribs, Null, new HashSet[String]) + iterate(attribs, Null, Set()) } /** @@ -156,19 +148,9 @@ abstract class MetaData extends Iterable[MetaData] case _ => false } - /** returns an iterator on attributes */ - def iterator: Iterator[MetaData] = new Iterator[MetaData] { - var x: MetaData = MetaData.this - def hasNext = Null != x - def next = { - val y = x - x = x.next - y - } - } - override def size : Int = 1 + { - if (Null == next) 0 else next.size - } + /** Returns an iterator on attributes */ + def iterator: Iterator[MetaData] = Iterator.iterate(this)(_.next) takeWhile (_ != Null) + override def size: Int = 1 + iterator.length /** shallow equals method */ def equals1(that: MetaData): Boolean diff --git a/src/library/scala/xml/PrettyPrinter.scala b/src/library/scala/xml/PrettyPrinter.scala index e97a2e0f59..1753860f50 100644 --- a/src/library/scala/xml/PrettyPrinter.scala +++ b/src/library/scala/xml/PrettyPrinter.scala @@ -25,7 +25,7 @@ import Utility.sbToString * @param width the width to fit the output into * @step indentation */ -class PrettyPrinter( width:Int, step:Int ) { +class PrettyPrinter(width: Int, step: Int) { class BrokenException() extends java.lang.Exception @@ -174,7 +174,7 @@ class PrettyPrinter( width:Int, step:Int ) { val sb = new StringBuilder() Utility.toXML(node, pscope, sb, false) if (doPreserve(node)) sb.toString - else TextBuffer.fromString(sb.toString()).toText(0)._data + else TextBuffer.fromString(sb.toString()).toText(0).data } if (childrenAreLeaves(node) && fits(test)) { makeBox(ind, test) @@ -300,8 +300,5 @@ class PrettyPrinter( width:Int, step:Int ) { * @param sb the string buffer to which to append to */ def formatNodes(nodes: Seq[Node], pscope: NamespaceBinding, sb: StringBuilder): Unit = - for (n <- nodes.iterator) { - sb.append(format(n, pscope)) - } - + nodes foreach (n => sb append format(n, pscope)) } diff --git a/src/library/scala/xml/ProcInstr.scala b/src/library/scala/xml/ProcInstr.scala index a4bff34271..c59e89e9a8 100644 --- a/src/library/scala/xml/ProcInstr.scala +++ b/src/library/scala/xml/ProcInstr.scala @@ -8,7 +8,6 @@ // $Id$ - package scala.xml /** an XML node for processing instructions (PI) @@ -17,50 +16,24 @@ package scala.xml * @param target target name of this PI * @param text text contained in this node, may not contain "?>" */ -case class ProcInstr(target:String, proctext:String) extends SpecialNode +case class ProcInstr(target: String, proctext: String) extends SpecialNode { - if (!Utility.isName(target)) throw new IllegalArgumentException(target+" must be an XML Name") - if (text.indexOf("?>") != -1) + if (proctext contains "?>") throw new IllegalArgumentException(proctext+" may not contain \"?>\"") + if (target.toLowerCase == "xml") + throw new IllegalArgumentException(target+" is reserved") final override def doCollectNamespaces = false final override def doTransform = false - (target: Seq[Char]) match { - case Seq('X'|'x','M'|'m','L'|'l') => - throw new IllegalArgumentException(target+" is reserved") - case _ => - } - - /** structural equality */ - override def equals(x: Any): Boolean = x match { - case ProcInstr(x, y) => x.equals(target) && y.equals(proctext) - case _ => false - } - - /** the constant "#PI" */ - final def label = "#PI" - - /** hashcode for this PI */ - override def hashCode() = target.hashCode() * 7 + proctext.hashCode() - - + final def label = "#PI" override def text = "" /** appends "<?" target (" "+text)?+"?>" * to this stringbuffer. */ - override def buildString(sb: StringBuilder) = { - sb - .append(" 0) { - sb - .append(' ') - .append(proctext); - } - sb.append("?>") - } + override def buildString(sb: StringBuilder) = + sb append "".format(target, (if (proctext.isEmpty) "" else " " + proctext)) } diff --git a/src/library/scala/xml/Text.scala b/src/library/scala/xml/Text.scala index f434d10acf..34001bba70 100644 --- a/src/library/scala/xml/Text.scala +++ b/src/library/scala/xml/Text.scala @@ -11,6 +11,10 @@ package scala.xml +object Text { + def apply(data: String) = new Text(data) + def unapply(other: Any) = other match { case x: Text => Some(x.data) ; case _ => None } +} /** The class Text implements an XML node for text (PCDATA). * It is used in both non-bound and bound XML representations. @@ -19,14 +23,14 @@ package scala.xml * * @param text the text contained in this node, may not be null. */ -case class Text(_data: String) extends Atom[String](_data) +class Text(data: String) extends Atom[String](data) { - if (null == data) + if (data == null) throw new IllegalArgumentException("tried to construct Text with null") + /** XXX More hashCode flailing. */ final override def equals(x: Any) = x match { case s:String => s == data - case s:Text => data == s.data case s:Atom[_] => data == s.data case _ => false } @@ -39,5 +43,4 @@ case class Text(_data: String) extends Atom[String](_data) */ override def buildString(sb: StringBuilder) = Utility.escape(data, sb) - } diff --git a/src/library/scala/xml/TextBuffer.scala b/src/library/scala/xml/TextBuffer.scala index 70635b6135..20c23a6a06 100644 --- a/src/library/scala/xml/TextBuffer.scala +++ b/src/library/scala/xml/TextBuffer.scala @@ -11,9 +11,10 @@ package scala.xml +import Utility.isSpace object TextBuffer { - def fromString(str: String): TextBuffer = new TextBuffer().append(str) + def fromString(str: String): TextBuffer = new TextBuffer() append str } /** The class TextBuffer is for creating text nodes without @@ -21,22 +22,20 @@ object TextBuffer { * appended with the append method will be replaced by a single * space character, and leading and trailing space will be removed completely. */ -class TextBuffer { - +class TextBuffer +{ val sb = new StringBuilder() - var ws = true - - def appendSpace = if(!ws) { ws = true; sb.append(' ') } else {} - def appendChar(c: Char) = { ws = false; sb.append( c ) } /** Appends this string to the text buffer, trimming whitespaces as needed. * * @param cs ... * @return ... */ - def append(cs: Seq[Char]): TextBuffer = { - for (c <- cs) - if (Utility.isSpace(c)) appendSpace else appendChar(c) + def append(cs: Seq[Char]): this.type = { + cs foreach { c => + if (!isSpace(c)) sb append c + else if (sb.isEmpty || !isSpace(sb.last)) sb append ' ' + } this } @@ -44,17 +43,8 @@ class TextBuffer { * * @return the text without whitespaces. */ - def toText: Seq[Text] = { - var len = sb.length /* invariant */ - if (len == 0) return Nil - - if (Utility.isSpace(sb.charAt(len - 1))) { - len -= 1 - sb.length = len - } - if (len == 0) return Nil - - List(Text(sb.toString())) + def toText: Seq[Text] = sb.toString.trim match { + case "" => Nil + case s => Seq(Text(s)) } - } diff --git a/src/library/scala/xml/Unparsed.scala b/src/library/scala/xml/Unparsed.scala index 7ee616f495..08e7f373e9 100644 --- a/src/library/scala/xml/Unparsed.scala +++ b/src/library/scala/xml/Unparsed.scala @@ -22,10 +22,9 @@ class Unparsed(data: String) extends Atom[String](data) if (null == data) throw new IllegalArgumentException("tried to construct Unparsed with null") + /** XXX another hashCode fail */ final override def equals(x: Any) = x match { case s:String => s == data - case s:Text => data == s.data - case s:Unparsed => data == s.data case s:Atom[_] => data == s.data case _ => false } diff --git a/src/library/scala/xml/UnprefixedAttribute.scala b/src/library/scala/xml/UnprefixedAttribute.scala index f82b5698dd..dcc10cd646 100644 --- a/src/library/scala/xml/UnprefixedAttribute.scala +++ b/src/library/scala/xml/UnprefixedAttribute.scala @@ -25,22 +25,19 @@ extends Attribute /** same as this(key, Text(value), next) */ def this(key: String, value: String, next: MetaData) = - this(key, if (value ne null) Text(value) else {val z:NodeSeq=null;z}, next) + this(key, if (value ne null) Text(value) else null: NodeSeq, next) /** same as this(key, value.get, next), or no attribute if value is None */ def this(key: String, value: Option[Seq[Node]], next: MetaData) = - this(key, if (!value.isEmpty) value.get else {val z:NodeSeq=null;z}, next) + this(key, value.orNull, next) /** returns a copy of this unprefixed attribute with the given next field*/ - def copy(next: MetaData) = - new UnprefixedAttribute(key, value, next) + def copy(next: MetaData) = new UnprefixedAttribute(key, value, next) def equals1(m: MetaData) = !m.isPrefixed && (m.key == key) && (m.value sameElements value) - /** returns null */ - final def getNamespace(owner: Node): String = - null + final def getNamespace(owner: Node): String = null /** * Gets value of unqualified (unprefixed) attribute with given key, null if not found @@ -62,12 +59,9 @@ extends Attribute def apply(namespace: String, scope: NamespaceBinding, key: String): Seq[Node] = next(namespace, scope, key) - /** returns the hashcode. - */ override def hashCode() = key.hashCode() * 7 + { if(value ne null) value.hashCode() * 53 else 0 } + next.hashCode() - /** returns false */ final def isPrefixed = false /** appends string representation of only this attribute to stringbuffer. diff --git a/src/library/scala/xml/path/Expression.scala b/src/library/scala/xml/path/Expression.scala deleted file mode 100644 index dce0cd94c2..0000000000 --- a/src/library/scala/xml/path/Expression.scala +++ /dev/null @@ -1,49 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2009, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.xml -package path - -object Expression -{ - final def testFromString(x: String): Test = if (x == "*") WildcardTest else NameTest(x) - private def emptyNodeSeq = new NodeSeq { val theSeq = Nil } - - case class FExp(e:Expr, c:Cond) { - def eval(n: Node): NodeSeq = emptyNodeSeq // @todo - } - - abstract class GenExp - case class Attrib(test: NameTest, e: Expr) extends GenExp - - abstract class Expr extends GenExp { - def \ (x: String) = Child(testFromString(x), this) - def \\ (x: String) = DescOrSelf(testFromString(x), this) - - def apply(c: Cond) = FExp(this, c) - def eval(n: Node): NodeSeq = emptyNodeSeq // @todo - } - - case object Root extends Expr; - - case class Child(test: Test, e: Expr) extends Expr; - case class DescOrSelf(test: Test, e: Expr) extends Expr; - - abstract class Test; - - case object WildcardTest extends Test; // "x \ * " - case class NameTest(label: String) extends Test; // "x \ bar" - - abstract class Cond; - - case class Exists(p: GenExp) extends Cond ; // "p [ p ]" - case class Equals(p: Expr, c:String) extends Cond ; // "p [ @p == bla ]" -} diff --git a/src/library/scala/xml/pull/XMLEvent.scala b/src/library/scala/xml/pull/XMLEvent.scala index a2177d61c9..0f6edfad52 100644 --- a/src/library/scala/xml/pull/XMLEvent.scala +++ b/src/library/scala/xml/pull/XMLEvent.scala @@ -24,6 +24,7 @@ case class EvElemStart(pre: String, label: String, attrs: MetaData, scope: Names /** An element is encountered the last time */ case class EvElemEnd(pre: String, label: String) extends XMLEvent + /** A text node is encountered */ case class EvText(text: String) extends XMLEvent diff --git a/src/library/scala/xml/transform/BasicTransformer.scala b/src/library/scala/xml/transform/BasicTransformer.scala index 6b01871397..f3a4d10a33 100644 --- a/src/library/scala/xml/transform/BasicTransformer.scala +++ b/src/library/scala/xml/transform/BasicTransformer.scala @@ -51,7 +51,7 @@ abstract class BasicTransformer extends Function1[Node,Node] val nch = transform(ch) if (ch eq nch) n - else Elem(n.prefix, n.label, n.attributes, n.scope, nch:_*) + else Elem(n.prefix, n.label, n.attributes, n.scope, nch: _*) } else n } -- cgit v1.2.3