From c05a0b7a4953f5b835441bf3fca1806f842a3935 Mon Sep 17 00:00:00 2001 From: Geoffrey Washburn Date: Mon, 7 Apr 2008 12:23:22 +0000 Subject: More reorg. --- .../jvm/scala/collection/jcl/ArrayList.scala | 21 - src/library/jvm/scala/collection/jcl/Buffer.scala | 229 ---- .../jvm/scala/collection/jcl/BufferIterator.scala | 31 - .../jvm/scala/collection/jcl/BufferWrapper.scala | 52 - .../jvm/scala/collection/jcl/Collection.scala | 67 -- .../scala/collection/jcl/CollectionWrapper.scala | 43 - .../jvm/scala/collection/jcl/Conversions.scala | 17 - src/library/jvm/scala/collection/jcl/HashMap.scala | 21 - src/library/jvm/scala/collection/jcl/HashSet.scala | 21 - .../jvm/scala/collection/jcl/Hashtable.scala | 22 - .../jvm/scala/collection/jcl/IdentityHashMap.scala | 24 - .../jvm/scala/collection/jcl/IterableWrapper.scala | 32 - .../jvm/scala/collection/jcl/LinkedHashMap.scala | 22 - .../jvm/scala/collection/jcl/LinkedHashSet.scala | 22 - .../jvm/scala/collection/jcl/LinkedList.scala | 32 - src/library/jvm/scala/collection/jcl/Map.scala | 129 --- .../jvm/scala/collection/jcl/MapWrapper.scala | 76 -- .../jvm/scala/collection/jcl/MutableIterable.scala | 110 -- .../jvm/scala/collection/jcl/MutableIterator.scala | 70 -- .../jvm/scala/collection/jcl/MutableSeq.scala | 123 -- src/library/jvm/scala/collection/jcl/Ranged.scala | 54 - .../jvm/scala/collection/jcl/SeqIterator.scala | 58 - src/library/jvm/scala/collection/jcl/Set.scala | 72 -- .../jvm/scala/collection/jcl/SetWrapper.scala | 22 - src/library/jvm/scala/collection/jcl/Sorted.scala | 46 - .../jvm/scala/collection/jcl/SortedMap.scala | 103 -- .../scala/collection/jcl/SortedMapWrapper.scala | 39 - .../jvm/scala/collection/jcl/SortedSet.scala | 99 -- .../scala/collection/jcl/SortedSetWrapper.scala | 39 - src/library/jvm/scala/collection/jcl/Tests.scala | 79 -- src/library/jvm/scala/collection/jcl/TreeMap.scala | 24 - src/library/jvm/scala/collection/jcl/TreeSet.scala | 26 - .../jvm/scala/collection/jcl/WeakHashMap.scala | 31 - .../scala/collection/mutable/JavaMapAdaptor.scala | 69 -- .../scala/collection/mutable/JavaSetAdaptor.scala | 47 - src/library/jvm/scala/concurrent/ops.scala | 78 -- src/library/jvm/scala/io/BufferedSource.scala | 98 -- src/library/jvm/scala/io/Source.scala | 400 ------- src/library/jvm/scala/reflect/BeanInfo.scala | 22 - src/library/jvm/scala/reflect/BeanProperty.scala | 33 - src/library/jvm/scala/reflect/ScalaBeanInfo.scala | 47 - src/library/jvm/scala/runtime/BooleanRef.java | 21 - src/library/jvm/scala/runtime/BoxedUnit.java | 33 - src/library/jvm/scala/runtime/BoxesRunTime.java | 845 -------------- src/library/jvm/scala/runtime/ByteRef.java | 21 - src/library/jvm/scala/runtime/CharRef.java | 21 - src/library/jvm/scala/runtime/DoubleRef.java | 21 - .../jvm/scala/runtime/ExceptionHandling.java | 26 - src/library/jvm/scala/runtime/FloatRef.java | 21 - src/library/jvm/scala/runtime/IntRef.java | 21 - src/library/jvm/scala/runtime/LongRef.java | 21 - src/library/jvm/scala/runtime/ObjectRef.java | 21 - src/library/jvm/scala/runtime/RichChar.scala | 71 -- src/library/jvm/scala/runtime/RichDouble.scala | 54 - src/library/jvm/scala/runtime/RichFloat.scala | 56 - src/library/jvm/scala/runtime/RichInt.scala | 39 - src/library/jvm/scala/runtime/RichLong.scala | 30 - src/library/jvm/scala/runtime/RichString.scala | 245 ---- src/library/jvm/scala/runtime/ShortRef.java | 20 - src/library/jvm/scala/runtime/StringAdd.scala | 41 - src/library/jvm/scala/util/DynamicVariable.scala | 84 -- src/library/jvm/scala/util/Properties.scala | 57 - src/library/jvm/scala/util/matching/Regex.scala | 274 ----- .../util/parsing/CharInputStreamIterator.scala | 52 - .../util/parsing/combinator/RegexParsers.scala | 84 -- .../scala/util/parsing/input/StreamReader.scala | 74 -- src/library/jvm/scala/xml/Parsing.scala | 105 -- src/library/jvm/scala/xml/PrettyPrinter.scala | 308 ----- src/library/jvm/scala/xml/Text.scala | 42 - src/library/jvm/scala/xml/Unparsed.scala | 35 - src/library/jvm/scala/xml/XML.scala | 158 --- .../jvm/scala/xml/include/XIncludeException.scala | 64 -- .../xml/include/parsing/ConstructingParser.scala | 67 -- .../xml/include/parsing/ExternalSources.scala | 82 -- .../scala/xml/include/parsing/FactoryAdapter.scala | 321 ------ .../jvm/scala/xml/include/parsing/FatalError.scala | 15 - .../scala/xml/include/parsing/MarkupParser.scala | 1215 -------------------- .../include/parsing/NoBindingFactoryAdapter.scala | 62 - .../jvm/scala/xml/include/parsing/TokenTests.scala | 146 --- .../xml/include/persistent/CachedFileStorage.scala | 123 -- .../xml/include/persistent/IndexedStorage.scala | 48 - .../scala/xml/include/persistent/SetStorage.scala | 43 - .../scala/xml/include/pull/XMLEventReader.scala | 133 --- .../scala/xml/include/sax/EncodingHeuristics.scala | 177 --- .../jvm/scala/xml/include/sax/XIncludeFilter.scala | 422 ------- .../jvm/scala/xml/include/sax/XIncluder.scala | 201 ---- src/library/scala/collection/jcl/ArrayList.scala | 21 + src/library/scala/collection/jcl/Buffer.scala | 229 ++++ .../scala/collection/jcl/BufferIterator.scala | 31 + .../scala/collection/jcl/BufferWrapper.scala | 52 + src/library/scala/collection/jcl/Collection.scala | 67 ++ .../scala/collection/jcl/CollectionWrapper.scala | 43 + src/library/scala/collection/jcl/Conversions.scala | 17 + src/library/scala/collection/jcl/HashMap.scala | 21 + src/library/scala/collection/jcl/HashSet.scala | 21 + src/library/scala/collection/jcl/Hashtable.scala | 22 + .../scala/collection/jcl/IdentityHashMap.scala | 24 + .../scala/collection/jcl/IterableWrapper.scala | 32 + .../scala/collection/jcl/LinkedHashMap.scala | 22 + .../scala/collection/jcl/LinkedHashSet.scala | 22 + src/library/scala/collection/jcl/LinkedList.scala | 32 + src/library/scala/collection/jcl/Map.scala | 129 +++ src/library/scala/collection/jcl/MapWrapper.scala | 76 ++ .../scala/collection/jcl/MutableIterable.scala | 110 ++ .../scala/collection/jcl/MutableIterator.scala | 70 ++ src/library/scala/collection/jcl/MutableSeq.scala | 123 ++ src/library/scala/collection/jcl/Ranged.scala | 54 + src/library/scala/collection/jcl/SeqIterator.scala | 58 + src/library/scala/collection/jcl/Set.scala | 72 ++ src/library/scala/collection/jcl/SetWrapper.scala | 22 + src/library/scala/collection/jcl/Sorted.scala | 46 + src/library/scala/collection/jcl/SortedMap.scala | 103 ++ .../scala/collection/jcl/SortedMapWrapper.scala | 39 + src/library/scala/collection/jcl/SortedSet.scala | 99 ++ .../scala/collection/jcl/SortedSetWrapper.scala | 39 + src/library/scala/collection/jcl/Tests.scala | 79 ++ src/library/scala/collection/jcl/TreeMap.scala | 24 + src/library/scala/collection/jcl/TreeSet.scala | 26 + src/library/scala/collection/jcl/WeakHashMap.scala | 31 + .../scala/collection/mutable/JavaMapAdaptor.scala | 69 ++ .../scala/collection/mutable/JavaSetAdaptor.scala | 47 + src/library/scala/concurrent/ops.scala | 78 ++ src/library/scala/io/BufferedSource.scala | 98 ++ src/library/scala/io/Source.scala | 400 +++++++ src/library/scala/reflect/BeanInfo.scala | 22 + src/library/scala/reflect/BeanProperty.scala | 33 + src/library/scala/reflect/ScalaBeanInfo.scala | 47 + src/library/scala/runtime/BooleanRef.java | 21 + src/library/scala/runtime/BoxedUnit.java | 33 + src/library/scala/runtime/BoxesRunTime.java | 845 ++++++++++++++ src/library/scala/runtime/ByteRef.java | 21 + src/library/scala/runtime/CharRef.java | 21 + src/library/scala/runtime/DoubleRef.java | 21 + src/library/scala/runtime/ExceptionHandling.java | 26 + src/library/scala/runtime/FloatRef.java | 21 + src/library/scala/runtime/IntRef.java | 21 + src/library/scala/runtime/LongRef.java | 21 + src/library/scala/runtime/ObjectRef.java | 21 + src/library/scala/runtime/RichChar.scala | 71 ++ src/library/scala/runtime/RichDouble.scala | 54 + src/library/scala/runtime/RichFloat.scala | 56 + src/library/scala/runtime/RichInt.scala | 39 + src/library/scala/runtime/RichLong.scala | 30 + src/library/scala/runtime/RichString.scala | 245 ++++ src/library/scala/runtime/ShortRef.java | 20 + src/library/scala/runtime/StringAdd.scala | 41 + src/library/scala/util/DynamicVariable.scala | 84 ++ src/library/scala/util/Properties.scala | 57 + src/library/scala/util/matching/Regex.scala | 274 +++++ .../util/parsing/CharInputStreamIterator.scala | 52 + .../util/parsing/combinator/RegexParsers.scala | 84 ++ .../scala/util/parsing/input/StreamReader.scala | 74 ++ src/library/scala/xml/Parsing.scala | 105 ++ src/library/scala/xml/PrettyPrinter.scala | 308 +++++ src/library/scala/xml/Text.scala | 42 + src/library/scala/xml/Unparsed.scala | 35 + src/library/scala/xml/XML.scala | 158 +++ .../scala/xml/include/XIncludeException.scala | 64 ++ .../xml/include/parsing/ConstructingParser.scala | 67 ++ .../xml/include/parsing/ExternalSources.scala | 82 ++ .../scala/xml/include/parsing/FactoryAdapter.scala | 321 ++++++ .../scala/xml/include/parsing/FatalError.scala | 15 + .../scala/xml/include/parsing/MarkupParser.scala | 1215 ++++++++++++++++++++ .../include/parsing/NoBindingFactoryAdapter.scala | 62 + .../scala/xml/include/parsing/TokenTests.scala | 146 +++ .../xml/include/persistent/CachedFileStorage.scala | 123 ++ .../xml/include/persistent/IndexedStorage.scala | 48 + .../scala/xml/include/persistent/SetStorage.scala | 43 + .../scala/xml/include/pull/XMLEventReader.scala | 133 +++ .../scala/xml/include/sax/EncodingHeuristics.scala | 177 +++ .../scala/xml/include/sax/XIncludeFilter.scala | 422 +++++++ src/library/scala/xml/include/sax/XIncluder.scala | 201 ++++ 172 files changed, 8670 insertions(+), 8670 deletions(-) delete mode 100644 src/library/jvm/scala/collection/jcl/ArrayList.scala delete mode 100644 src/library/jvm/scala/collection/jcl/Buffer.scala delete mode 100644 src/library/jvm/scala/collection/jcl/BufferIterator.scala delete mode 100644 src/library/jvm/scala/collection/jcl/BufferWrapper.scala delete mode 100644 src/library/jvm/scala/collection/jcl/Collection.scala delete mode 100644 src/library/jvm/scala/collection/jcl/CollectionWrapper.scala delete mode 100644 src/library/jvm/scala/collection/jcl/Conversions.scala delete mode 100644 src/library/jvm/scala/collection/jcl/HashMap.scala delete mode 100644 src/library/jvm/scala/collection/jcl/HashSet.scala delete mode 100644 src/library/jvm/scala/collection/jcl/Hashtable.scala delete mode 100644 src/library/jvm/scala/collection/jcl/IdentityHashMap.scala delete mode 100644 src/library/jvm/scala/collection/jcl/IterableWrapper.scala delete mode 100644 src/library/jvm/scala/collection/jcl/LinkedHashMap.scala delete mode 100644 src/library/jvm/scala/collection/jcl/LinkedHashSet.scala delete mode 100644 src/library/jvm/scala/collection/jcl/LinkedList.scala delete mode 100644 src/library/jvm/scala/collection/jcl/Map.scala delete mode 100644 src/library/jvm/scala/collection/jcl/MapWrapper.scala delete mode 100644 src/library/jvm/scala/collection/jcl/MutableIterable.scala delete mode 100644 src/library/jvm/scala/collection/jcl/MutableIterator.scala delete mode 100644 src/library/jvm/scala/collection/jcl/MutableSeq.scala delete mode 100644 src/library/jvm/scala/collection/jcl/Ranged.scala delete mode 100644 src/library/jvm/scala/collection/jcl/SeqIterator.scala delete mode 100644 src/library/jvm/scala/collection/jcl/Set.scala delete mode 100644 src/library/jvm/scala/collection/jcl/SetWrapper.scala delete mode 100644 src/library/jvm/scala/collection/jcl/Sorted.scala delete mode 100644 src/library/jvm/scala/collection/jcl/SortedMap.scala delete mode 100644 src/library/jvm/scala/collection/jcl/SortedMapWrapper.scala delete mode 100644 src/library/jvm/scala/collection/jcl/SortedSet.scala delete mode 100644 src/library/jvm/scala/collection/jcl/SortedSetWrapper.scala delete mode 100644 src/library/jvm/scala/collection/jcl/Tests.scala delete mode 100644 src/library/jvm/scala/collection/jcl/TreeMap.scala delete mode 100644 src/library/jvm/scala/collection/jcl/TreeSet.scala delete mode 100644 src/library/jvm/scala/collection/jcl/WeakHashMap.scala delete mode 100644 src/library/jvm/scala/collection/mutable/JavaMapAdaptor.scala delete mode 100644 src/library/jvm/scala/collection/mutable/JavaSetAdaptor.scala delete mode 100644 src/library/jvm/scala/concurrent/ops.scala delete mode 100644 src/library/jvm/scala/io/BufferedSource.scala delete mode 100644 src/library/jvm/scala/io/Source.scala delete mode 100644 src/library/jvm/scala/reflect/BeanInfo.scala delete mode 100644 src/library/jvm/scala/reflect/BeanProperty.scala delete mode 100644 src/library/jvm/scala/reflect/ScalaBeanInfo.scala delete mode 100644 src/library/jvm/scala/runtime/BooleanRef.java delete mode 100644 src/library/jvm/scala/runtime/BoxedUnit.java delete mode 100644 src/library/jvm/scala/runtime/BoxesRunTime.java delete mode 100644 src/library/jvm/scala/runtime/ByteRef.java delete mode 100644 src/library/jvm/scala/runtime/CharRef.java delete mode 100644 src/library/jvm/scala/runtime/DoubleRef.java delete mode 100644 src/library/jvm/scala/runtime/ExceptionHandling.java delete mode 100644 src/library/jvm/scala/runtime/FloatRef.java delete mode 100644 src/library/jvm/scala/runtime/IntRef.java delete mode 100644 src/library/jvm/scala/runtime/LongRef.java delete mode 100644 src/library/jvm/scala/runtime/ObjectRef.java delete mode 100644 src/library/jvm/scala/runtime/RichChar.scala delete mode 100644 src/library/jvm/scala/runtime/RichDouble.scala delete mode 100644 src/library/jvm/scala/runtime/RichFloat.scala delete mode 100644 src/library/jvm/scala/runtime/RichInt.scala delete mode 100644 src/library/jvm/scala/runtime/RichLong.scala delete mode 100644 src/library/jvm/scala/runtime/RichString.scala delete mode 100644 src/library/jvm/scala/runtime/ShortRef.java delete mode 100644 src/library/jvm/scala/runtime/StringAdd.scala delete mode 100644 src/library/jvm/scala/util/DynamicVariable.scala delete mode 100644 src/library/jvm/scala/util/Properties.scala delete mode 100644 src/library/jvm/scala/util/matching/Regex.scala delete mode 100644 src/library/jvm/scala/util/parsing/CharInputStreamIterator.scala delete mode 100644 src/library/jvm/scala/util/parsing/combinator/RegexParsers.scala delete mode 100644 src/library/jvm/scala/util/parsing/input/StreamReader.scala delete mode 100644 src/library/jvm/scala/xml/Parsing.scala delete mode 100644 src/library/jvm/scala/xml/PrettyPrinter.scala delete mode 100644 src/library/jvm/scala/xml/Text.scala delete mode 100644 src/library/jvm/scala/xml/Unparsed.scala delete mode 100644 src/library/jvm/scala/xml/XML.scala delete mode 100644 src/library/jvm/scala/xml/include/XIncludeException.scala delete mode 100644 src/library/jvm/scala/xml/include/parsing/ConstructingParser.scala delete mode 100644 src/library/jvm/scala/xml/include/parsing/ExternalSources.scala delete mode 100644 src/library/jvm/scala/xml/include/parsing/FactoryAdapter.scala delete mode 100644 src/library/jvm/scala/xml/include/parsing/FatalError.scala delete mode 100644 src/library/jvm/scala/xml/include/parsing/MarkupParser.scala delete mode 100644 src/library/jvm/scala/xml/include/parsing/NoBindingFactoryAdapter.scala delete mode 100644 src/library/jvm/scala/xml/include/parsing/TokenTests.scala delete mode 100644 src/library/jvm/scala/xml/include/persistent/CachedFileStorage.scala delete mode 100644 src/library/jvm/scala/xml/include/persistent/IndexedStorage.scala delete mode 100644 src/library/jvm/scala/xml/include/persistent/SetStorage.scala delete mode 100644 src/library/jvm/scala/xml/include/pull/XMLEventReader.scala delete mode 100644 src/library/jvm/scala/xml/include/sax/EncodingHeuristics.scala delete mode 100644 src/library/jvm/scala/xml/include/sax/XIncludeFilter.scala delete mode 100644 src/library/jvm/scala/xml/include/sax/XIncluder.scala create mode 100644 src/library/scala/collection/jcl/ArrayList.scala create mode 100644 src/library/scala/collection/jcl/Buffer.scala create mode 100644 src/library/scala/collection/jcl/BufferIterator.scala create mode 100644 src/library/scala/collection/jcl/BufferWrapper.scala create mode 100644 src/library/scala/collection/jcl/Collection.scala create mode 100644 src/library/scala/collection/jcl/CollectionWrapper.scala create mode 100644 src/library/scala/collection/jcl/Conversions.scala create mode 100644 src/library/scala/collection/jcl/HashMap.scala create mode 100644 src/library/scala/collection/jcl/HashSet.scala create mode 100644 src/library/scala/collection/jcl/Hashtable.scala create mode 100644 src/library/scala/collection/jcl/IdentityHashMap.scala create mode 100644 src/library/scala/collection/jcl/IterableWrapper.scala create mode 100644 src/library/scala/collection/jcl/LinkedHashMap.scala create mode 100644 src/library/scala/collection/jcl/LinkedHashSet.scala create mode 100644 src/library/scala/collection/jcl/LinkedList.scala create mode 100644 src/library/scala/collection/jcl/Map.scala create mode 100644 src/library/scala/collection/jcl/MapWrapper.scala create mode 100644 src/library/scala/collection/jcl/MutableIterable.scala create mode 100644 src/library/scala/collection/jcl/MutableIterator.scala create mode 100644 src/library/scala/collection/jcl/MutableSeq.scala create mode 100644 src/library/scala/collection/jcl/Ranged.scala create mode 100644 src/library/scala/collection/jcl/SeqIterator.scala create mode 100644 src/library/scala/collection/jcl/Set.scala create mode 100644 src/library/scala/collection/jcl/SetWrapper.scala create mode 100644 src/library/scala/collection/jcl/Sorted.scala create mode 100644 src/library/scala/collection/jcl/SortedMap.scala create mode 100644 src/library/scala/collection/jcl/SortedMapWrapper.scala create mode 100644 src/library/scala/collection/jcl/SortedSet.scala create mode 100644 src/library/scala/collection/jcl/SortedSetWrapper.scala create mode 100644 src/library/scala/collection/jcl/Tests.scala create mode 100644 src/library/scala/collection/jcl/TreeMap.scala create mode 100644 src/library/scala/collection/jcl/TreeSet.scala create mode 100644 src/library/scala/collection/jcl/WeakHashMap.scala create mode 100644 src/library/scala/collection/mutable/JavaMapAdaptor.scala create mode 100644 src/library/scala/collection/mutable/JavaSetAdaptor.scala create mode 100644 src/library/scala/concurrent/ops.scala create mode 100644 src/library/scala/io/BufferedSource.scala create mode 100644 src/library/scala/io/Source.scala create mode 100644 src/library/scala/reflect/BeanInfo.scala create mode 100644 src/library/scala/reflect/BeanProperty.scala create mode 100644 src/library/scala/reflect/ScalaBeanInfo.scala create mode 100644 src/library/scala/runtime/BooleanRef.java create mode 100644 src/library/scala/runtime/BoxedUnit.java create mode 100644 src/library/scala/runtime/BoxesRunTime.java create mode 100644 src/library/scala/runtime/ByteRef.java create mode 100644 src/library/scala/runtime/CharRef.java create mode 100644 src/library/scala/runtime/DoubleRef.java create mode 100644 src/library/scala/runtime/ExceptionHandling.java create mode 100644 src/library/scala/runtime/FloatRef.java create mode 100644 src/library/scala/runtime/IntRef.java create mode 100644 src/library/scala/runtime/LongRef.java create mode 100644 src/library/scala/runtime/ObjectRef.java create mode 100644 src/library/scala/runtime/RichChar.scala create mode 100644 src/library/scala/runtime/RichDouble.scala create mode 100644 src/library/scala/runtime/RichFloat.scala create mode 100644 src/library/scala/runtime/RichInt.scala create mode 100644 src/library/scala/runtime/RichLong.scala create mode 100644 src/library/scala/runtime/RichString.scala create mode 100644 src/library/scala/runtime/ShortRef.java create mode 100644 src/library/scala/runtime/StringAdd.scala create mode 100644 src/library/scala/util/DynamicVariable.scala create mode 100644 src/library/scala/util/Properties.scala create mode 100644 src/library/scala/util/matching/Regex.scala create mode 100644 src/library/scala/util/parsing/CharInputStreamIterator.scala create mode 100644 src/library/scala/util/parsing/combinator/RegexParsers.scala create mode 100644 src/library/scala/util/parsing/input/StreamReader.scala create mode 100644 src/library/scala/xml/Parsing.scala create mode 100644 src/library/scala/xml/PrettyPrinter.scala create mode 100644 src/library/scala/xml/Text.scala create mode 100644 src/library/scala/xml/Unparsed.scala create mode 100644 src/library/scala/xml/XML.scala create mode 100644 src/library/scala/xml/include/XIncludeException.scala create mode 100644 src/library/scala/xml/include/parsing/ConstructingParser.scala create mode 100644 src/library/scala/xml/include/parsing/ExternalSources.scala create mode 100644 src/library/scala/xml/include/parsing/FactoryAdapter.scala create mode 100644 src/library/scala/xml/include/parsing/FatalError.scala create mode 100644 src/library/scala/xml/include/parsing/MarkupParser.scala create mode 100644 src/library/scala/xml/include/parsing/NoBindingFactoryAdapter.scala create mode 100644 src/library/scala/xml/include/parsing/TokenTests.scala create mode 100644 src/library/scala/xml/include/persistent/CachedFileStorage.scala create mode 100644 src/library/scala/xml/include/persistent/IndexedStorage.scala create mode 100644 src/library/scala/xml/include/persistent/SetStorage.scala create mode 100644 src/library/scala/xml/include/pull/XMLEventReader.scala create mode 100644 src/library/scala/xml/include/sax/EncodingHeuristics.scala create mode 100644 src/library/scala/xml/include/sax/XIncludeFilter.scala create mode 100644 src/library/scala/xml/include/sax/XIncluder.scala (limited to 'src') diff --git a/src/library/jvm/scala/collection/jcl/ArrayList.scala b/src/library/jvm/scala/collection/jcl/ArrayList.scala deleted file mode 100644 index bd54d46a69..0000000000 --- a/src/library/jvm/scala/collection/jcl/ArrayList.scala +++ /dev/null @@ -1,21 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl; - -/** Creates a buffer backed by a Java array list. - * - * @author Sean McDirmid - */ -class ArrayList[A](override val underlying : java.util.ArrayList[A]) extends BufferWrapper[A] { - def this() = this(new java.util.ArrayList[A]); - override def clone: ArrayList[A] = - new ArrayList[A](underlying.clone().asInstanceOf[java.util.ArrayList[A]]) -} diff --git a/src/library/jvm/scala/collection/jcl/Buffer.scala b/src/library/jvm/scala/collection/jcl/Buffer.scala deleted file mode 100644 index dfc36765d3..0000000000 --- a/src/library/jvm/scala/collection/jcl/Buffer.scala +++ /dev/null @@ -1,229 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl; - -/** A mutable sequence that supports element insertion and update. - * - * @author Sean McDirmid - */ -trait Buffer[A] extends RandomAccessSeq.Mutable[A] with Ranged[Int,A] with MutableSeq[A] with Collection[A] { - final protected type SortedSelf = Buffer[A]; - - override def projection : Buffer.Projection[A] = new Buffer.Projection[A] { - override def elements = Buffer.this.elements - override def length = Buffer.this.length - override def apply(idx : Int) = Buffer.this.apply(idx) - override def transform(f : A => A) = Buffer.this.transform(f) - } - - protected class DefaultBufferIterator extends DefaultSeqIterator with BufferIterator[Int,A] { - override def set(a : A) = { - if (index == 0) throw new NoSuchElementException - Buffer.this.set(index - 1, a) - } - override def add(a : A) = { - Buffer.this.add(index, a) - } - } - override def elements : BufferIterator[Int,A] = new DefaultBufferIterator - - /** The first index of a buffer is 0. */ - override def firstKey = 0; - - /** The last index of a buffer is its size - 1. */ - override def lastKey = size - 1; - - /** Indices are compared through subtraction. */ - final def compare(k0 : Int, k1 : Int) = k0 - k1; - - /** Removes the element at index idx */ - def remove(idx : Int) = { - val i = elements; - val ret = i.seek(idx); i.remove; ret; - } - /** Removes N elements from index idx */ - def remove(idx : Int, length : Int) = { - val i = elements - i.seek(idx) - for (j <- 0.until(length)) i.remove - } - /** replaces */ - def replace(from : Int, length : Int, added : Seq[A]) = { - val min = if (length < added.length) length else added.length - val i = added.elements - var j = 0 - while (j < length && i.hasNext) { - set(from + j, i.next); j = j + 1 - } - assert(j == min) - if (i.hasNext) { - val slice = added.drop(length) - assert(!slice.isEmpty) - addAll(from + min, slice) - } else if (j < length) { - assert(length > min) - remove(from + min, length - min) - } - } - - /** Replaces the element at index "idx" with "a." - * @returns the element replaced. - */ - def set(idx : Int, a : A) : A = { - val i = elements; - val ret = i.seek(idx); i.set(a); ret; - } - - /** Equivalent to set except the replaced element is not returned. */ - def update(idx : Int, a : A) : Unit = set(idx, a); - - /** @returns always true. */ - def add(a : A) : Boolean = { - val i = elements; - while (i.hasNext) i.next; - i.add(a); - true; - } - - /** Inserts "a" into this buffer just before the element at index "idx." */ - def add(idx: Int, a: A): Unit = { - val i = elements; i.seek(idx); - i.add(a); - } - - /** Inserts all elements of that into this buffer just before - * the element at index idx. - * - * @param idx .. - * @param that .. - */ - def addAll(idx: Int, that: Iterable[A]): Unit = { - val i = elements; i.seek(idx); - for (that <- that) { - i.add(that); i.next; - } - } - - override def transform(f: A => A): Boolean = { - var changed = false; - val i = elements; - while (i.hasNext) { - val a0 = i.next; - val a1 = f(a0); - if (a0 != a1) { - i.set(a1); changed = true; - } - } - changed; - } - override def +(a : A) : this.type = super[Collection].+(a); - override def -=(a : A) = super[Collection].-=(a); - override def isEmpty = super[MutableSeq].isEmpty; - override def rangeImpl(from : Option[Int], until : Option[Int]) : Buffer[A] = new Range(from, until); - - - protected class Range(var from : Option[Int], var until : Option[Int]) extends Buffer[A] { - if (from == None && until == None) throw new IllegalArgumentException; - if (from != None && until != None && !(from.get < until.get)) throw new IllegalArgumentException; - override def add(a : A) = - if (until == None) Buffer.this.add(a); - else { - Buffer.this.add(until.get, a); - true; - } - private def translate(idx : Int) = { - if (until != None && idx > until.get) throw new IllegalArgumentException; - else if (from != None) from.get + idx; - else idx; - } - override def apply(idx : Int) : A = Buffer.this.apply(translate(idx)); - override def set(idx : Int, a : A) = Buffer.this.set(translate(idx), a); - override def add(idx : Int, a : A) = Buffer.this.add(translate(idx), a); - override def remove(idx : Int) = Buffer.this.remove(translate(idx)); - override def length = { - if (until != None) { - if (from != None) until.get - from.get; - else until.get; - } else super.length; - } - override def elements : BufferIterator[Int,A] = new RangeIterator; - class RangeIterator extends BufferIterator[Int,A] { - val underlying = Buffer.this.elements; - if (from != None) underlying.seek(from.get); - def hasNext = underlying.hasNext && - (until == None || underlying.nextIndex < until.get); - def hasPrevious = underlying.hasPrevious && - (from == None || underlying.previousIndex >= from.get); - def next = { - if (until != None && underlying.nextIndex >= until.get) throw new NoSuchElementException; - underlying.next; - } - def previous = { - if (from != None && underlying.previousIndex < from.get) throw new NoSuchElementException; - underlying.previous; - } - def add(a : A) = { - if (until != None && underlying.nextIndex > until.get) throw new NoSuchElementException; - if (from != None && underlying.previousIndex < from.get) throw new NoSuchElementException; - underlying.add(a); - if (until != None) until = Some(until.get + 1); - } - def set(a : A) = { - if (until != None && underlying.nextIndex > until.get) throw new NoSuchElementException; - if (from != None && underlying.previousIndex < from.get) throw new NoSuchElementException; - underlying.set(a); - } - def remove = { - if (until != None && underlying.nextIndex > until.get) throw new NoSuchElementException; - if (from != None && underlying.previousIndex < from.get) throw new NoSuchElementException; - underlying.remove; - } - def nextIndex = { - val ret = underlying.nextIndex; - if (until != None && ret >= until.get) throw new NoSuchElementException; - if (from != None) ret - from.get; - else ret; - } - def previousIndex = { - val ret = underlying.previousIndex; - if (from != None && ret < from.get) throw new NoSuchElementException; - if (from != None) ret - from.get; - else ret; - } - } - } - /* - protected class Map[B](f : A => B) extends super.Map[B](f) with Buffer.Projection[B] { - override def elements = Buffer.this.elements.map[B](f); - //override def apply(idx : Int) = f(MutableSeq.this.apply(idx)); - //override def size = length; - } - */ -} -object Buffer { - def apply[T](list : java.util.List[T]) = new BufferWrapper[T] { - val underlying = list - } - - trait Projection0[A] extends MutableSeq.Projection[A] with RandomAccessSeq.Projection[A] { - override def projection : Projection0[A] = this - override def elements : SeqIterator[Int,A] = new DefaultSeqIterator - - protected class MapProjection[B](f : A => B) extends super.MapProjection[B](f) with Projection0[B] { - override def projection = this - } - override def map[B](f: A => B) : Projection0[B] = new MapProjection[B](f) - } - class Projection[A] extends Collection.Projection[A] with RandomAccessSeq.MutableProjection[A] with Projection0[A] with Buffer[A] { - override def elements : BufferIterator[Int,A] = new DefaultBufferIterator - override def projection : Buffer.Projection[A] = this - } -} diff --git a/src/library/jvm/scala/collection/jcl/BufferIterator.scala b/src/library/jvm/scala/collection/jcl/BufferIterator.scala deleted file mode 100644 index bb7b79d099..0000000000 --- a/src/library/jvm/scala/collection/jcl/BufferIterator.scala +++ /dev/null @@ -1,31 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl; - -/** An iterator for a buffer that supports element update and insertion. - * - * @author Sean McDirmid - */ -trait BufferIterator[K,A] extends SeqIterator[K,A] { - - /** Sets the element before this iterator's cursor to "a." - * Replaces either the last element returned by "next" or, - * if previous was called, - * the next element that would be return by "previous." - */ - def set(a: A): Unit; - - /** Inserts "a" after the iterator's cursor. - * If next was last called, "a" is inserted after the element returned. - * If previous was last called, "a" is inserted before the element returned. - */ - def add(a: A): Unit; -} diff --git a/src/library/jvm/scala/collection/jcl/BufferWrapper.scala b/src/library/jvm/scala/collection/jcl/BufferWrapper.scala deleted file mode 100644 index 0472c15dea..0000000000 --- a/src/library/jvm/scala/collection/jcl/BufferWrapper.scala +++ /dev/null @@ -1,52 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl; - -/** Wraps Java lists. - * - * @author Sean McDirmid - */ -trait BufferWrapper[A] extends Buffer[A] with CollectionWrapper[A] { - def underlying : java.util.List[A]; - override def elements : BufferIterator[Int,A] = new IteratorWrapper(underlying.listIterator); - override def remove(idx : Int) = underlying.remove(idx).asInstanceOf[A]; - override def add(a : A) = underlying.add(a); - override def add(idx : Int, a : A) = underlying.add(idx,a); - override def addAll(idx : Int, that : Iterable[A]) = that match { - case that : CollectionWrapper[_] => underlying.addAll(idx, that.underlying); {} - case _ => super.addAll(idx, that); - } - override def indexOf(a : A) = { - val result = underlying.indexOf(a); - if (result == -1) None; - else Some(result); - } - override def apply(idx : Int) = underlying.get(idx).asInstanceOf[A]; - override def set(idx : Int, a : A) = underlying.set(idx, a).asInstanceOf[A]; - override def rangeImpl(from : Option[Int], until : Option[Int]) : Buffer[A] = new Range(from, until); - protected class Range(from : Option[Int], until : Option[Int]) extends super.Range(from,until) with BufferWrapper[A] { - val underlying = { - val fromi = if (from == None) 0 else from.get; - val toi = if (until == None) BufferWrapper.this.size else until.get; - BufferWrapper.this.underlying.subList(fromi, toi); - } - override def elements = super[BufferWrapper].elements; - } - class IteratorWrapper(underlying : java.util.ListIterator[A]) extends MutableIterator.Wrapper[A](underlying) with BufferIterator[Int,A] { - def add(a : A) = underlying.add(a); - def set(a : A) = underlying.set(a); - def hasPrevious = underlying.hasPrevious; - def previous = underlying.previous.asInstanceOf[A]; - def previousIndex = underlying.previousIndex; - def nextIndex = underlying.nextIndex; - } - override def length = underlying.size; -} diff --git a/src/library/jvm/scala/collection/jcl/Collection.scala b/src/library/jvm/scala/collection/jcl/Collection.scala deleted file mode 100644 index 0df2f74f4b..0000000000 --- a/src/library/jvm/scala/collection/jcl/Collection.scala +++ /dev/null @@ -1,67 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl; - -object Collection { - val DEFAULT_FILTER : Any => Boolean = x => true; - trait Projection[A] extends Collection[A] with MutableIterable.Projection[A] { - override def projection = this - } -} - -/** Analogous to a Java collection. - * - * @author Sean McDirmid - */ -trait Collection[A] extends MutableIterable[A] { - /** Type-safe version of containsAll. - ** - ** @author Sean McDirmid - **/ - def hasAll(i: Iterable[A]): Boolean = i.forall(elements.has); - - /** Adds "a" to the collection, return true if "a" is actually added. */ - def add(a: A): Boolean; - - /** Adds all elements in "i" to the collection, return true if any elements are added. */ - def addAll(i: Iterable[A]): Boolean = { - var changed = false; - i.foreach(t => changed = add(t) || changed); - changed; - } - /** Operator shortcut for addAll. */ - def ++(that: Iterable[A]): this.type = { - addAll(that); this; - } - - /** removes "a" from the collection. */ - def -=(a : A) : Unit = remove(a); - - /** adds "a" from the collection. */ - def +=(t : A) : Unit = add(t); - - /** adds "a" from the collection. Useful for chaining. */ - def +(t : A) : this.type = { add(t); this; } - - /** Transforms each element of the collection in-place according to - * f. - * - * @param f - * @return true if the collection is actually updated. - */ - def transform(f: A => A): Boolean - override def projection : Collection.Projection[A] = new Collection.Projection[A] { - override def elements = Collection.this.elements - override def size = Collection.this.size - override def add(a: A): Boolean = Collection.this.add(a) - override def transform(f : A => A) = Collection.this.transform(f); - } -} diff --git a/src/library/jvm/scala/collection/jcl/CollectionWrapper.scala b/src/library/jvm/scala/collection/jcl/CollectionWrapper.scala deleted file mode 100644 index ec6a22f325..0000000000 --- a/src/library/jvm/scala/collection/jcl/CollectionWrapper.scala +++ /dev/null @@ -1,43 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl; - -/** Used to wrap Java collections in Scala. - * - * @author Sean McDirmid - */ -trait CollectionWrapper[A] extends Collection[A] with IterableWrapper[A] { - /** Override to specify the collection being accessed through this wrapper. - ** Collection operations are then routed through the wrapped Java collection. - **/ - def underlying : java.util.Collection[A]; - override def has(a : A) = underlying.contains(a); - override def elements : MutableIterator[A] = super.elements; - override def size = underlying.size; - - override def hasAll(that : Iterable[A]) = that match { - case that : CollectionWrapper[_] => - val u = underlying; - u.containsAll(that.underlying); - case _ => super.hasAll(that); - } - override def add(a : A) = underlying.add(a); - override def addAll(that : Iterable[A]) = that match { - case that : CollectionWrapper[_] => underlying.addAll(that.underlying); - case _ => super.addAll(that); - } - override def toString = underlying.toString; - override def hashCode = underlying.hashCode; - override def equals(that : Any) = that match { - case that: CollectionWrapper[_] => underlying == that.underlying; - case _ => super.equals(that); - } -} diff --git a/src/library/jvm/scala/collection/jcl/Conversions.scala b/src/library/jvm/scala/collection/jcl/Conversions.scala deleted file mode 100644 index edb96322b6..0000000000 --- a/src/library/jvm/scala/collection/jcl/Conversions.scala +++ /dev/null @@ -1,17 +0,0 @@ -package scala.collection.jcl - -object Conversions { - implicit def convertSet[T](set : java.util.Set[T]) = Set(set) - implicit def convertList[T](set : java.util.List[T]) = Buffer(set) - implicit def convertSortedSet[T](set : java.util.SortedSet[T]) = SortedSet(set) - implicit def convertMap[T,E](set : java.util.Map[T,E]) = Map(set) - implicit def convertSortedMap[T,E](set : java.util.SortedMap[T,E]) = SortedMap(set) - - implicit def unconvertSet[T](set : SetWrapper[T]) = set.underlying - implicit def unconvertCollection[T](set : CollectionWrapper[T]) = set.underlying - implicit def unconvertList[T](set : BufferWrapper[T]) = set.underlying - implicit def unconvertSortedSet[T](set : SortedSetWrapper[T]) = set.underlying - implicit def unconvertMap[T,E](set : MapWrapper[T,E]) = set.underlying - implicit def unconvertSortedMap[T,E](set : SortedMapWrapper[T,E]) = set.underlying - -} \ No newline at end of file diff --git a/src/library/jvm/scala/collection/jcl/HashMap.scala b/src/library/jvm/scala/collection/jcl/HashMap.scala deleted file mode 100644 index e9c156f655..0000000000 --- a/src/library/jvm/scala/collection/jcl/HashMap.scala +++ /dev/null @@ -1,21 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2008, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://www.scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl - -/** A map that is backed by a Java hash map. - * - * @author Sean McDirmid - */ -class HashMap[K, E](override val underlying: java.util.HashMap[K, E]) extends MapWrapper[K, E] { - def this() = this(new java.util.HashMap[K, E]) - override def clone: HashMap[K, E] = - new HashMap[K, E](underlying.clone().asInstanceOf[java.util.HashMap[K, E]]) -} diff --git a/src/library/jvm/scala/collection/jcl/HashSet.scala b/src/library/jvm/scala/collection/jcl/HashSet.scala deleted file mode 100644 index 7d57278273..0000000000 --- a/src/library/jvm/scala/collection/jcl/HashSet.scala +++ /dev/null @@ -1,21 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2008, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://www.scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl - -/** A hash set that is backed by a Java hash set. - * - * @author Sean McDirmid - */ -class HashSet[A](override val underlying: java.util.HashSet[A]) extends SetWrapper[A] { - def this() = this(new java.util.HashSet[A]) - override def clone: HashSet[A] = - new HashSet[A](underlying.clone().asInstanceOf[java.util.HashSet[A]]) -} diff --git a/src/library/jvm/scala/collection/jcl/Hashtable.scala b/src/library/jvm/scala/collection/jcl/Hashtable.scala deleted file mode 100644 index c46c762163..0000000000 --- a/src/library/jvm/scala/collection/jcl/Hashtable.scala +++ /dev/null @@ -1,22 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2008, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://www.scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl - -/** A hash set that is backed by a Java hash table. - * - * @author Sean McDirmid - */ -class Hashtable[K,E](override val underlying: java.util.Hashtable[K,E]) extends MapWrapper[K,E] { - def this() = this(new java.util.Hashtable[K,E]) - - override def clone() : Hashtable[K,E] = - new Hashtable[K,E](underlying.clone().asInstanceOf[java.util.Hashtable[K,E]]) -} diff --git a/src/library/jvm/scala/collection/jcl/IdentityHashMap.scala b/src/library/jvm/scala/collection/jcl/IdentityHashMap.scala deleted file mode 100644 index c3113388e9..0000000000 --- a/src/library/jvm/scala/collection/jcl/IdentityHashMap.scala +++ /dev/null @@ -1,24 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2008, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://www.scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl - -/** A map that is backed by a Java identity hash map, which compares keys - * by their reference-based identity as opposed to using equals and hashCode. - * An identity hash map will often perform better than traditional hash map - * because it can utilize linear probing. - * - * @author Sean McDirmid - */ -class IdentityHashMap[K, E](override val underlying : java.util.IdentityHashMap[K, E]) extends MapWrapper[K, E] { - def this() = this(new java.util.IdentityHashMap[K, E]) - override def clone: IdentityHashMap[K, E] = - new IdentityHashMap[K, E](underlying.clone().asInstanceOf[java.util.IdentityHashMap[K, E]]) -} diff --git a/src/library/jvm/scala/collection/jcl/IterableWrapper.scala b/src/library/jvm/scala/collection/jcl/IterableWrapper.scala deleted file mode 100644 index caa31d10cf..0000000000 --- a/src/library/jvm/scala/collection/jcl/IterableWrapper.scala +++ /dev/null @@ -1,32 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl; - -/** A wrapper around a Java collection that only supports remove mutations. - * - * @author Sean McDirmid - */ -trait IterableWrapper[A] extends MutableIterable[A] { - def underlying: java.util.Collection[A]; - override def remove(a: A) = underlying.remove(a); - override def removeAll(that: Iterable[A]) = that match { - case that: IterableWrapper[_] => underlying.removeAll(that.underlying); - case _ => super.removeAll(that); - } - override def retainAll(that : Iterable[A]) = that match { - case that : IterableWrapper[_] => underlying.retainAll(that.underlying); - case _ => super.retainAll(that); - } - override def size = underlying.size; - override def isEmpty = underlying.isEmpty; - override def clear = underlying.clear; - override def elements : MutableIterator[A] = new MutableIterator.Wrapper[A](underlying.iterator); -} diff --git a/src/library/jvm/scala/collection/jcl/LinkedHashMap.scala b/src/library/jvm/scala/collection/jcl/LinkedHashMap.scala deleted file mode 100644 index 424043ba9a..0000000000 --- a/src/library/jvm/scala/collection/jcl/LinkedHashMap.scala +++ /dev/null @@ -1,22 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2008, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://www.scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl - -/** A map that is backed by a Java linked hash map, which fixes iteration - * order in terms of insertion order. - * - * @author Sean McDirmid - */ -class LinkedHashMap[K, E](override val underlying: java.util.LinkedHashMap[K, E]) extends MapWrapper[K, E] { - def this() = this(new java.util.LinkedHashMap[K, E]) - override def clone: LinkedHashMap[K, E] = - new LinkedHashMap[K, E](underlying.clone().asInstanceOf[java.util.LinkedHashMap[K, E]]) -} diff --git a/src/library/jvm/scala/collection/jcl/LinkedHashSet.scala b/src/library/jvm/scala/collection/jcl/LinkedHashSet.scala deleted file mode 100644 index 2d0d1dddff..0000000000 --- a/src/library/jvm/scala/collection/jcl/LinkedHashSet.scala +++ /dev/null @@ -1,22 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2008, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://www.scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl - -/** A set that is backed by a Java linked hash set, which fixes iteration - * order in terms of insertion order. - * - * @author Sean McDirmid - */ -class LinkedHashSet[A](override val underlying: java.util.LinkedHashSet[A]) extends SetWrapper[A] { - def this() = this(new java.util.LinkedHashSet[A]) - override def clone: LinkedHashSet[A] = - new LinkedHashSet[A](underlying.clone().asInstanceOf[java.util.LinkedHashSet[A]]) -} diff --git a/src/library/jvm/scala/collection/jcl/LinkedList.scala b/src/library/jvm/scala/collection/jcl/LinkedList.scala deleted file mode 100644 index a7fc726af6..0000000000 --- a/src/library/jvm/scala/collection/jcl/LinkedList.scala +++ /dev/null @@ -1,32 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl; - -/** Creates a buffer backed by a Java linked list. Includes additional - * peek/poll/removeFirst/removeLast APIs that are useful in implementing - * queues and stacks. - * - * @author Sean McDirmid - */ -class LinkedList[A](override val underlying : java.util.LinkedList[A]) extends BufferWrapper[A] { - def this() = this(new java.util.LinkedList[A]); - override def elements = super[BufferWrapper].elements; - override def add(idx : Int, a : A) = - if (idx == 0) underlying.addFirst(a); - else super.add(idx, a); - //def peek = underlying.peek.asInstanceOf[A]; - //def poll = underlying.poll.asInstanceOf[A]; - //def removeFirst = underlying.removeFirst.asInstanceOf[A]; - //def removeLast = underlying.removeLast.asInstanceOf[A]; - - override def clone: LinkedList[A] = - new LinkedList[A](underlying.clone().asInstanceOf[java.util.LinkedList[A]]) -} diff --git a/src/library/jvm/scala/collection/jcl/Map.scala b/src/library/jvm/scala/collection/jcl/Map.scala deleted file mode 100644 index 4dc0625b71..0000000000 --- a/src/library/jvm/scala/collection/jcl/Map.scala +++ /dev/null @@ -1,129 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl; - -/** A mutable map that is compatible with Java maps. - * - * @author Sean McDirmid - */ -trait Map[K,E] extends MutableIterable[Tuple2[K,E]] with scala.collection.mutable.Map[K,E] { - override def clear() = super[MutableIterable].clear; - override def isEmpty = super[MutableIterable].isEmpty; - override def keySet : Set[K] = new KeySet; - override final def keys = keySet.elements; - /** The values of this map as a projection, which means - removals from the returned collection will remove the element from this map. - @returns a projection of this map's elements. */ - def valueSet : MutableIterable.Projection[E] = projection.map(_._2); - - override def put(key : K, elem : E) : Option[E] = throw new java.lang.AbstractMethodError - - override def ++=(that : Iterable[(K,E)]) : Unit = - that.foreach(p => put(p._1, p._2)); - - override def removeKey(key : K) : Option[E] = { - val i = elements; - while (!i.hasNext) { - val result = i.next; - if (result._1 == key) { - i.remove; - return Some(result._2); - } - } - return None; - } - override def has(pair : Tuple2[K,E]) = get(pair._1) match { - case Some(e) if e == pair._2 => true; - case _ => false; - } - override def get(key : K) = elements.find(p => p._1 == key).map(_._2); - override def update(key : K, e : E) : Unit = put(key,e); - override def +(pair : Tuple2[K,E]) : this.type = { - put(pair._1,pair._2); this; - } - override def +=(pair : Tuple2[K,E]) : Unit = put(pair._1, pair._2); - override def -(key : K) : this.type = { - removeKey(key); this; - } - override def remove(p : (K,E)) = get(p._1) match { - case Some(p._2) => this -= p._1; true - case _ => false; - } - - override def -=(key : K) : Unit = removeKey(key); - override def elements : MutableIterator[Tuple2[K,E]]; - - override def projection : Map.Projection[K,E] = new Map.Projection[K,E] { - override def elements = Map.this.elements - override def size = Map.this.size - override def get(k : K) = Map.this.get(k) - override def put(k : K, e : E) = Map.this.put(k, e) - } - /** - */ - def lense[F](f : E => F, g : F => E) : jcl.Map.Projection[K,F] = new Lense[F](f,g); - - protected class Lense[F](f : E => F, g : F => E) extends jcl.Map.Projection[K,F] { - override def elements = Map.this.elements.map(k => Tuple2(k._1, f(k._2))); - override def removeKey(key : K) = Map.this.removeKey(key).map(f); - override def put(key : K, elem : F) = Map.this.put(key, g(elem)).map(f); - override def get(key : K) = Map.this.get(key).map(f); - override def lense[G](f0 : F => G, g0 : G => F) : jcl.Map.Projection[K,G] = - Map.this.lense[G](x => f0(f(x)), y => g(g0(y))); - override def size = size0; - } - protected class KeySet extends Set[K] { - override def size = Map.this.size; - override def add(k : K) = Map.this.put(k, default(k)) == None; - override def elements = Map.this.elements.map(_._1); - override def has(k : K) = Map.this.contains(k); - } - override def filterKeys(p : K => Boolean) : Map.Projection[K,E] = new Filter(p); - - protected class Filter(p : K => Boolean) extends Map.Projection[K,E] { - override def elements = { - val i = Map.this.elements.filter(e => p(e._1)); - new MutableIterator[(K,E)] { - def next = i.next - def hasNext = i.hasNext - def remove : Unit = throw new NoSuchMethodException - } - } - override def removeKey(key : K) = { - if (!p(key)) throw new IllegalArgumentException; - Map.this.removeKey(key); - } - override def contains(key : K) = p(key) && Map.this.contains(key); - override def put(key : K, elem : E) = { - if (!p(key)) throw new IllegalArgumentException; - Map.this.put(key, elem); - } - override def get(key : K) = { - if (!p(key)) None; - else Map.this.get(key); - } - override def filterKeys(p0 : K => Boolean) : Map.Projection[K,E] = - Map.this.filterKeys(e => p(e) && p0(e)); - - override def size = size0; - } -} - -object Map { - trait MutableIterableProjection[A] extends MutableIterable.Projection[A]; - trait Projection[K,E] extends MutableIterableProjection[(K,E)] with scala.collection.Map.Projection[K,E] with Map[K,E] { - override def projection = this - override def map[B](f : ((K,E)) => B) : MutableIterable.Projection[B] = super[MutableIterableProjection].map(f); - } - def apply[T,E](map0 : java.util.Map[T,E]) = new MapWrapper[T,E] { - val underlying = map0 - } -} diff --git a/src/library/jvm/scala/collection/jcl/MapWrapper.scala b/src/library/jvm/scala/collection/jcl/MapWrapper.scala deleted file mode 100644 index 7fed4d2e8f..0000000000 --- a/src/library/jvm/scala/collection/jcl/MapWrapper.scala +++ /dev/null @@ -1,76 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2008, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://www.scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl - -/** A wrapper around a Java map. - * - * @author Sean McDirmid - */ -trait MapWrapper[K, E] extends jcl.Map[K, E] { - def underlying: java.util.Map[K, E] - override def size = underlying.size - override def isEmpty = underlying.isEmpty - override def clear() = underlying.clear - - override def put(key: K, elem: E) = { - //if (elem == null) throw new IllegalArgumentException; - val ret = underlying.put(key, elem) - if (ret == null) None else Some(ret.asInstanceOf[E]) - } - - override def get(key : K) : Option[E] = { - val ret = underlying.get(key); - if (ret == null) None else Some(ret.asInstanceOf[E]); - } - - override def ++=(that : Iterable[Tuple2[K,E]]) : Unit = that match { - case that : MapWrapper[_,_] => underlying.putAll(that.underlying); - case _ => super.++=(that) - } - - override def removeKey(key: K) = { - val ret = underlying.remove(key) - if (ret == null) None else Some(ret.asInstanceOf[E]) - } - - override def contains(key: K) = underlying.containsKey(key) - override def keySet: Set.Projection[K] = new KeySet - override def valueSet: MutableIterable.Projection[E] = new ValueSet - override def elements: MutableIterator[Tuple2[K,E]] = new IteratorWrapper - - class IteratorWrapper extends MutableIterator[Tuple2[K,E]] { - val underlying = MapWrapper.this.underlying.entrySet.iterator - def hasNext = underlying.hasNext - def remove = underlying.remove - def next = { - val next = underlying.next.asInstanceOf[java.util.Map.Entry[K,E]] - Tuple2(next.getKey.asInstanceOf[K],next.getValue.asInstanceOf[E]) - } - } - - class KeySet extends super.KeySet with SetWrapper[K] with Set.Projection[K] { - val underlying = MapWrapper.this.underlying.keySet - } - - class ValueSet extends IterableWrapper[E] with MutableIterable.Projection[E] { - override def size = MapWrapper.this.size - val underlying = MapWrapper.this.underlying.values - override def has(e : E) = MapWrapper.this.underlying.containsValue(e) - } - - override def toString = underlying.toString - override def hashCode = underlying.hashCode - - override def equals(that : Any) = that match { - case that: MapWrapper[_,_] => underlying == that.underlying - case _ => super.equals(that) - } -} diff --git a/src/library/jvm/scala/collection/jcl/MutableIterable.scala b/src/library/jvm/scala/collection/jcl/MutableIterable.scala deleted file mode 100644 index 3988ed8d93..0000000000 --- a/src/library/jvm/scala/collection/jcl/MutableIterable.scala +++ /dev/null @@ -1,110 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl; - -/** - * An iterable collection that supports remove operations. - * Useful for representing projections of mutable collections that where only - * the remove operation makes sense. - * - * @author Sean McDirmid - */ -trait MutableIterable[A] extends scala.Collection[A] { - /** @return true if t is in the collection. - **/ - def has(t : A ) : Boolean = elements.contains(t); - - /** @return true if t was removed from this collection. - **/ - def remove(t : A ) : Boolean = elements.remove(t); - /** @return true if any element in that was removed from this collection. - **/ - def removeAll(that : Iterable[A]) : Boolean = { - var changed = false; - that.foreach(t => changed = elements.remove(t) || changed); - changed; - } - /** Operator shortcut for removeAll. */ - def --(that : Iterable[A]) : this.type = { - removeAll(that); this; - } - - /** @return the collection that t was removed from. - */ - def -(t : A) : this.type = { remove(t); this; } - /** retain only elements in the collection that predicate p is true for. - */ - def retainOnly(p : A => Boolean) : Unit = elements.retain(p); - /** retain only elements that are also in that. - */ - def retainAll(that : Iterable[A]) : Boolean = elements.retain(s => that.exists(t => t == s)); - - /** @return the current number of elements in the collection. - */ - protected def size0 : Int = { - var count = 0; - val i = elements; - while (i.hasNext) { count = count + 1; i.next; } - count; - } - - /** clear all elements from the collection. - */ - def clear(): Unit = { - val i = elements; - while (i.hasNext) { - i.next; i.remove; - } - } - override def projection : MutableIterable.Projection[A] = new MutableIterable.Projection[A] { - override def elements = MutableIterable.this.elements - override def size = MutableIterable.this.size - override def remove(t : A ) : Boolean = MutableIterable.this.remove(t) - override def filter(p : A => Boolean) : MutableIterable.Projection[A] = super.filter(p) - } - /** The default implementation of a map over mutable iterable collections. - **/ - override def elements : MutableIterator[A]; - protected class Map[B](f : A => B) extends MutableIterable.Projection[B] { - override def elements = MutableIterable.this.elements.map(f) - override def size = MutableIterable.this.size - } - trait Filter extends MutableIterable.Projection[A] { - protected def p(a : A) : Boolean - override def has(a : A) = if (!p(a)) false else MutableIterable.this.has(a); - override def remove(a : A) = { - if (!p(a)) throw new IllegalArgumentException; - MutableIterable.this.remove(a); - } - override def filter(p0 : A => Boolean) : MutableIterable.Projection[A] = - MutableIterable.this.projection.filter(a => p(a) && p0(a)); - def elements = { - val i = MutableIterable.this.elements.filter(p); - new MutableIterator[A] { - def next = i.next - def hasNext = i.hasNext - def remove : Unit = throw new NoSuchMethodException - } - } - def size = size0; - } -} - -object MutableIterable { - trait Projection[A] extends MutableIterable[A] with Iterable.Projection[A] { - override def projection = this - override def map[B](f : A => B) : Projection[B] = new Map[B](f); - override def filter(pp : A => Boolean) : Projection[A] = new Filter { - def p(a : A) = pp(a) - } - } -} - diff --git a/src/library/jvm/scala/collection/jcl/MutableIterator.scala b/src/library/jvm/scala/collection/jcl/MutableIterator.scala deleted file mode 100644 index 5f92746358..0000000000 --- a/src/library/jvm/scala/collection/jcl/MutableIterator.scala +++ /dev/null @@ -1,70 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl; - -object MutableIterator { - class Wrapper[A](val underlying : java.util.Iterator[A]) extends MutableIterator[A] { - def hasNext = underlying.hasNext; - def next = underlying.next.asInstanceOf[A]; - def remove = underlying.remove; - } -} - -/** An iterator that supports the remove operation. - * These iterators wrap Java iterators, and so have the same fail fast - * behavior when dealing with concurrent modifications. - * - * @author Sean McDirmid - */ -trait MutableIterator[A] extends Iterator[A] { - def remove : Unit; - - /* filter doesnt' support remove yet. - override def filter(f : A => Boolean) : MutableIterator[A] = { - val buffered = this.buffered0; - new buffered.Filter(f); - } - */ - - override def map[B](f: A => B) : MutableIterator[B] = new Map(f); - /** A type-safe version of contains. - **/ - def has(a: A) = exists(b => a == a); - - /** Finds and removes the first instance of "a" through the iterator. - * After execution, the iterator's cursor is located where the removed - * element existed. - * - * @param a .. - * @return false if "a" is not encountered in the iterator - * and the iterator's cursor is located at the end of its elements. - */ - def remove(a: A): Boolean = { - while (hasNext) - if (next == a) { remove; return true; } - return false; - } - /** Removes all elements in the iterator that predicate "p" returns false on. - **/ - def retain(p : A => Boolean) : Boolean = { - var changed = false; - while (hasNext) - if (!p(next)) { remove; changed = true; } - changed; - } - - /** Standard implementation of a mapped iterator. **/ - class Map[B](f : A => B) extends MutableIterator[B] { - def hasNext = MutableIterator.this.hasNext - def next = f(MutableIterator.this.next) - def remove = MutableIterator.this.remove - } -} diff --git a/src/library/jvm/scala/collection/jcl/MutableSeq.scala b/src/library/jvm/scala/collection/jcl/MutableSeq.scala deleted file mode 100644 index 559965c9ea..0000000000 --- a/src/library/jvm/scala/collection/jcl/MutableSeq.scala +++ /dev/null @@ -1,123 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl; - -/** A mutable sequence that supports the remove operation and is ordered. - * - * @author Sean McDirmid - */ -trait MutableSeq[A] extends Seq[A] with MutableIterable[A] { - protected class DefaultSeqIterator extends SeqIterator[Int,A] { - protected var index = 0 - override def hasNext = index < length - override def next = { - if (!hasNext) throw new NoSuchElementException("no lookahead") - index = index + 1 - MutableSeq.this.apply(index - 1) - } - override def hasPrevious = index > 0 - override def previous = { - if (!hasPrevious) throw new NoSuchElementException - index = index - 1 - MutableSeq.this.apply(index) - } - - override def nextIndex = index - override def previousIndex = { - if (index == 0) throw new NoSuchElementException - else index - 1 - } - def remove = throw new UnsupportedOperationException - } - override def elements : SeqIterator[Int,A] = new DefaultSeqIterator - - override def isEmpty = super[MutableIterable].isEmpty; - - override def apply(idx : Int) = elements.seek(idx); - override def projection : MutableSeq.Projection[A] = new MutableSeq.Projection[A] { - override def length = MutableSeq.this.length - override def elements = MutableSeq.this.elements - override def apply(idx : Int) = MutableSeq.this.apply(idx) - } - - /** Find the index of "a" in this sequence. - * @returns None if the "a" is not in this sequence. - */ - def indexOf(a : A) = elements.indexOf(a); - - override def length = { - var i = elements; - var sz = 0; - while (i.hasNext) { - sz = sz + 1; - i.next; - } - sz; - } - protected trait Filter extends MutableSeq.Projection[A] { - protected def p(a : A) : Boolean - override def elements : SeqIterator[Int,A] = new FilterIterator(MutableSeq.this.elements); - class FilterIterator(underlying : SeqIterator[Int,A]) extends SeqIterator[Int,A] { - private var index = 0; - protected def seekNext : Option[A] = { - while (underlying.hasNext) { - val next = underlying.next; - if (p(next)) return Some(next); - } - return None; - } - protected def seekPrevious : Option[A] = { - while (underlying.hasPrevious) { - val previous = underlying.previous; - if (p(previous)) return Some(previous); - } - return None; - } - def hasNext : Boolean = seekNext match { - case None => false; - case Some(_) => underlying.previous; true; - } - def nextIndex = index; - def next = seekNext match { - case None => throw new NoSuchElementException; - case Some(result) => index = index + 1; result; - } - def hasPrevious : Boolean = seekPrevious match { - case None => false; - case Some(_) => underlying.previous; true; - } - def previousIndex = { - if (index == 0) throw new NoSuchElementException; - index - 1; - } - def previous = seekPrevious match { - case None => throw new NoSuchElementException; - case Some(result) => index = index - 1; result; - } - def remove = underlying.remove; - } - } - protected class Map[B](f : A => B) extends super.Map[B](f) with MutableSeq.Projection[B] { - override def elements = MutableSeq.this.elements.map(f); - override def apply(idx : Int) = f(MutableSeq.this.apply(idx)); - override def size = length; - } -} -object MutableSeq { - trait Projection[A] extends MutableSeq[A] with MutableIterable.Projection[A] with Seq.Projection[A] { - override def projection = this - override def filter(pp : A => Boolean) : Projection[A] = new Filter { - override def p(a : A) = pp(a) - } - override def map[B](f : A => B) : Projection[B] = new Map[B](f); - } -} - diff --git a/src/library/jvm/scala/collection/jcl/Ranged.scala b/src/library/jvm/scala/collection/jcl/Ranged.scala deleted file mode 100644 index 054d9c381d..0000000000 --- a/src/library/jvm/scala/collection/jcl/Ranged.scala +++ /dev/null @@ -1,54 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl; - -/** Any collection (including maps) whose keys (or elements) are ordered. - * - * @author Sean McDirmid - */ -trait Ranged[K,A] extends scala.collection.Ranged[K,A] with MutableIterable[A] { - protected type SortedSelf <: Ranged[K,A]; - - /** Comparison function that orders keys. */ - def compare(k0: K, k1: K): Int; - - /** Creates a ranged projection of this collection. Any mutations in the - * ranged projection will update this collection and vice versa. Note: keys - * are not garuanteed to be consistent between this collection and the projection. - * This is the case for buffers where indexing is relative to the projection. - * - * @param from The lower-bound (inclusive) of the ranged projection. - * None if there is no lower bound. - * @param until The upper-bound (exclusive) of the ranged projection. - * None if there is no upper bound. - */ - def rangeImpl(from: Option[K], until: Option[K]) : SortedSelf; - /** Creates a ranged projection of this collection with no upper-bound. - ** @param from The lower-bound (inclusive) of the ranged projection. - **/ - override final def from(from: K): SortedSelf = rangeImpl(Some(from), None); - /** Creates a ranged projection of this collection with no lower-bound. - ** @param until The upper-bound (exclusive) of the ranged projection. - **/ - override final def until(until: K): SortedSelf = rangeImpl(None, Some(until)); - - /** Creates a ranged projection of this collection with both a lower-bound and an upper-bound. - ** @param from The upper-bound (exclusive) of the ranged projection. - **/ - override final def range(from: K, until: K) : SortedSelf = rangeImpl(Some(from),Some(until)); - - /** A wrapper around Java comparators. */ - protected class Comparator[K <% Ordered[K]] extends java.util.Comparator[Any] { - def compare(x0 : Any, x1 : Any) = { - x0.asInstanceOf[K].compare(x1.asInstanceOf[K]); //!!! - } - } -} diff --git a/src/library/jvm/scala/collection/jcl/SeqIterator.scala b/src/library/jvm/scala/collection/jcl/SeqIterator.scala deleted file mode 100644 index 5461928735..0000000000 --- a/src/library/jvm/scala/collection/jcl/SeqIterator.scala +++ /dev/null @@ -1,58 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl; - -/** An iterator for a sequence that can move both forwards and backwards. - * over a set of ordered keys. - * - * @author Sean McDirmid - */ -trait SeqIterator[K,A] extends MutableIterator[A] { - /** @returns The index at the iterator's cursor. */ - def nextIndex: K; - - /** @returns The index of the element before the iterator's cursor. */ - def previousIndex: K; - - /** @return The previous element, will move the iterator's cursor backwards. */ - def previous: A; - - /** @return True if and only if the iterator's cursor is not at the beging of the iteration. */ - def hasPrevious : Boolean; - - /** Winds the iteration forward until index "idx" is found */ - def seek(idx: K) = { - while (nextIndex != idx) next; - next; - } - /** finds the index of the next "a" in this iteration. - * - * @param a .. - * @return None if "a" is not found in the iteration. - */ - def indexOf(a: A): Option[K] = { - while (hasNext) { - val ret = next; - if (ret == a) return Some(previousIndex); - } - return None; - } - - override def map[B](f: A => B) : SeqIterator[K,B] = new Map[B](f); - class Map[B](f: A => B) extends super.Map[B](f) with SeqIterator[K,B] { - override def hasPrevious = SeqIterator.this.hasPrevious; - override def previous = f(SeqIterator.this.previous); - override def previousIndex = SeqIterator.this.previousIndex; - override def nextIndex = SeqIterator.this.nextIndex; - override def map[C](g : B => C) : SeqIterator[K,C] = - SeqIterator.this.map(a => g(f(a))); - } -} diff --git a/src/library/jvm/scala/collection/jcl/Set.scala b/src/library/jvm/scala/collection/jcl/Set.scala deleted file mode 100644 index 7ef9360c2a..0000000000 --- a/src/library/jvm/scala/collection/jcl/Set.scala +++ /dev/null @@ -1,72 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl - -/** Analogous to a Java set. - * - * @author Sean McDirmid - */ -trait Set[A] extends scala.collection.mutable.Set[A] with Collection[A] { - final def contains(a : A) = has(a) - - /** Add will return false if "a" already exists in the set. **/ - override def add(a: A): Boolean - - override def ++(i: Iterable[A]) : this.type = super[Collection].++(i) - override def --(i: Iterable[A]) : this.type = super[Collection].--(i) - override def +(t: A) : this.type = super[Collection].+(t) - override def -(t: A) : this.type = super[Collection].-(t) - override final def retain(f: A => Boolean) = retainOnly(f) - override def isEmpty = super[Collection].isEmpty - override def clear() = super.clear() - override def subsetOf(set : scala.collection.Set[A]) = set match { - case set : Set[_] => set.hasAll(this) - case set => super.subsetOf(set) - } - - override def transform(f: A => A) = { - var toAdd : List[A] = Nil - val i = elements - while (i.hasNext) { - val i0 = i.next - val i1 = f(i0) - if (i0 != i1) { - i.remove; toAdd = i1 :: toAdd - } - } - addAll(toAdd) - } - class Filter(pp : A => Boolean) extends super.Filter with Set.Projection[A] { - override def p(a : A) = pp(a) - override def retainOnly(p0 : A => Boolean): Unit = - Set.this.retainOnly(e => !p(e) || p0(e)) - override def add(a : A) = { - if (!p(a)) throw new IllegalArgumentException - else Set.this.add(a) - } - } - override def projection : Set.Projection[A] = new Set.Projection[A] { - override def add(a: A): Boolean = Set.this.add(a) - override def elements = Set.this.elements - override def size = Set.this.size - override def has(a : A) : Boolean = Set.this.has(a) - } -} - -object Set { - trait Projection[A] extends Collection.Projection[A] with Set[A] { - override def filter(p : A => Boolean) : Projection[A] = new Filter(p); - override def projection = this - } - def apply[T](set : java.util.Set[T]) = new SetWrapper[T] { - val underlying = set - } -} diff --git a/src/library/jvm/scala/collection/jcl/SetWrapper.scala b/src/library/jvm/scala/collection/jcl/SetWrapper.scala deleted file mode 100644 index 5aeaf57a1b..0000000000 --- a/src/library/jvm/scala/collection/jcl/SetWrapper.scala +++ /dev/null @@ -1,22 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl; - -/** Used to wrap Java sets. - * - * @author Sean McDirmid - */ -trait SetWrapper[A] extends Set[A] with CollectionWrapper[A] { - def underlying: java.util.Set[A]; - override def isEmpty = super[CollectionWrapper].isEmpty; - override def clear() = super[CollectionWrapper].clear; - override def size = underlying.size; -} diff --git a/src/library/jvm/scala/collection/jcl/Sorted.scala b/src/library/jvm/scala/collection/jcl/Sorted.scala deleted file mode 100644 index 7bbe49da75..0000000000 --- a/src/library/jvm/scala/collection/jcl/Sorted.scala +++ /dev/null @@ -1,46 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl; - -/** Any collection (including maps) whose keys (or elements) are ordered. - * - * @author Sean McDirmid - */ -trait Sorted[K,A] extends scala.collection.Sorted[K,A] with Ranged[K,A] { - override protected type SortedSelf <: Sorted[K,A]; - /** return as a projection the set of keys in this collection */ - override def keySet : SortedSet[K]; - - /** Creates a ranged projection of this collection. Any mutations in the - * ranged projection will update this collection and vice versa. Keys - * are garuanteed to be consistent between the collection and its projection. - * - * @param from The lower-bound (inclusive) of the ranged projection. - * None if there is no lower bound. - * @param until The upper-bound (exclusive) of the ranged projection. - * None if there is no upper bound. - */ - override def rangeImpl(from: Option[K], until: Option[K]) : SortedSelf; - - /** Create a range projection of this collection with no lower-bound. - ** @param to The upper-bound (inclusive) of the ranged projection. - **/ - final override def to(to : K): SortedSelf = { - // tough! - val i = keySet.from(to).elements; - if (!i.hasNext) return this.asInstanceOf[SortedSelf]; - val next = i.next; - if (next == to) { - if (!i.hasNext) return this.asInstanceOf[SortedSelf]; - else return until(i.next); - } else return until(next); - } -} diff --git a/src/library/jvm/scala/collection/jcl/SortedMap.scala b/src/library/jvm/scala/collection/jcl/SortedMap.scala deleted file mode 100644 index be5591e7b8..0000000000 --- a/src/library/jvm/scala/collection/jcl/SortedMap.scala +++ /dev/null @@ -1,103 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl; - -object SortedMap { - trait Projection[K,E] extends Map.Projection[K,E] with SortedMap[K,E] { - override def projection = this - } - def apply[T,E](map0 : java.util.SortedMap[T,E]) = new SortedMapWrapper[T,E] { - val underlying = map0 - } -} -/** A map whose keys are sorted. - * - * @author Sean McDirmid - */ -trait SortedMap[K,E] extends scala.collection.SortedMap[K,E] with Map[K,E] with Sorted[K,Tuple2[K,E]] { - final protected type SortedSelf = SortedMap[K,E]; - override def compare(k0 : K, k1 : K) : Int; - override def firstKey : K = elements.next._1; - override def lastKey : K = { - val i = elements; - var last : K = i.next._1; - while (i.hasNext) last = i.next._1; - last; - } - override def rangeImpl(from : Option[K], until : Option[K]) : SortedMap[K,E] = Range(from, until); - override def keySet : SortedSet.Projection[K] = new KeySet; - - override def projection : SortedMap.Projection[K,E] = new SortedMap.Projection[K,E] { - override def elements = SortedMap.this.elements - override def size = SortedMap.this.size - override def get(k : K) = SortedMap.this.get(k) - override def put(k : K, e : E) = SortedMap.this.put(k, e) - override def compare(k0 : K, k1 : K) = SortedMap.this.compare(k0, k1) - } - - override def lense[F](f : E => F, g : F => E) : jcl.SortedMap.Projection[K,F] = new Lense[F](f,g); - - protected class Lense[F](f : E => F, g : F => E) extends super.Lense[F](f,g) with SortedMap.Projection[K,F] { - def compare(k0 : K, k1 : K) = SortedMap.this.compare(k0, k1); - override def filterKeys(p : K => Boolean) : SortedMap.Projection[K,F] = - SortedMap.this.projection.filterKeys(p).lense(f,g); - override def lense[G](f0 : F => G, g0 : G => F) : jcl.SortedMap.Projection[K,G] = - SortedMap.this.lense[G]({x:E => f0(f(x))}, {y:G => g(g0(y))}); - override def rangeImpl(from : Option[K], until : Option[K]) = - SortedMap.this.rangeImpl(from,until).lense(f,g); - } - protected class KeySet extends super.KeySet with SortedSet.Projection[K] { - def compare(k0 : K, k1 : K) = SortedMap.this.compare(k0,k1); - override def firstKey = SortedMap.this.firstKey; - override def lastKey = SortedMap.this.lastKey; - override def rangeImpl(from : Option[K], until : Option[K]) = - SortedMap.this.rangeImpl(from,until).keySet; - } - override def filterKeys(p : K => Boolean) : SortedMap.Projection[K,E] = new Filter(p); - protected class Filter(p : K => Boolean) extends super.Filter(p) with SortedMap.Projection[K,E] { - def compare(k0 : K, k1 : K) = SortedMap.this.compare(k0,k1); - override def filterKeys(p0 : K => Boolean) : SortedMap.Projection[K,E] = - SortedMap.this.filterKeys(k => p(k) && p0(k)); - override def rangeImpl(from : Option[K], until : Option[K]) : SortedMap.Projection[K,E] = - SortedMap.this.Range(from, until).projection.filterKeys(p); - } - protected def Range(from : Option[K], until : Option[K]) : SortedMap.Projection[K,E] = new Range(from,until); - protected class Range(from : Option[K], until : Option[K]) extends super.Filter(key => { - ((from == None || (compare(from.get,key) <= 0)) && - (until == None || (compare(key,until.get) < 0))); - }) with SortedMap.Projection[K,E] { - def compare(k0 : K, k1 : K) = SortedMap.this.compare(k0,k1); - private def contains0(key : K) = - (from == None || (compare(from.get,key) <= 0)) && - (until == None || (compare(key,until.get) < 0)); - - override def contains(key : K) = SortedMap.this.contains(key) && contains0(key); - override def get(key : K) = if (!contains0(key)) None else SortedMap.this.get(key); - override def put(key : K, elem : E) = { - if (!contains0(key)) throw new IllegalArgumentException; - SortedMap.this.put(key, elem); - } - override def rangeImpl(from : Option[K], until : Option[K]) : SortedMap[K,E] = { - if (this.from != None && from == None) return rangeImpl(this.from, until); - if (this.until != None && until == None) return rangeImpl(from, this.until); - if (from != None && compare(this.from.get, from.get) > 0) return rangeImpl(this.from, until); - if (until != None && compare(this.until.get, until.get) < 0) return rangeImpl(from, this.until); - SortedMap.this.Range(from, until); - } - override def filterKeys(p : K => Boolean) : SortedMap.Projection[K,E] = new Filter(p); - protected class Filter(p : K => Boolean) extends super.Filter(p) with SortedMap.Projection[K,E] { - //def compare(k0 : K, k1 : K) = Range.this.compare(k0, k1); - override def filterKeys(p0 : K => Boolean) = Range.this.projection.filterKeys(k => p(k) && p0(k)); - override def rangeImpl(from : Option[K], until : Option[K]) : SortedMap.Projection[K,E] = - Range.this.rangeImpl(from,until).projection.filterKeys(p); - } - } -} diff --git a/src/library/jvm/scala/collection/jcl/SortedMapWrapper.scala b/src/library/jvm/scala/collection/jcl/SortedMapWrapper.scala deleted file mode 100644 index c706a4fec9..0000000000 --- a/src/library/jvm/scala/collection/jcl/SortedMapWrapper.scala +++ /dev/null @@ -1,39 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl; - -/** A sorted map that wraps an underlying Java sorted map. - * - * @author Sean McDirmid - */ -trait SortedMapWrapper[K,E] extends SortedMap[K,E] with MapWrapper[K,E] { - override def underlying : java.util.SortedMap[K,E]; - /** the comparator function of this sorted map is defined in terms - * of the underlying sorted map's comparator. - */ - def compare(k0 : K, k1 : K) = underlying.comparator.compare(k0,k1); - override def firstKey = underlying.firstKey.asInstanceOf[K]; - override def lastKey = underlying.lastKey.asInstanceOf[K]; - override def keySet : SortedSet.Projection[K] = new KeySet; - override protected def Range(from : Option[K], until : Option[K]) = new Range(from,until); - protected class Range(from : Option[K], until : Option[K]) extends super.Range(from,until) with SortedMapWrapper[K,E] { - val underlying = Tuple2(from,until) match { - case Tuple2(None,None) => throw new IllegalArgumentException; - case Tuple2(Some(from),None) => SortedMapWrapper.this.underlying.tailMap(from); - case Tuple2(None,Some(until)) => SortedMapWrapper.this.underlying.headMap(until); - case Tuple2(Some(from),Some(until)) => SortedMapWrapper.this.underlying.subMap(from,until); - } - override def compare(k0 : K, k1 : K) = super[SortedMapWrapper].compare(k0, k1); - } - protected class KeySet extends super[SortedMap].KeySet with SetWrapper[K] with SortedSet.Projection[K] { - val underlying = SortedMapWrapper.this.underlying.keySet; - } -} diff --git a/src/library/jvm/scala/collection/jcl/SortedSet.scala b/src/library/jvm/scala/collection/jcl/SortedSet.scala deleted file mode 100644 index 5050a1c36a..0000000000 --- a/src/library/jvm/scala/collection/jcl/SortedSet.scala +++ /dev/null @@ -1,99 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl; -import Predef._ - -object SortedSet { - trait Projection[A] extends Set.Projection[A] with SortedSet[A] { - override def projection = this - override def filter(p : A => Boolean) : Projection[A] = new Filter(p); - } - def apply[T](set : java.util.SortedSet[T]) = new SortedSetWrapper[T] { - val underlying = set - } - -} - -/** Analogous to a Java sorted set. - * - * @author Sean McDirmid - */ -trait SortedSet[A] extends scala.collection.SortedSet[A] with jcl.Set[A] with Sorted[A,A] { - final protected type SortedSelf = SortedSet[A]; - override def keySet = this; - def compare(a0 : A, a1 : A) : Int; - override def firstKey : A = { - val i = elements; - if (i.hasNext) i.next; - else throw new NoSuchElementException; - } - override def subsetOf(that : scala.collection.Set[A]) = super[SortedSet].subsetOf(that); - override def hasAll(that : Iterable[A]) = super[Sorted].hasAll(that.elements); - - override def lastKey : A = { - var last : A = null.asInstanceOf[A]; - val i = elements; - while (i.hasNext) last = i.next; - if (last == null) throw new NoSuchElementException; - else last; - } - override def rangeImpl(from : Option[A], until : Option[A]) : SortedSet[A] = new Range(from, until); - override def projection : SortedSet.Projection[A] = new SortedSet.Projection[A] { - override def compare(a0 : A, a1 : A) = SortedSet.this.compare(a0, a1) - override def add(a: A): Boolean = SortedSet.this.add(a) - override def elements = SortedSet.this.elements - override def size = SortedSet.this.size - override def has(a : A) : Boolean = SortedSet.this.has(a) - } - - protected class Filter(pp : A => Boolean) extends super.Filter(pp) with SortedSet.Projection[A] { - override def p(a : A) = pp(a) - def compare(a0 : A, a1 : A) : Int = SortedSet.this.compare(a0, a1); - override def filter(p0 : A => Boolean) = SortedSet.this.projection.filter(k => p(k) && p0(k)); - } - protected class Range(from : Option[A], until : Option[A]) extends Filter(key => { - (from == None || (compare(from.get,key) <= 0)) && - (until == None || (compare(key,until.get) < 0)); - }) with SortedSet.Projection[A] { - if (from == None && until == None) throw new IllegalArgumentException; - if (from != None && until != None && !(SortedSet.this.compare(from.get, until.get) < 0)) - throw new IllegalArgumentException; - //override def elements : MutableIterator[A] = - // new RangeIterator(SortedSet.this.elements.buffered0); - private def contains1(key : A) = - (from == None || (compare(from.get,key) <= 0)) && - (until == None || (compare(key,until.get) < 0)); - override def has(elem : A) = contains1(elem) && SortedSet.this.has(elem); - override def rangeImpl(from : Option[A], until : Option[A]) : SortedSet[A] = { - if (this.from != None && from == None) return rangeImpl(this.from, until); - if (this.until != None && until == None) return rangeImpl(from, this.until); - if (from != None && compare(this.from.get, from.get) > 0) return rangeImpl(this.from, until); - if (until != None && compare(this.until.get, until.get) < 0) return rangeImpl(from, this.until); - SortedSet.this.rangeImpl(from, until); - } - /* - class RangeIterator(underlying : MutableIterator[A]#Buffered) extends MutableIterator[A] { - if (from != None) - underlying.seekNext(a => compare(from.get, a) <= 0); - - private def okNext(a : A) = - if (until == None) true; - else compare(a, until.get) < 0; - - def hasNext = underlying.hasNext && okNext(underlying.peekNext); - def next = underlying.seekNext(okNext) match { - case Some(result) => underlying.next; result; - case None => throw new NoSuchElementException; - } - def remove = underlying.remove; - }*/ - } -} diff --git a/src/library/jvm/scala/collection/jcl/SortedSetWrapper.scala b/src/library/jvm/scala/collection/jcl/SortedSetWrapper.scala deleted file mode 100644 index 39b066bfd7..0000000000 --- a/src/library/jvm/scala/collection/jcl/SortedSetWrapper.scala +++ /dev/null @@ -1,39 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl; - -/**

- * A wrapper around a Java sorted set. - *

- *

- * The comparator of the sorted set matches the comparator of this set. - *

- * - * @author Sean McDirmid - */ -trait SortedSetWrapper[A] extends SortedSet[A] with SetWrapper[A] { - def underlying : java.util.SortedSet[A]; - /** delegates to the comparator of the underlying Java sorted set */ - override def compare(a0 : A, a1 : A) = underlying.comparator.compare(a0, a1); - override def firstKey = underlying.first.asInstanceOf[A]; - override def lastKey = underlying.last .asInstanceOf[A]; - override def rangeImpl(from : Option[A], until : Option[A]) : SortedSet[A] = new Range(from,until); - protected class Range(from : Option[A], until : Option[A]) extends super.Range(from, until) with SortedSetWrapper[A] { - val underlying = Tuple2(from,until) match { - case Tuple2(None,Some(until)) => SortedSetWrapper.this.underlying.headSet(until); - case Tuple2(Some(from),None) => SortedSetWrapper.this.underlying.tailSet(from); - case Tuple2(Some(from),Some(until)) => SortedSetWrapper.this.underlying.subSet(from,until); - case _ => throw new IllegalArgumentException; - } - override def elements : MutableIterator[A] = super[SortedSetWrapper].elements; - } - override def toString = super.toString; -} diff --git a/src/library/jvm/scala/collection/jcl/Tests.scala b/src/library/jvm/scala/collection/jcl/Tests.scala deleted file mode 100644 index a3007d8e1b..0000000000 --- a/src/library/jvm/scala/collection/jcl/Tests.scala +++ /dev/null @@ -1,79 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl; - -import java.lang.Integer; - -private[jcl] object Tests { - - def main(args : Array[String]) : Unit = { - hashSet; - treeSet; - treeMap; - } - - def treeSet : Unit = { - val set = new TreeSet[String]; - set + "aaa" + "bbb" + "ccc" + "ddd" + "eee" + "fff"; - Console.println(set); - val rset : SortedSet[String] = set.range("b", "e"); - Console.println(rset); - rset + "bad"; - Console.println(rset); - Console.println(set); - val fset : SortedSet[String] = rset.projection.filter(_.endsWith("d")); - Console.println(fset); - fset += "cd"; - Console.println(set); - //set.projection.map(_.length).retain(x => x == 3); - Console.println(set); - Console.println(rset); - Console.println(fset); - } - - def treeMap : Unit = { - val map = new TreeMap[String,Integer]; - map + ("bb" -> 3) + ("cc" -> 4) + ("aa" -> 2) + ("dd" -> 5); - //Console.println(map); - val rmap : SortedMap[String,Integer] = map.range("b", "d"); - rmap + ("bad" -> 10); - Console.println(rmap); - //Console.println(map); - val fmap : SortedMap[String,Integer] = rmap.projection.filterKeys(k => k.length == 2); - Console.println(fmap); - } - - def hashSet = { - val set = new HashSet[String]; - set + "hello" + "world" + "you" + "to"; - Console.println(set); - val fset = set.projection.filter(s => s.length <= 3); - Console.println(fset); - fset += "xxx"; - Console.println(set); - try { - fset += "xxxx"; - throw new Error; - } catch { - case e : IllegalArgumentException => - case _ => throw new Error; - } - //val mset : MutableIterable[Int] = set // set.projection.map(s => s.length); - //Console.println(mset); - //mset.retain(n => n < 5); - Console.println(set); - val set1 = new HashSet[String] + "1" + "2" + "3"; - set ++ (set1); - Console.println(set); - set.transform(s => "x_" + s); - Console.println(set); - } -} diff --git a/src/library/jvm/scala/collection/jcl/TreeMap.scala b/src/library/jvm/scala/collection/jcl/TreeMap.scala deleted file mode 100644 index c01584851d..0000000000 --- a/src/library/jvm/scala/collection/jcl/TreeMap.scala +++ /dev/null @@ -1,24 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2008, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://www.scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl - -/** A sorted map that is backed by a Java tree map. - * - * @author Sean McDirmid - */ -class TreeMap[K <% Ordered[K], E] extends SortedMapWrapper[K, E] { tm => - val underlying = (new java.util.TreeMap[K, E](new Comparator[K])) - override def clone: TreeMap[K, E] = - new TreeMap[K, E] { - override val underlying = - tm.underlying.clone().asInstanceOf[java.util.TreeMap[K, E]] - } -} diff --git a/src/library/jvm/scala/collection/jcl/TreeSet.scala b/src/library/jvm/scala/collection/jcl/TreeSet.scala deleted file mode 100644 index e708349763..0000000000 --- a/src/library/jvm/scala/collection/jcl/TreeSet.scala +++ /dev/null @@ -1,26 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2008, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://www.scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl - -/** Creates a sorted set that is backed by an underlying Java tree set. - * Elements of the sorted set are ordered with respect to the ordered - * view bound of A. - * - * @author Sean McDirmid - */ -class TreeSet[A <% Ordered[A]] extends SortedSetWrapper[A] { ts => - val underlying = new java.util.TreeSet[A](new Comparator[A]) - override def clone: TreeSet[A] = - new TreeSet[A] { - override val underlying = - ts.underlying.clone().asInstanceOf[java.util.TreeSet[A]] - } -} diff --git a/src/library/jvm/scala/collection/jcl/WeakHashMap.scala b/src/library/jvm/scala/collection/jcl/WeakHashMap.scala deleted file mode 100644 index 1d8ff4207e..0000000000 --- a/src/library/jvm/scala/collection/jcl/WeakHashMap.scala +++ /dev/null @@ -1,31 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2008, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://www.scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.collection.jcl - -/**

- * A map that is backed by a Java weak hash map, whose keys are maintained - * as weak references. - *

- *

- * Because keys are weak references, the garbage collector can collect - * them if they are not referred to elsewhere. - *

- *

- * Useful for implementing caches. - *

- * - * @author Sean McDirmid - */ -class WeakHashMap[K, E](override val underlying: java.util.WeakHashMap[K, E]) extends MapWrapper[K, E] { - def this() = this(new java.util.WeakHashMap[K, E]) - override def clone: WeakHashMap[K, E] = - throw new CloneNotSupportedException("The underlying map doesn't implement the Cloneable interface") -} diff --git a/src/library/jvm/scala/collection/mutable/JavaMapAdaptor.scala b/src/library/jvm/scala/collection/mutable/JavaMapAdaptor.scala deleted file mode 100644 index b912057c28..0000000000 --- a/src/library/jvm/scala/collection/mutable/JavaMapAdaptor.scala +++ /dev/null @@ -1,69 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.collection.mutable - - -/** This class can be used as an adaptor to create mutable maps from - * Java classes that implementat the java.util.Map interface. - * - * @author Matthias Zenger - * @version 1.0, 21/07/2003 - * @deprecated Use scala.collection.jcl.Map(jmap) instead - */ -@deprecated class JavaMapAdaptor[A, B](jmap: java.util.Map[A, B]) extends Map[A, B] { - - def size: Int = jmap.size() - - def get(key: A): Option[B] = - if (jmap.containsKey(key)) Some(jmap.get(key).asInstanceOf[B]) else None - - override def isEmpty: Boolean = jmap.isEmpty() - - override def apply(key: A): B = jmap.get(key).asInstanceOf[B] - - override def contains(key: A): Boolean = jmap.containsKey(key) - - override def isDefinedAt(key: A) = jmap.containsKey(key) - - override def keys: Iterator[A] = new Iterator[A] { - val iter = jmap.keySet().iterator() - def hasNext = iter.hasNext() - def next = iter.next().asInstanceOf[A] - } - - override def values: Iterator[B] = new Iterator[B] { - val iter = jmap.values().iterator() - def hasNext = iter.hasNext() - def next = iter.next().asInstanceOf[B] - } - - def elements: Iterator[(A, B)] = new Iterator[(A, B)] { - val iter = jmap.keySet().iterator() - def hasNext = iter.hasNext() - def next = { - val key = iter.next().asInstanceOf[A] - (key, apply(key)) - } - } - - def update(key: A, value: B): Unit = { val x = jmap.put(key, value); } - - def -= (key: A): Unit = { val x = jmap.remove(key); } - - override def clear(): Unit = jmap.clear() - - override def clone(): Map[A, B] = { - val res = new HashMap[A, B] - res ++= this - res - } -} diff --git a/src/library/jvm/scala/collection/mutable/JavaSetAdaptor.scala b/src/library/jvm/scala/collection/mutable/JavaSetAdaptor.scala deleted file mode 100644 index f3a6f3386d..0000000000 --- a/src/library/jvm/scala/collection/mutable/JavaSetAdaptor.scala +++ /dev/null @@ -1,47 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.collection.mutable - - -/** This class can be used as an adaptor to create mutable sets from - * Java classes that implement interface java.util.Set. - * - * @author Matthias Zenger - * @version 1.0, 19/09/2003 - * @deprecated Use scala.collection.jcl.Set(jmap) instead - */ -@deprecated class JavaSetAdaptor[A](jset: java.util.Set[A]) extends Set[A] { - - def size: Int = jset.size() - - override def isEmpty: Boolean = jset.isEmpty() - - def contains(elem: A): Boolean = jset.contains(elem) - - def elements: Iterator[A] = new Iterator[A] { - val iter = jset.iterator() - def hasNext = iter.hasNext() - def next = iter.next().asInstanceOf[A] - } - - def +=(elem: A): Unit = { val x = jset.add(elem); } - - def -=(elem: A): Unit = { val x = jset.remove(elem); } - - override def clear(): Unit = jset.clear() - - override def clone(): Set[A] = { - val res = new HashSet[A] - res ++= this - res - } -} diff --git a/src/library/jvm/scala/concurrent/ops.scala b/src/library/jvm/scala/concurrent/ops.scala deleted file mode 100644 index 0d3c485300..0000000000 --- a/src/library/jvm/scala/concurrent/ops.scala +++ /dev/null @@ -1,78 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.concurrent - - -import java.lang.Thread - -/** The object ops ... - * - * @author Martin Odersky, Stepan Koltsov - * @version 1.0, 12/03/2003 - */ -object ops { - - /** - * @param p ... - */ - def spawn(p: => Unit) = { - val t = new Thread() { override def run() = p } - t.start() - } - - /** - * @param p ... - * @return ... - */ - def future[A](p: => A): () => A = { - val result = new SyncVar[A] - spawn { result setWithCatch p } - () => result.get - } - - /** - * @param xp ... - * @param yp ... - * @return ... - */ - def par[A, B](xp: => A, yp: => B): (A, B) = { - val y = new SyncVar[B] - spawn { y setWithCatch yp } - (xp, y.get) - } - - /** - * @param start ... - * @param end ... - * @param p ... - */ - def replicate(start: Int, end: Int)(p: Int => Unit) { - if (start == end) - () - else if (start + 1 == end) - p(start) - else { - val mid = (start + end) / 2 - spawn { replicate(start, mid)(p) } - replicate(mid, end)(p) - } - } - -/* - def parMap[a,b](f: a => b, xs: Array[a]): Array[b] = { - val results = new Array[b](xs.length); - replicate(0, xs.length) { i => results(i) = f(xs(i)) } - results - } -*/ - -} diff --git a/src/library/jvm/scala/io/BufferedSource.scala b/src/library/jvm/scala/io/BufferedSource.scala deleted file mode 100644 index 99d8d036ae..0000000000 --- a/src/library/jvm/scala/io/BufferedSource.scala +++ /dev/null @@ -1,98 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2008, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.io - -import java.io.InputStream -import java.nio.{ByteBuffer, CharBuffer} -import java.nio.channels.{ByteChannel, Channels, ReadableByteChannel} -import java.nio.charset.{Charset, CharsetDecoder} - -object BufferedSource { - - /** same as fromInputStream(inpStream, Charset.forName(enc), buffer_size, do_reset) */ - def fromInputStream(inpStream: InputStream, enc: String, buffer_size: Int, do_reset: () => Source): BufferedSource = - fromInputStream(inpStream, Charset.forName(enc), buffer_size, do_reset) - - /** same as fromInputStream(inpStream, charSet.newDecoder(), buffer_size, do_reset) */ - def fromInputStream(inpStream: InputStream, charSet: Charset, buffer_size: Int, do_reset: () => Source): BufferedSource = - fromInputStream(inpStream, charSet.newDecoder(), buffer_size, do_reset) - - /** constructs a BufferedSource instance from an input stream, using given decoder */ - def fromInputStream(inpStream: InputStream, decoder: CharsetDecoder, buffer_size: Int, do_reset: () => Source): BufferedSource = { - val byteChannel = Channels.newChannel(inpStream) - return new BufferedSource(byteChannel, decoder) { - val buf_size = buffer_size - override def reset = do_reset() - def close { inpStream.close } - } - } -} - -/** This object provides convenience methods to create an iterable - * representation of a source file. - * - * @author Burak Emir - * @version 1.0, 19/08/2004 - */ -abstract class BufferedSource(byteChannel: ReadableByteChannel, decoder: CharsetDecoder) extends Source { - - val buf_size: Int - - def close: Unit - - val byteBuffer = ByteBuffer.allocate(buf_size) - var charBuffer = CharBuffer.allocate(buf_size) - byteBuffer.position(byteBuffer.limit()) - charBuffer.position(charBuffer.limit()) - decoder.reset() - var endOfInput = false - - def fillBuffer() = { - byteBuffer.compact() - charBuffer.position(0) - var num_bytes = byteChannel.read(byteBuffer) - while (0 == num_bytes) { - Thread.sleep(1); // wait 1 ms for new data - num_bytes = byteChannel.read(byteBuffer) - } - num_bytes match { - case -1 => - endOfInput = true; - byteBuffer.position(0) - decoder.decode(byteBuffer, charBuffer, true) - decoder.flush(charBuffer) - case num_bytes => - endOfInput = false - byteBuffer.flip() - decoder.decode(byteBuffer, charBuffer, false) - charBuffer.flip() - } - } - override val iter = new Iterator[Char] { - var buf_char = { - fillBuffer() - if (endOfInput) ' ' else charBuffer.get() - } - def hasNext = { charBuffer.remaining() > 0 || !endOfInput} - def next = { - val c = buf_char - if (charBuffer.remaining() == 0) { - fillBuffer() - } - if (!endOfInput) { - buf_char = charBuffer.get() - } - c - } - } -} - diff --git a/src/library/jvm/scala/io/Source.scala b/src/library/jvm/scala/io/Source.scala deleted file mode 100644 index 90bff94028..0000000000 --- a/src/library/jvm/scala/io/Source.scala +++ /dev/null @@ -1,400 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2008, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.io - - -import java.io.{BufferedInputStream, File, FileInputStream, InputStream, - PrintStream} -import java.nio.{ByteBuffer, CharBuffer} -import java.nio.charset.Charset -import java.net.{URI, URL} - -/** This object provides convenience methods to create an iterable - * representation of a source file. - * - * @author Burak Emir - * @version 1.0, 19/08/2004 - */ -object Source { - - val DefaultBufSize = 2048 - - val NoReset: () => Source = () => throw new UnsupportedOperationException() - - /** Creates a Source instance from the given array of bytes, - * with empty description. - * - * @param bytes ... - * @return the created Source instance. - */ - def fromBytes(bytes: Array[Byte]): Source = - fromString(new String(bytes)) - - /** Creates Source from array of bytes with given encoding, with - * empty description. - * - * @param bytes ... - * @param enc ... - * @return ... - */ - def fromBytes(bytes: Array[Byte], enc: String): Source = - fromString(new String(bytes, enc)) - - /** Creates a Source instance from a single character. - * - * @param c ... - * @return the create Source instance. - */ - def fromChar(c: Char): Source = { - val it = Iterator.single(c) - new Source { - def reset() = fromChar(c) - val iter = it - } - } - - /** creates Source from array of characters, with empty description. - * - * @param chars ... - * @return ... - */ - def fromChars(chars: Array[Char]): Source = { - val it = chars.elements - new Source { - def reset() = fromChars(chars) - val iter = it - } - } - - /** creates Source from string, with empty description. - * - * @param s ... - * @return ... - */ - def fromString(s: String): Source = { - val it = s.elements - new Source { - def reset() = fromString(s) - val iter = it - } - } - - /** creates Source from file with given name, setting its description to - * filename. - */ - def fromFile(name: String): Source = - fromFile(name, util.Properties.encodingString) - - /** creates Source from file with given name, using given encoding, setting - * its description to filename. - */ - def fromFile(name: String, enc: String): Source = - fromFile(new File(name), enc) - - /** creates Source from file with given file: URI - */ - def fromFile(uri: URI): Source = - fromFile(uri, util.Properties.encodingString) - - /** creates Source from file with given file: URI - */ - def fromFile(uri: URI, enc: String): Source = - fromFile(new File(uri), enc) - - /** creates Source from file, using default character encoding, setting its - * description to filename. - */ - def fromFile(file: File): Source = - fromFile(file, util.Properties.encodingString, Source.DefaultBufSize) - - /** same as fromFile(file, enc, Source.DefaultBufSize) - */ - def fromFile(file: File, enc: String): Source = - fromFile(file, enc, Source.DefaultBufSize) - - /** Creates Source from file, using given character encoding, - * setting its description to filename. Input is buffered in a buffer of - * size bufferSize. - */ - def fromFile(file: File, enc: String, bufferSize: Int): Source = { - val inpStream = new FileInputStream(file) - val size = if (bufferSize > 0) bufferSize else Source.DefaultBufSize - setFileDescriptor(file, - BufferedSource.fromInputStream(inpStream, enc, size, { () => fromFile(file, enc, size)})) - } - - /** This method sets the descr property of the given source to a string of the form "file:"+path - * @param file the file whose path we want to describe - * @param s the source whose property we set - * @return s - */ - private def setFileDescriptor(file: File, s: Source): Source = { - s.descr = new StringBuilder("file:").append(file.getAbsolutePath()).toString(); - s - } - - /** - * @param s ... - * @return ... - * @deprecated use fromURL(s, enc) - */ - def fromURL(s: String): Source = - fromURL(new URL(s)) - - /** same as fromURL(new URL(s), enc) - */ - def fromURL(s: String, enc:String): Source = - fromURL(new URL(s), enc) - - /** - * @param url ... - * @return ... - * @deprecated use fromURL(url, enc) - */ - def fromURL(url: URL): Source = { - val it = new Iterator[Char] { - var data: Int = _ - def hasNext = {data != -1} - def next = {val x = data.asInstanceOf[Char]; data = bufIn.read(); x} - val in = url.openStream() - val bufIn = new BufferedInputStream(in) - data = bufIn.read() - } - val s = new Source { - def reset() = fromURL(url) - val iter = it - } - s.descr = url.toString() - s - } - - /** same as fromInputStream(url.openStream(), enc) - */ - def fromURL(url: URL, enc:String): Source = - fromInputStream(url.openStream(), enc) - - /** reads data from istream into a byte array, and calls - * fromBytes with given encoding enc. - * If maxlen is given, reads not more bytes than maxlen; - * if maxlen was not given, or was <= 0, then - * whole istream is read and closed afterwards. - * - * @param istream the input stream from which to read - * @param enc the encoding to apply to the bytes - * @param maxlen optionally, a positive int specifying maximum number of bytes to read - */ - @deprecated def fromInputStream(istream: InputStream, enc: String, maxlen: Option[Int]): Source = { - val limit = maxlen match { case Some(i) => i; case None => 0 } - val bi = new BufferedInputStream(istream, Source.DefaultBufSize) - val bytes = new collection.mutable.ArrayBuffer[Byte]() - var b = 0 - var i = 0 - while( {b = bi.read; i += 1; b} != -1 && (limit <= 0 || i < limit)) { - bytes += b.toByte; - } - if(limit <= 0) bi.close - fromBytes(bytes.toArray, enc) - } - - /** same as BufferedSource.fromInputStream(is, enc, Source.DefaultBufSize) - */ - def fromInputStream(is: InputStream, enc: String): Source = - BufferedSource.fromInputStream(is, enc, Source.DefaultBufSize, { () => fromInputStream(is, enc) }) - - /** same as BufferedSource.fromInputStream(is, "utf-8", Source.DefaultBufSize) */ - def fromInputStream(is: InputStream): Source = - BufferedSource.fromInputStream(is, "utf-8", Source.DefaultBufSize, { () => fromInputStream(is) }) - -} - -/** The class Source implements an iterable representation - * of source files. Calling method reset returns an identical, - * resetted source. - * - * @author Burak Emir - * @version 1.0 - */ -abstract class Source extends Iterator[Char] { - - // ------ protected values - - /** the actual iterator */ - protected val iter: Iterator[Char] - - protected var cline = 1 - protected var ccol = 1 - - // ------ public values - - /** position of last character returned by next*/ - var pos = 0 - - /** the last character returned by next. - * the value before the first call to next is undefined. - */ - var ch: Char = _ - - /** description of this source, default empty */ - var descr: String = "" - - var nerrors = 0 - var nwarnings = 0 - - /** default col increment for tabs '\t', set to 4 initially - */ - var tabinc = 4 - - // - // -- methods - // - - /** convenience method, returns given line (not including newline) - * from Source. - * - * @param line the line index, first line is 1 - * @return the character string of the specified line. - * @throws scala.compat.Platform.IllegalArgumentException - * - */ - def getLine(line: Int): String = { // faster than getLines.drop(line).next - // todo: should @throws scala.compat.Platform.IndexOutOfBoundsException - if (line < 1) throw new IllegalArgumentException(line.toString); - val buf = new StringBuilder() - val it = reset - var i = 0 - - while (it.hasNext && i < (line-1)) - if ('\n' == it.next) - i += 1; - - if (!it.hasNext) // this should not happen - throw new IllegalArgumentException( - "line " + line + " does not exist" - ); - - var ch = it.next - while (it.hasNext && '\n' != ch) { - buf append ch - ch = it.next - } - - if ('\n' != ch) - buf append ch - - val res = buf.toString() - buf setLength 0 // hopefully help collector to deallocate StringBuilder - res - } - - /** returns an iterator who returns lines (including newline character). - * a line ends in \n. - */ - def getLines: Iterator[String] = new Iterator[String] { - val buf = new StringBuilder - def next = { - var ch = iter.next - while(ch != '\n' && iter.hasNext) { - buf append ch - ch = iter.next - } - buf.append(ch) - val res = buf.toString() - buf setLength 0 // clean things up for next call of "next" - res - } - def hasNext = iter.hasNext - } - /** Returns true if this source has more characters. - */ - def hasNext = iter.hasNext - - /** returns next character and has the following side-effects: updates - * position (ccol and cline) and assigns the character to ch - */ - def next = { - ch = iter.next - pos = Position.encode(cline,ccol) - ch match { - case '\n' => - ccol = 1 - cline += 1 - case '\t' => - ccol += tabinc - case _ => - ccol += 1 - } - ch - } - - /** Reports an error message to console. - * - * @param pos ... - * @param msg the error message to report - */ - def reportError(pos: Int, msg: String) { - reportError(pos, msg, java.lang.System.out) - } - - /** Reports an error message to the output stream out. - * - * @param pos ... - * @param msg the error message to report - * @param out ... - */ - def reportError(pos: Int, msg: String, out: PrintStream) { - nerrors = nerrors + 1 - report(pos, msg, out) - } - - /** - * @param pos ... - * @param msg the error message to report - * @param out ... - */ - def report(pos: Int, msg: String, out: PrintStream) { - val buf = new StringBuilder - val line = Position.line(pos) - val col = Position.column(pos) - buf.append(descr + ":" + line + ":" + col + ": " + msg) - buf.append(getLine(line)) - var i = 1 - while (i < col) { - buf.append(' ') - i += 1 - } - buf.append('^') - out.println(buf.toString) - } - - /** Reports a warning message to java.lang.System.out. - * - * @param pos ... - * @param msg the warning message to report - */ - def reportWarning(pos: Int, msg: String) { - reportWarning(pos, msg, java.lang.System.out) - } - - /** - * @param pos ... - * @param msg the warning message to report - * @param out ... - */ - def reportWarning(pos: Int, msg: String, out: PrintStream) { - nwarnings = nwarnings + 1 - report(pos, "warning! " + msg, out) - } - - /** the actual reset method */ - def reset(): Source - -} diff --git a/src/library/jvm/scala/reflect/BeanInfo.scala b/src/library/jvm/scala/reflect/BeanInfo.scala deleted file mode 100644 index a5ea0fb975..0000000000 --- a/src/library/jvm/scala/reflect/BeanInfo.scala +++ /dev/null @@ -1,22 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2008, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.reflect - -/**

- * This attribute indicates that a JavaBean-compliant BeanInfo - * class should be generated for this attributed Scala class. - * A val becomes a read-only property. A var becomes a read-write - * property. A def becomes a method. - *

- * - * @author Ross Judson (rjudson@managedobjects.com) - */ -class BeanInfo extends Annotation diff --git a/src/library/jvm/scala/reflect/BeanProperty.scala b/src/library/jvm/scala/reflect/BeanProperty.scala deleted file mode 100644 index 4a09578df9..0000000000 --- a/src/library/jvm/scala/reflect/BeanProperty.scala +++ /dev/null @@ -1,33 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.reflect - -/**

- * This attribute adds a setter and a getter method, following the - * Java Bean convention (first letter of the property is capitalized) - * used by popular Java web frameworks. For example: - *

- *    @BeanProperty
- *    var status = ""
- *

- * adds the following methods to the generated code - *

- *    def setStatus(s: String) { this.status = s }
- *    def getStatus: String = this.status
- *  
- *

- * However, you cannot call setStatus from - * Scala, - * you should use the normal Scala access and assignment. - *

- */ -class BeanProperty extends Annotation diff --git a/src/library/jvm/scala/reflect/ScalaBeanInfo.scala b/src/library/jvm/scala/reflect/ScalaBeanInfo.scala deleted file mode 100644 index f8ea948818..0000000000 --- a/src/library/jvm/scala/reflect/ScalaBeanInfo.scala +++ /dev/null @@ -1,47 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2008, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.reflect - -/** Provides some simple runtime processing necessary to create - * JavaBean descriptors for Scala entities. The compiler creates - * subclasses of this class automatically when the BeanInfo annotation is - * attached to a class. - * - * @author Ross Judson (rjudson@managedobjects.com) - */ -abstract class ScalaBeanInfo(clazz: java.lang.Class[_], - props: Array[String], - methods: Array[String]) extends java.beans.SimpleBeanInfo { - - import java.beans._ - - private val pd = new Array[PropertyDescriptor](props.length / 3) - private val md = - for (m <- clazz.getMethods if methods.exists(_ == m.getName)) - yield new MethodDescriptor(m) - - init - - override def getPropertyDescriptors() = pd - override def getMethodDescriptors() = md - - // override def getAdditionalBeanInfo() = Array(Introspector getBeanInfo clazz.getSuperclass) - - private def init { - var i = 0; - while (i < props.length) { - pd(i/3) = new PropertyDescriptor(props(i), clazz, props(i+1), props(i+2)) - i = i + 3; - } - } - -} - diff --git a/src/library/jvm/scala/runtime/BooleanRef.java b/src/library/jvm/scala/runtime/BooleanRef.java deleted file mode 100644 index e7c2467329..0000000000 --- a/src/library/jvm/scala/runtime/BooleanRef.java +++ /dev/null @@ -1,21 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2008, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.runtime; - - -public class BooleanRef implements java.io.Serializable { - private static final long serialVersionUID = -5730524563015615974L; - - public boolean elem; - public BooleanRef(boolean elem) { this.elem = elem; } - public String toString() { return "" + elem; } -} diff --git a/src/library/jvm/scala/runtime/BoxedUnit.java b/src/library/jvm/scala/runtime/BoxedUnit.java deleted file mode 100644 index fe6a4b9265..0000000000 --- a/src/library/jvm/scala/runtime/BoxedUnit.java +++ /dev/null @@ -1,33 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2008, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.runtime; - - -public final class BoxedUnit implements java.io.Serializable { - private static final long serialVersionUID = 8405543498931817370L; - - public final static BoxedUnit UNIT = new BoxedUnit(); - - private BoxedUnit() { } - - public boolean equals(java.lang.Object other) { - return this == other; - } - - public int hashCode() { - return 0; - } - - public String toString() { - return "()"; - } -} diff --git a/src/library/jvm/scala/runtime/BoxesRunTime.java b/src/library/jvm/scala/runtime/BoxesRunTime.java deleted file mode 100644 index a8e0549449..0000000000 --- a/src/library/jvm/scala/runtime/BoxesRunTime.java +++ /dev/null @@ -1,845 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.runtime; - -/** An object (static class) that defines methods used for creating, - * reverting, and calculating with, boxed values. There are four classes - * of methods in this object: - * - High-performance value boxing methods that feed from a pre- - * computed map of instances for the most common instanciations. - * - Convenience unboxing methods returning default value on null. - * - The generalised comparison method to be used when an object may - * be a boxed value. - * - Standard value operators for boxed number and quasi-number values. - * - * @author Gilles Dubochet - * @author Martin Odersky - * @contributor Stepan Koltsov - * @version 2.0 */ -public class BoxesRunTime { - - private static final int CHAR = 0, BYTE = 1, SHORT = 2, INT = 3, LONG = 4, FLOAT = 5, DOUBLE = 6, OTHER = 7; - - private static int typeCode(Object a) { - if (a instanceof Integer) return INT; - if (a instanceof Character) return CHAR; - if (a instanceof Long) return LONG; - if (a instanceof Double) return DOUBLE; - if (a instanceof Float) return FLOAT; - if (a instanceof Byte) return BYTE; - if (a instanceof Short) return SHORT; - return OTHER; - } - -/* BOXING ... BOXING ... BOXING ... BOXING ... BOXING ... BOXING ... BOXING ... BOXING */ - - private static int charLowBound = 0; - private static int charUpBound = 255; - private static Character[] charCache = new Character[charUpBound - charLowBound + 1]; - - private static int byteLowBound = -128; - private static int byteUpBound = 127; - private static Byte[] byteCache = new Byte[byteUpBound - byteLowBound + 1]; - - private static int shortLowBound = -128; - private static int shortUpBound = 127; - private static Short[] shortCache = new Short[shortUpBound - shortLowBound + 1]; - - private static int intLowBound = -128; - private static int intUpBound = 1024; - private static Integer[] intCache = new Integer[intUpBound - intLowBound + 1]; - - private static int longLowBound = -128; - private static int longUpBound = 1024; - private static Long[] longCache = new Long[longUpBound - longLowBound + 1]; - - static { - int idx = 0; - while (idx <= charUpBound - charLowBound) { - charCache[idx] = new Character((char)(idx + charLowBound)); - idx = idx + 1; - } - idx = 0; - while (idx <= byteUpBound - byteLowBound) { - byteCache[idx] = new Byte((byte)(idx + byteLowBound)); - idx = idx + 1; - } - idx = 0; - while (idx <= shortUpBound - shortLowBound) { - shortCache[idx] = new Short((short)(idx + shortLowBound)); - idx = idx + 1; - } - idx = 0; - while (idx <= intUpBound - intLowBound) { - intCache[idx] = new Integer((int)(idx + intLowBound)); - idx = idx + 1; - } - idx = 0; - while (idx <= longUpBound - longLowBound) { - longCache[idx] = new Long((long)(idx + longLowBound)); - idx = idx + 1; - } - } - - public static Boolean boxToBoolean(boolean b) { - return b ? Boolean.TRUE : Boolean.FALSE; - } - - public static Character boxToCharacter(char c) { - if (c >= charLowBound && c <= charUpBound) - return charCache[(int)c - charLowBound]; - return new Character(c); - } - - public static Byte boxToByte(byte b) { - if (b >= byteLowBound && b <= byteUpBound) - return byteCache[(int)b - byteLowBound]; - return new Byte(b); - } - - public static Short boxToShort(short s) { - if (s >= shortLowBound && s <= shortUpBound) - return shortCache[(int)s - shortLowBound]; - return new Short(s); - } - - public static Integer boxToInteger(int i) { - if (i >= intLowBound && i <= intUpBound) - return intCache[(int)i - intLowBound]; - return new Integer(i); - } - - public static Long boxToLong(long l) { - if (l >= longLowBound && l <= longUpBound) - return longCache[(int)l - longLowBound]; - return new Long(l); - } - - public static Float boxToFloat(float f) { - return new Float(f); - } - - public static Double boxToDouble(double d) { - return new Double(d); - } - -/* UNBOXING ... UNBOXING ... UNBOXING ... UNBOXING ... UNBOXING ... UNBOXING ... UNBOXING */ - - public static boolean unboxToBoolean(Object b) { - return b == null ? false : ((Boolean)b).booleanValue(); - } - - public static char unboxToChar(Object c) { - return c == null ? 0 : ((Character)c).charValue(); - } - - public static byte unboxToByte(Object b) { - return b == null ? 0 : ((Byte)b).byteValue(); - } - - public static short unboxToShort(Object s) { - return s == null ? 0 : ((Short)s).shortValue(); - } - - public static int unboxToInt(Object i) { - return i == null ? 0 : ((Integer)i).intValue(); - } - - public static long unboxToLong(Object l) { - return l == null ? 0 : ((Long)l).longValue(); - } - - public static float unboxToFloat(Object f) { - return f == null ? 0.0f : ((Float)f).floatValue(); - } - - public static double unboxToDouble(Object d) { - return d == null ? 0.0d : ((Double)d).doubleValue(); - } - - /* - public static boolean unboxToBoolean(Object b) { - if (b == null) - throw new ClassCastException("null is no Boolean value"); - return ((Boolean)b).booleanValue(); - } - - public static char unboxToChar(Object c) { - if (c == null) - throw new ClassCastException("null is no Char value"); - return ((Character)c).charValue(); - } - - public static byte unboxToByte(Object b) { - if (b == null) - throw new ClassCastException("null is no Byte value"); - return ((Byte)b).byteValue(); - } - - public static short unboxToShort(Object s) { - if (s == null) - throw new ClassCastException("null is no Short value"); - return ((Short)s).shortValue(); - } - - public static int unboxToInt(Object i) { - if (i == null) - throw new ClassCastException("null is no Int value"); - return ((Integer)i).intValue(); - } - - public static long unboxToLong(Object l) { - if (l == null) - throw new ClassCastException("null is no Long value"); - return ((Long)l).longValue(); - } - - public static float unboxToFloat(Object f) { - if (f == null) - throw new ClassCastException("null is no Float value"); - return ((Float)f).floatValue(); - } - - public static double unboxToDouble(Object d) { - if (d == null) - throw new ClassCastException("null is no Double value"); - return ((Double)d).doubleValue(); - } - */ - -/* COMPARISON ... COMPARISON ... COMPARISON ... COMPARISON ... COMPARISON ... COMPARISON */ - - /** A rich implementation of the equals method that overrides the - * default equals because Java's boxed primitives are utterly broken. This equals - * is inserted instead of a normal equals by the Scala compiler (in the - * ICode phase, method genEqEqPrimitive) only when either - * side of the comparison is a subclass of AnyVal, of - * java.lang.Number, of java.lang.Character or - * is exactly Any or AnyRef. */ - public static boolean equals(Object a, Object b) { - if (a == null || b == null) - return a == b; - if (a.equals(b)) - return true; - if (a instanceof Number || a instanceof Character || b instanceof Number || b instanceof Character) { - int acode = typeCode(a); - int bcode = typeCode(b); - int maxcode = (acode < bcode) ? bcode : acode; - if (maxcode <= INT) { - int aa = (acode == CHAR) ? ((Character) a).charValue() : ((Number) a).intValue(); - int bb = (bcode == CHAR) ? ((Character) b).charValue() : ((Number) b).intValue(); - return aa == bb; - } - if (maxcode <= LONG) { - long aa = (acode == CHAR) ? ((Character) a).charValue() : ((Number) a).longValue(); - long bb = (bcode == CHAR) ? ((Character) b).charValue() : ((Number) b).longValue(); - return aa == bb; - } - if (maxcode <= FLOAT) { - float aa = (acode == CHAR) ? ((Character) a).charValue() : ((Number) a).floatValue(); - float bb = (bcode == CHAR) ? ((Character) b).charValue() : ((Number) b).floatValue(); - return aa == bb; - } - if (maxcode <= DOUBLE) { - double aa = (acode == CHAR) ? ((Character) a).charValue() : ((Number) a).doubleValue(); - double bb = (bcode == CHAR) ? ((Character) b).charValue() : ((Number) b).doubleValue(); - return aa == bb; - } - return b.equals(a); - } - return false; - } - -/* OPERATORS ... OPERATORS ... OPERATORS ... OPERATORS ... OPERATORS ... OPERATORS ... OPERATORS ... OPERATORS */ - - /** arg1 + arg2 */ - public static Object add(Object arg1, Object arg2) throws NoSuchMethodException { - int code1 = typeCode(arg1); - int code2 = typeCode(arg2); - int maxcode = (code1 < code2) ? code2 : code1; - if (maxcode <= INT) { - int val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).intValue(); - int val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).intValue(); - return boxToInteger(val1 + val2); - } - if (maxcode <= LONG) { - long val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).longValue(); - long val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).longValue(); - return boxToLong(val1 + val2); - } - if (maxcode <= FLOAT) { - float val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).floatValue(); - float val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).floatValue(); - return boxToFloat(val1 + val2); - } - if (maxcode <= DOUBLE) { - double val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).doubleValue(); - double val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).doubleValue(); - return boxToDouble(val1 + val2); - } - throw new NoSuchMethodException(); - } - - /** arg1 - arg2 */ - public static Object subtract(Object arg1, Object arg2) throws NoSuchMethodException { - int code1 = typeCode(arg1); - int code2 = typeCode(arg2); - int maxcode = (code1 < code2) ? code2 : code1; - if (maxcode <= INT) { - int val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).intValue(); - int val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).intValue(); - return boxToInteger(val1 - val2); - } - if (maxcode <= LONG) { - long val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).longValue(); - long val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).longValue(); - return boxToLong(val1 - val2); - } - if (maxcode <= FLOAT) { - float val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).floatValue(); - float val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).floatValue(); - return boxToFloat(val1 - val2); - } - if (maxcode <= DOUBLE) { - double val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).doubleValue(); - double val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).doubleValue(); - return boxToDouble(val1 - val2); - } - throw new NoSuchMethodException(); - } - - /** arg1 * arg2 */ - public static Object multiply(Object arg1, Object arg2) throws NoSuchMethodException { - int code1 = typeCode(arg1); - int code2 = typeCode(arg2); - int maxcode = (code1 < code2) ? code2 : code1; - if (maxcode <= INT) { - int val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).intValue(); - int val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).intValue(); - return boxToInteger(val1 * val2); - } - if (maxcode <= LONG) { - long val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).longValue(); - long val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).longValue(); - return boxToLong(val1 * val2); - } - if (maxcode <= FLOAT) { - float val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).floatValue(); - float val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).floatValue(); - return boxToFloat(val1 * val2); - } - if (maxcode <= DOUBLE) { - double val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).doubleValue(); - double val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).doubleValue(); - return boxToDouble(val1 * val2); - } - throw new NoSuchMethodException(); - } - - /** arg1 / arg2 */ - public static Object divide(Object arg1, Object arg2) throws NoSuchMethodException { - int code1 = typeCode(arg1); - int code2 = typeCode(arg2); - int maxcode = (code1 < code2) ? code2 : code1; - if (maxcode <= INT) { - int val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).intValue(); - int val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).intValue(); - return boxToInteger(val1 / val2); - } - if (maxcode <= LONG) { - long val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).longValue(); - long val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).longValue(); - return boxToLong(val1 / val2); - } - if (maxcode <= FLOAT) { - float val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).floatValue(); - float val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).floatValue(); - return boxToFloat(val1 / val2); - } - if (maxcode <= DOUBLE) { - double val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).doubleValue(); - double val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).doubleValue(); - return boxToDouble(val1 / val2); - } - throw new NoSuchMethodException(); - } - - /** arg1 % arg2 */ - public static Object takeModulo(Object arg1, Object arg2) throws NoSuchMethodException { - int code1 = typeCode(arg1); - int code2 = typeCode(arg2); - int maxcode = (code1 < code2) ? code2 : code1; - if (maxcode <= INT) { - int val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).intValue(); - int val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).intValue(); - return boxToInteger(val1 % val2); - } - if (maxcode <= LONG) { - long val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).longValue(); - long val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).longValue(); - return boxToLong(val1 % val2); - } - if (maxcode <= FLOAT) { - float val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).floatValue(); - float val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).floatValue(); - return boxToFloat(val1 % val2); - } - if (maxcode <= DOUBLE) { - double val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).doubleValue(); - double val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).doubleValue(); - return boxToDouble(val1 % val2); - } - throw new NoSuchMethodException(); - } - - /** arg1 >> arg2 */ - public static Object shiftSignedRight(Object arg1, Object arg2) throws NoSuchMethodException { - int code1 = typeCode(arg1); - int code2 = typeCode(arg2); - if (code1 <= INT) { - int val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).intValue(); - if (code2 <= INT) { - int val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).intValue(); - return boxToInteger(val1 >> val2); - } - if (code2 <= LONG) { - long val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).longValue(); - return boxToInteger(val1 >> val2); - } - } - if (code1 <= LONG) { - long val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).longValue(); - if (code2 <= INT) { - int val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).intValue(); - return boxToLong(val1 >> val2); - } - if (code2 <= LONG) { - long val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).longValue(); - return boxToLong(val1 >> val2); - } - } - throw new NoSuchMethodException(); - } - - /** arg1 << arg2 */ - public static Object shiftSignedLeft(Object arg1, Object arg2) throws NoSuchMethodException { - int code1 = typeCode(arg1); - int code2 = typeCode(arg2); - if (code1 <= INT) { - int val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).intValue(); - if (code2 <= INT) { - int val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).intValue(); - return boxToInteger(val1 << val2); - } - if (code2 <= LONG) { - long val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).longValue(); - return boxToInteger(val1 << val2); - } - } - if (code1 <= LONG) { - long val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).longValue(); - if (code2 <= INT) { - int val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).intValue(); - return boxToLong(val1 << val2); - } - if (code2 <= LONG) { - long val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).longValue(); - return boxToLong(val1 << val2); - } - } - throw new NoSuchMethodException(); - } - - /** arg1 >>> arg2 */ - public static Object shiftLogicalRight(Object arg1, Object arg2) throws NoSuchMethodException { - int code1 = typeCode(arg1); - int code2 = typeCode(arg2); - if (code1 <= INT) { - int val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).intValue(); - if (code2 <= INT) { - int val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).intValue(); - return boxToInteger(val1 >>> val2); - } - if (code2 <= LONG) { - long val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).longValue(); - return boxToInteger(val1 >>> val2); - } - } - if (code1 <= LONG) { - long val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).longValue(); - if (code2 <= INT) { - int val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).intValue(); - return boxToLong(val1 >>> val2); - } - if (code2 <= LONG) { - long val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).longValue(); - return boxToLong(val1 >>> val2); - } - } - throw new NoSuchMethodException(); - } - - /** -arg */ - public static Object negate(Object arg) throws NoSuchMethodException { - int code = typeCode(arg); - if (code <= INT) { - int val = (code == CHAR) ? ((Character) arg).charValue() : ((Number) arg).intValue(); - return boxToInteger(-val); - } - if (code <= LONG) { - long val = (code == CHAR) ? ((Character) arg).charValue() : ((Number) arg).longValue(); - return boxToLong(-val); - } - if (code <= FLOAT) { - float val = (code == CHAR) ? ((Character) arg).charValue() : ((Number) arg).floatValue(); - return boxToFloat(-val); - } - if (code <= DOUBLE) { - double val = (code == CHAR) ? ((Character) arg).charValue() : ((Number) arg).doubleValue(); - return boxToDouble(-val); - } - throw new NoSuchMethodException(); - } - - /** +arg */ - public static Object positive(Object arg) throws NoSuchMethodException { - int code = typeCode(arg); - if (code <= INT) { - int val = (code == CHAR) ? ((Character) arg).charValue() : ((Number) arg).intValue(); - return boxToInteger(+val); - } - if (code <= LONG) { - long val = (code == CHAR) ? ((Character) arg).charValue() : ((Number) arg).longValue(); - return boxToLong(+val); - } - if (code <= FLOAT) { - float val = (code == CHAR) ? ((Character) arg).charValue() : ((Number) arg).floatValue(); - return boxToFloat(+val); - } - if (code <= DOUBLE) { - double val = (code == CHAR) ? ((Character) arg).charValue() : ((Number) arg).doubleValue(); - return boxToDouble(+val); - } - throw new NoSuchMethodException(); - } - - /** arg1 & arg2 */ - public static Object takeAnd(Object arg1, Object arg2) throws NoSuchMethodException { - if ((arg1 instanceof Boolean) || (arg2 instanceof Boolean)) { - if (!((arg1 instanceof Boolean) && (arg2 instanceof Boolean))) { - throw new NoSuchMethodException(); - } - return boxToBoolean(((Boolean) arg1).booleanValue() & ((Boolean) arg2).booleanValue()); - } - int code1 = typeCode(arg1); - int code2 = typeCode(arg2); - int maxcode = (code1 < code2) ? code2 : code1; - if (maxcode <= INT) { - int val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).intValue(); - int val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).intValue(); - return boxToInteger(val1 & val2); - } - if (maxcode <= LONG) { - long val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).longValue(); - long val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).longValue(); - return boxToLong(val1 & val2); - } - throw new NoSuchMethodException(); - } - - /** arg1 | arg2 */ - public static Object takeOr(Object arg1, Object arg2) throws NoSuchMethodException { - if ((arg1 instanceof Boolean) || (arg2 instanceof Boolean)) { - if (!((arg1 instanceof Boolean) && (arg2 instanceof Boolean))) { - throw new NoSuchMethodException(); - } - return boxToBoolean(((Boolean) arg1).booleanValue() | ((Boolean) arg2).booleanValue()); - } - int code1 = typeCode(arg1); - int code2 = typeCode(arg2); - int maxcode = (code1 < code2) ? code2 : code1; - if (maxcode <= INT) { - int val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).intValue(); - int val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).intValue(); - return boxToInteger(val1 | val2); - } - if (maxcode <= LONG) { - long val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).longValue(); - long val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).longValue(); - return boxToLong(val1 | val2); - } - throw new NoSuchMethodException(); - } - - /** arg1 ^ arg2 */ - public static Object takeXor(Object arg1, Object arg2) throws NoSuchMethodException { - if ((arg1 instanceof Boolean) || (arg2 instanceof Boolean)) { - if (!((arg1 instanceof Boolean) && (arg2 instanceof Boolean))) { - throw new NoSuchMethodException(); - } - return boxToBoolean(((Boolean) arg1).booleanValue() ^ ((Boolean) arg2).booleanValue()); - } - int code1 = typeCode(arg1); - int code2 = typeCode(arg2); - int maxcode = (code1 < code2) ? code2 : code1; - if (maxcode <= INT) { - int val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).intValue(); - int val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).intValue(); - return boxToInteger(val1 ^ val2); - } - if (maxcode <= LONG) { - long val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).longValue(); - long val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).longValue(); - return boxToLong(val1 ^ val2); - } - throw new NoSuchMethodException(); - } - - /** arg1 && arg2 */ - public static Object takeConditionalAnd(Object arg1, Object arg2) throws NoSuchMethodException { - if ((arg1 instanceof Boolean) && (arg2 instanceof Boolean)) { - return boxToBoolean(((Boolean) arg1).booleanValue() && ((Boolean) arg2).booleanValue()); - } - throw new NoSuchMethodException(); - } - - /** arg1 || arg2 */ - public static Object takeConditionalOr(Object arg1, Object arg2) throws NoSuchMethodException { - if ((arg1 instanceof Boolean) && (arg2 instanceof Boolean)) { - return boxToBoolean(((Boolean) arg1).booleanValue() || ((Boolean) arg2).booleanValue()); - } - throw new NoSuchMethodException(); - } - - /** ~arg */ - public static Object complement(Object arg) throws NoSuchMethodException { - int code = typeCode(arg); - if (code <= INT) { - int val = (code == CHAR) ? ((Character) arg).charValue() : ((Number) arg).intValue(); - return boxToInteger(~val); - } - if (code <= LONG) { - long val = (code == CHAR) ? ((Character) arg).charValue() : ((Number) arg).longValue(); - return boxToLong(~val); - } - throw new NoSuchMethodException(); - } - - /** !arg */ - public static Object takeNot(Object arg) throws NoSuchMethodException { - if (arg instanceof Boolean) { - return boxToBoolean(!((Boolean) arg).booleanValue()); - } - throw new NoSuchMethodException(); - } - - public static Object testEqual(Object arg1, Object arg2) throws NoSuchMethodException { - return boxToBoolean(arg1 == arg2); - } - - public static Object testNotEqual(Object arg1, Object arg2) throws NoSuchMethodException { - return boxToBoolean(arg1 != arg2); - } - - public static Object testLessThan(Object arg1, Object arg2) throws NoSuchMethodException { - int code1 = typeCode(arg1); - int code2 = typeCode(arg2); - int maxcode = (code1 < code2) ? code2 : code1; - if (maxcode <= INT) { - int val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).intValue(); - int val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).intValue(); - return boxToBoolean(val1 < val2); - } - if (maxcode <= LONG) { - long val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).longValue(); - long val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).longValue(); - return boxToBoolean(val1 < val2); - } - if (maxcode <= FLOAT) { - float val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).floatValue(); - float val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).floatValue(); - return boxToBoolean(val1 < val2); - } - if (maxcode <= DOUBLE) { - double val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).doubleValue(); - double val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).doubleValue(); - return boxToBoolean(val1 < val2); - } - throw new NoSuchMethodException(); - } - - public static Object testLessOrEqualThan(Object arg1, Object arg2) throws NoSuchMethodException { - int code1 = typeCode(arg1); - int code2 = typeCode(arg2); - int maxcode = (code1 < code2) ? code2 : code1; - if (maxcode <= INT) { - int val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).intValue(); - int val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).intValue(); - return boxToBoolean(val1 <= val2); - } - if (maxcode <= LONG) { - long val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).longValue(); - long val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).longValue(); - return boxToBoolean(val1 <= val2); - } - if (maxcode <= FLOAT) { - float val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).floatValue(); - float val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).floatValue(); - return boxToBoolean(val1 <= val2); - } - if (maxcode <= DOUBLE) { - double val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).doubleValue(); - double val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).doubleValue(); - return boxToBoolean(val1 <= val2); - } - throw new NoSuchMethodException(); - } - - public static Object testGreaterOrEqualThan(Object arg1, Object arg2) throws NoSuchMethodException { - int code1 = typeCode(arg1); - int code2 = typeCode(arg2); - int maxcode = (code1 < code2) ? code2 : code1; - if (maxcode <= INT) { - int val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).intValue(); - int val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).intValue(); - return boxToBoolean(val1 >= val2); - } - if (maxcode <= LONG) { - long val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).longValue(); - long val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).longValue(); - return boxToBoolean(val1 >= val2); - } - if (maxcode <= FLOAT) { - float val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).floatValue(); - float val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).floatValue(); - return boxToBoolean(val1 >= val2); - } - if (maxcode <= DOUBLE) { - double val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).doubleValue(); - double val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).doubleValue(); - return boxToBoolean(val1 >= val2); - } - throw new NoSuchMethodException(); - } - - public static Object testGreaterThan(Object arg1, Object arg2) throws NoSuchMethodException { - int code1 = typeCode(arg1); - int code2 = typeCode(arg2); - int maxcode = (code1 < code2) ? code2 : code1; - if (maxcode <= INT) { - int val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).intValue(); - int val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).intValue(); - return boxToBoolean(val1 > val2); - } - if (maxcode <= LONG) { - long val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).longValue(); - long val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).longValue(); - return boxToBoolean(val1 > val2); - } - if (maxcode <= FLOAT) { - float val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).floatValue(); - float val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).floatValue(); - return boxToBoolean(val1 > val2); - } - if (maxcode <= DOUBLE) { - double val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).doubleValue(); - double val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).doubleValue(); - return boxToBoolean(val1 > val2); - } - throw new NoSuchMethodException(); - } - - /** arg.toChar */ - public static Character toCharacter(Object arg) throws NoSuchMethodException { - if (arg instanceof Character) return (Character)arg; - if (arg instanceof Byte) return boxToCharacter((char)unboxToByte(arg)); - if (arg instanceof Short) return boxToCharacter((char)unboxToShort(arg)); - if (arg instanceof Integer) return boxToCharacter((char)unboxToInt(arg)); - if (arg instanceof Long) return boxToCharacter((char)unboxToLong(arg)); - if (arg instanceof Float) return boxToCharacter((char)unboxToFloat(arg)); - if (arg instanceof Double) return boxToCharacter((char)unboxToDouble(arg)); - throw new NoSuchMethodException(); - } - - /** arg.toByte */ - public static Byte toByte(Object arg) throws NoSuchMethodException { - if (arg instanceof Character) return boxToByte((byte)unboxToChar(arg)); - if (arg instanceof Byte) return (Byte)arg; - if (arg instanceof Short) return boxToByte((byte)unboxToShort(arg)); - if (arg instanceof Integer) return boxToByte((byte)unboxToInt(arg)); - if (arg instanceof Long) return boxToByte((byte)unboxToLong(arg)); - if (arg instanceof Float) return boxToByte((byte)unboxToFloat(arg)); - if (arg instanceof Double) return boxToByte((byte)unboxToDouble(arg)); - throw new NoSuchMethodException(); - } - - /** arg.toShort */ - public static Short toShort(Object arg) throws NoSuchMethodException { - if (arg instanceof Character) return boxToShort((short)unboxToChar(arg)); - if (arg instanceof Byte) return boxToShort((short)unboxToByte(arg)); - if (arg instanceof Short) return (Short)arg; - if (arg instanceof Integer) return boxToShort((short)unboxToInt(arg)); - if (arg instanceof Long) return boxToShort((short)unboxToLong(arg)); - if (arg instanceof Float) return boxToShort((short)unboxToFloat(arg)); - if (arg instanceof Double) return boxToShort((short)unboxToDouble(arg)); - throw new NoSuchMethodException(); - } - - /** arg.toInt */ - public static Integer toInteger(Object arg) throws NoSuchMethodException { - if (arg instanceof Character) return boxToInteger((int)unboxToChar(arg)); - if (arg instanceof Byte) return boxToInteger((int)unboxToByte(arg)); - if (arg instanceof Short) return boxToInteger((int)unboxToShort(arg)); - if (arg instanceof Integer) return (Integer)arg; - if (arg instanceof Long) return boxToInteger((int)unboxToLong(arg)); - if (arg instanceof Float) return boxToInteger((int)unboxToFloat(arg)); - if (arg instanceof Double) return boxToInteger((int)unboxToDouble(arg)); - throw new NoSuchMethodException(); - } - - /** arg.toLong */ - public static Long toLong(Object arg) throws NoSuchMethodException { - if (arg instanceof Character) return boxToLong((long)unboxToChar(arg)); - if (arg instanceof Byte) return boxToLong((long)unboxToByte(arg)); - if (arg instanceof Short) return boxToLong((long)unboxToShort(arg)); - if (arg instanceof Integer) return boxToLong((long)unboxToInt(arg)); - if (arg instanceof Long) return (Long)arg; - if (arg instanceof Float) return boxToLong((long)unboxToFloat(arg)); - if (arg instanceof Double) return boxToLong((long)unboxToDouble(arg)); - throw new NoSuchMethodException(); - } - - /** arg.toFloat */ - public static Float toFloat(Object arg) throws NoSuchMethodException { - if (arg instanceof Character) return boxToFloat((float)unboxToChar(arg)); - if (arg instanceof Byte) return boxToFloat((float)unboxToByte(arg)); - if (arg instanceof Short) return boxToFloat((float)unboxToShort(arg)); - if (arg instanceof Integer) return boxToFloat((float)unboxToInt(arg)); - if (arg instanceof Long) return boxToFloat((float)unboxToLong(arg)); - if (arg instanceof Float) return (Float)arg; - if (arg instanceof Double) return boxToFloat((float)unboxToDouble(arg)); - throw new NoSuchMethodException(); - } - - /** arg.toDouble */ - public static Double toDouble(Object arg) throws NoSuchMethodException { - if (arg instanceof Character) return boxToDouble((double)unboxToChar(arg)); - if (arg instanceof Byte) return boxToDouble((double)unboxToByte(arg)); - if (arg instanceof Short) return boxToDouble((double)unboxToShort(arg)); - if (arg instanceof Integer) return boxToDouble((double)unboxToInt(arg)); - if (arg instanceof Long) return boxToDouble((double)unboxToLong(arg)); - if (arg instanceof Float) return boxToDouble((double)unboxToFloat(arg)); - if (arg instanceof Double) return (Double)arg; - throw new NoSuchMethodException(); - } - -} diff --git a/src/library/jvm/scala/runtime/ByteRef.java b/src/library/jvm/scala/runtime/ByteRef.java deleted file mode 100644 index 1e67f18a1f..0000000000 --- a/src/library/jvm/scala/runtime/ByteRef.java +++ /dev/null @@ -1,21 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2008, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.runtime; - - -public class ByteRef implements java.io.Serializable { - private static final long serialVersionUID = -100666928446877072L; - - public byte elem; - public ByteRef(byte elem) { this.elem = elem; } - public String toString() { return Byte.toString(elem); } -} diff --git a/src/library/jvm/scala/runtime/CharRef.java b/src/library/jvm/scala/runtime/CharRef.java deleted file mode 100644 index a64b59dfd7..0000000000 --- a/src/library/jvm/scala/runtime/CharRef.java +++ /dev/null @@ -1,21 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2008, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.runtime; - - -public class CharRef implements java.io.Serializable { - private static final long serialVersionUID = 6537214938268005702L; - - public char elem; - public CharRef(char elem) { this.elem = elem; } - public String toString() { return Character.toString(elem); } -} diff --git a/src/library/jvm/scala/runtime/DoubleRef.java b/src/library/jvm/scala/runtime/DoubleRef.java deleted file mode 100644 index 086429e03e..0000000000 --- a/src/library/jvm/scala/runtime/DoubleRef.java +++ /dev/null @@ -1,21 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2008, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.runtime; - - -public class DoubleRef implements java.io.Serializable { - private static final long serialVersionUID = 8304402127373655534L; - - public double elem; - public DoubleRef(double elem) { this.elem = elem; } - public String toString() { return Double.toString(elem); } -} diff --git a/src/library/jvm/scala/runtime/ExceptionHandling.java b/src/library/jvm/scala/runtime/ExceptionHandling.java deleted file mode 100644 index 0fcc1e2b1c..0000000000 --- a/src/library/jvm/scala/runtime/ExceptionHandling.java +++ /dev/null @@ -1,26 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.runtime; - - -public abstract class ExceptionHandling { - - public static Throwable tryCatch(Runnable runnable) { - try { - runnable.run(); - return null; - } catch (Throwable exception) { - return exception; - } - } - -} diff --git a/src/library/jvm/scala/runtime/FloatRef.java b/src/library/jvm/scala/runtime/FloatRef.java deleted file mode 100644 index 2160f54977..0000000000 --- a/src/library/jvm/scala/runtime/FloatRef.java +++ /dev/null @@ -1,21 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2008, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.runtime; - - -public class FloatRef implements java.io.Serializable { - private static final long serialVersionUID = -5793980990371366933L; - - public float elem; - public FloatRef(float elem) { this.elem = elem; } - public String toString() { return Float.toString(elem); } -} diff --git a/src/library/jvm/scala/runtime/IntRef.java b/src/library/jvm/scala/runtime/IntRef.java deleted file mode 100644 index 3ad9ad69e5..0000000000 --- a/src/library/jvm/scala/runtime/IntRef.java +++ /dev/null @@ -1,21 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2008, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.runtime; - - -public class IntRef implements java.io.Serializable { - private static final long serialVersionUID = 1488197132022872888L; - - public int elem; - public IntRef(int elem) { this.elem = elem; } - public String toString() { return Integer.toString(elem); } -} diff --git a/src/library/jvm/scala/runtime/LongRef.java b/src/library/jvm/scala/runtime/LongRef.java deleted file mode 100644 index 31b9cd3b55..0000000000 --- a/src/library/jvm/scala/runtime/LongRef.java +++ /dev/null @@ -1,21 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2008, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.runtime; - - -public class LongRef implements java.io.Serializable { - private static final long serialVersionUID = -3567869820105829499L; - - public long elem; - public LongRef(long elem) { this.elem = elem; } - public String toString() { return Long.toString(elem); } -} diff --git a/src/library/jvm/scala/runtime/ObjectRef.java b/src/library/jvm/scala/runtime/ObjectRef.java deleted file mode 100644 index 1154c1dd26..0000000000 --- a/src/library/jvm/scala/runtime/ObjectRef.java +++ /dev/null @@ -1,21 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2008, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.runtime; - - -public class ObjectRef implements java.io.Serializable { - private static final long serialVersionUID = -9055728157600312291L; - - public Object elem; - public ObjectRef(Object elem) { this.elem = elem; } - public String toString() { return "" + elem; } -} diff --git a/src/library/jvm/scala/runtime/RichChar.scala b/src/library/jvm/scala/runtime/RichChar.scala deleted file mode 100644 index d06aa62a57..0000000000 --- a/src/library/jvm/scala/runtime/RichChar.scala +++ /dev/null @@ -1,71 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.runtime - - -import java.lang.Character -import Predef.NoSuchElementException - -/**

- * For example, in the following code - *

- *
- *    object test extends Application {
- *      Console.println('\40'.isWhitespace)
- *      Console.println('\011'.isWhitespace)
- *      Console.println('1'.asDigit == 1)
- *      Console.println('A'.asDigit == 10)
- *    }
- *

- * the implicit conversions are performed using the predefined view - * Predef.charWrapper. - *

- */ -final class RichChar(x: Char) extends Proxy with Ordered[Char] { - - // Proxy.self - def self: Any = x - - // Ordered[Char].compare - def compare (y: Char): Int = if (x < y) -1 else if (x > y) 1 else 0 - - def asDigit: Int = Character.digit(x, Character.MAX_RADIX) - - def isControl: Boolean = Character.isISOControl(x) - def isDigit: Boolean = Character.isDigit(x) - def isLetter: Boolean = Character.isLetter(x) - def isLetterOrDigit: Boolean = Character.isLetterOrDigit(x) - def isLowerCase: Boolean = Character.isLowerCase(x) - def isUpperCase: Boolean = Character.isUpperCase(x) - def isWhitespace: Boolean = Character.isWhitespace(x) - - def toLowerCase: Char = Character.toLowerCase(x) - def toUpperCase: Char = Character.toUpperCase(x) - - /** Create an Iterator[Char] over the characters from 'x' to 'y' - 1 - */ - def until(limit: Char): Iterator[Char] = new Iterator[Char] { - private var ch = x - def hasNext: Boolean = ch < limit - def next: Char = - if (hasNext) { val j = ch; ch = (ch + 1).toChar; j } - else throw new NoSuchElementException("next on empty iterator") - } - - //def until(y: Char): Iterator[Char] = to(y) - - /** Create an Iterator[Char] over the characters from 'x' to 'y' - */ - def to(y: Char): Iterator[Char] = until((y + 1).toChar) - -} diff --git a/src/library/jvm/scala/runtime/RichDouble.scala b/src/library/jvm/scala/runtime/RichDouble.scala deleted file mode 100644 index 64d9046980..0000000000 --- a/src/library/jvm/scala/runtime/RichDouble.scala +++ /dev/null @@ -1,54 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.runtime - - -final class RichDouble(x: Double) extends Proxy with Ordered[Double] { - - // Proxy.self - def self: Any = x - - // Ordered[Double].compare - //def compare(y: Double): Int = if (x < y) -1 else if (x > y) 1 else 0 - def compare(y: Double): Int = java.lang.Double.compare(x, y) - - def min(y: Double): Double = Math.min(x, y) - def max(y: Double): Double = Math.max(x, y) - def abs: Double = Math.abs(x) - - def round: Long = Math.round(x) - def ceil: Double = Math.ceil(x) - def floor: Double = Math.floor(x) - - /** Converts an angle measured in degrees to an approximately equivalent - * angle measured in radians. - * - * @param x an angle, in degrees - * @return the measurement of the angle x in radians. - */ - def toRadians: Double = Math.toRadians(x) - - /** Converts an angle measured in radians to an approximately equivalent - * angle measured in degrees. - * - * @param x angle, in radians - * @return the measurement of the angle x in degrees. - */ - def toDegrees: Double = Math.toDegrees(x) - - // isNaN is provided by the implicit conversion to java.lang.Double - // def isNaN: Boolean = java.lang.Double.isNaN(x) - def isInfinity: Boolean = java.lang.Double.isInfinite(x) - def isPosInfinity: Boolean = isInfinity && x > 0.0 - def isNegInfinity: Boolean = isInfinity && x < 0.0 - -} diff --git a/src/library/jvm/scala/runtime/RichFloat.scala b/src/library/jvm/scala/runtime/RichFloat.scala deleted file mode 100644 index 482ec3fbc0..0000000000 --- a/src/library/jvm/scala/runtime/RichFloat.scala +++ /dev/null @@ -1,56 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.runtime - - -import Predef._ - -final class RichFloat(x: Float) extends Proxy with Ordered[Float] { - - // Proxy.self - def self: Any = x - - // Ordered[Float].compare - //def compare(y: Float): Int = if (x < y) -1 else if (x > y) 1 else 0 - def compare(y: Float): Int = java.lang.Float.compare(x, y) - - def min(y: Float) = Math.min(x, y) - def max(y: Float) = Math.max(x, y) - def abs: Float = Math.abs(x) - - def round: Int = Math.round(x) - def ceil: Float = Math.ceil(x).toFloat - def floor: Float = Math.floor(x).toFloat - - /** Converts an angle measured in degrees to an approximately equivalent - * angle measured in radians. - * - * @param x an angle, in degrees - * @return the measurement of the angle x in radians. - */ - def toRadians: Float = Math.toRadians(x).toFloat - - /** Converts an angle measured in radians to an approximately equivalent - * angle measured in degrees. - * - * @param x angle, in radians - * @return the measurement of the angle x in degrees. - */ - def toDegrees: Float = Math.toDegrees(x).toFloat - - // isNaN is provided by the implicit conversion to java.lang.Float - // def isNaN: Boolean = java.lang.Float.isNaN(x) - def isInfinity: Boolean = java.lang.Float.isInfinite(x) - def isPosInfinity: Boolean = isInfinity && x > 0.0f - def isNegInfinity: Boolean = isInfinity && x < 0.0f - -} diff --git a/src/library/jvm/scala/runtime/RichInt.scala b/src/library/jvm/scala/runtime/RichInt.scala deleted file mode 100644 index 73b13afa28..0000000000 --- a/src/library/jvm/scala/runtime/RichInt.scala +++ /dev/null @@ -1,39 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2008, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.runtime - - -final class RichInt(start: Int) extends Proxy with Ordered[Int] { - - // Proxy - def self: Any = start - - // Ordered[Int] - def compare(that: Int): Int = if (start < that) -1 else if (start > that) 1 else 0 - - /** See Iterator.range. */ - def until(end: Int): Range = new Range(start, end, 1) - - /** See Iterator.range. */ - def until(end: Int, step: Int): Range = new Range(start, end, step) - - /** like until, but includes the last index */ - def to(end: Int) = new Range.Inclusive(start, end, 1) - - def min(that: Int): Int = if (start < that) start else that - def max(that: Int): Int = if (start > that) start else that - def abs: Int = if (start < 0) -start else start - - def toBinaryString: String = java.lang.Integer.toBinaryString(start) - def toHexString: String = java.lang.Integer.toHexString(start) - def toOctalString: String = java.lang.Integer.toOctalString(start) -} diff --git a/src/library/jvm/scala/runtime/RichLong.scala b/src/library/jvm/scala/runtime/RichLong.scala deleted file mode 100644 index 7e835f10c3..0000000000 --- a/src/library/jvm/scala/runtime/RichLong.scala +++ /dev/null @@ -1,30 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2008, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.runtime - - -final class RichLong(x: Long) extends Proxy with Ordered[Long] { - - // Proxy.self - def self: Any = x - - // Ordered[Long].compare - def compare(y: Long): Int = if (x < y) -1 else if (x > y) 1 else 0 - - def min(y: Long): Long = if (x < y) x else y - def max(y: Long): Long = if (x > y) x else y - def abs: Long = if (x < 0) -x else x - - def toBinaryString: String = java.lang.Long.toBinaryString(x) - def toHexString: String = java.lang.Long.toHexString(x) - def toOctalString: String = java.lang.Long.toOctalString(x) -} diff --git a/src/library/jvm/scala/runtime/RichString.scala b/src/library/jvm/scala/runtime/RichString.scala deleted file mode 100644 index 192cf62ebb..0000000000 --- a/src/library/jvm/scala/runtime/RichString.scala +++ /dev/null @@ -1,245 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2008, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.runtime - -import Predef._ -import scala.util.matching.Regex - -final class RichString(val self: String) extends Proxy with CharSequence with RandomAccessSeq[Char] with Ordered[String] { - import RichString._ - override def apply(n: Int) = self charAt n - override def length = self.length - override def toString = self - override def mkString = self - - override def slice(from: Int, until: Int): RichString = { - val len = self.length - new RichString( - if (from >= until || from >= len) - "" - else { - val from0 = if (from < 0) 0 else from - val until0 = if (until > len) len else until - self.substring(from0, until0) - } - ) - } - - //override def ++ [B >: A](that: Iterable[B]): Seq[B] = { - override def ++[B >: Char](that: Iterable[B]): RandomAccessSeq[B] = that match { - case that: RichString => new RichString(self + that.self) - case that => super.++(that) - } - - override def take(until: Int): RichString = slice(0, until) - - override def drop(from: Int): RichString = slice(from, self.length) - - override def startsWith[B](that: Seq[B]) = that match { - case that: RichString => self startsWith that.self - case that => super.startsWith(that) - } - - override def endsWith[B](that: Seq[B]) = that match { - case that: RichString => self endsWith that.self - case that => super.endsWith(that) - } - - override def indexOf[B](that: Seq[B]) = that match { - case that: RichString => self indexOf that.self - case that => super.indexOf(that) - } - - override def containsSlice[B](that: Seq[B]) = that match { - case that: RichString => self contains that.self - case that => super.containsSlice(that) - } - - override def reverse: RichString = { - val buf = new StringBuilder - var i = self.length - 1 - while (i >= 0) { - buf append (self charAt i) - i -= 1 - } - new RichString(buf.toString) - } - - def charAt(index: Int) = self.charAt(index) - - def subSequence(start: Int, end: Int): CharSequence = - new RichString(self.substring(start, end)) - - /** return n times the current string - */ - def * (n: Int): String = { - val buf = new StringBuilder - for (i <- 0 until n) buf append self - buf.toString - } - - override def compare(other: String) = self compareTo other - - private def isLineBreak(c: Char) = c == LF || c == FF - - /**

- * Strip trailing line end character from this string if it has one. - * A line end character is one of - *

- * - *

- * If a line feed character LF is preceded by a carriage return CR - * (0x0D hex), the CR character is also stripped (Windows convention). - *

- */ - def stripLineEnd: String = { - val len = self.length - if (len == 0) self - else { - val last = apply(len - 1) - if (isLineBreak(last)) - self.substring(0, if (last == LF && len >= 2 && apply(len - 2) == CR) len - 2 else len - 1) - else - self - } - } - - /**

- * Return all lines in this string in an iterator, including trailing - * line end characters. - *

- *

- * The number of strings returned is one greater than the number of line - * end characters in this string. For an empty string, a single empty - * line is returned. A line end character is one of - *

- * - */ - def linesWithSeparators = new Iterator[String] { - val len = self.length - var index = 0 - def hasNext: Boolean = index < len - def next(): String = { - if (index >= len) throw new NoSuchElementException("next on empty iterator") - val start = index - while (index < len && !isLineBreak(apply(index))) index += 1 - index += 1 - self.substring(start, index min len) - } - } - - /** Return all lines in this string in an iterator, excluding trailing line - * end characters, i.e. apply .stripLineEnd to all lines - * returned by linesWithSeparators. - */ - def lines: Iterator[String] = - linesWithSeparators map (line => new RichString(line).stripLineEnd) - - /** Returns this string with first character converted to upper case */ - def capitalize: String = - if (self == null) null - else if (self.length == 0) "" - else { - val chars = self.toCharArray - chars(0) = chars(0).toUpperCase - new String(chars) - } - - /**

- * For every line in this string: - *

- *
- * Strip a leading prefix consisting of blanks or control characters - * followed by marginChar from the line. - *
- */ - def stripMargin(marginChar: Char): String = { - val buf = new StringBuilder - for (line <- linesWithSeparators) { - val len = line.length - var index = 0 - while (index < len && line.charAt(index) <= ' ') index += 1 - buf append - (if (index < len && line.charAt(index) == marginChar) line.substring(index + 1) else line) - } - buf.toString - } - - /**

- * For every line in this string: - *

- *
- * Strip a leading prefix consisting of blanks or control characters - * followed by | from the line. - *
- */ - def stripMargin: String = stripMargin('|') - - // NB. "\\Q" + '\\' + "\\E" works on Java 1.5 and newer, but not on Java 1.4 - private def escape(ch: Char): String = ch match { - case '\\' => "\\\\" - case _ => "\\Q"+ch+"\\E" - } - - @throws(classOf[java.util.regex.PatternSyntaxException]) - def split(separator: Char): Array[String] = self.split(escape(separator)) - - @throws(classOf[java.util.regex.PatternSyntaxException]) - def split(separators: Array[Char]): Array[String] = { - val re = separators.foldLeft("[")(_+escape(_)) + "]" - self.split(re) - } - - /** You can follow a string with `.r', turning - * it into a Regex. E.g. - * - * """A\w*""".r is the regular expression for identifiers starting with `A'. - */ - def r: Regex = new Regex(self) - - def toBoolean: Boolean = parseBoolean(self) - def toByte: Byte = java.lang.Byte.parseByte(self) - def toShort: Short = java.lang.Short.parseShort(self) - def toInt: Int = java.lang.Integer.parseInt(self) - def toLong: Long = java.lang.Long.parseLong(self) - def toFloat: Float = java.lang.Float.parseFloat(self) - def toDouble: Double = java.lang.Double.parseDouble(self) - - override def toArray: Array[Char] = { - val result = new Array[Char](length) - self.getChars(0, length, result, 0) - result - } -} - -object RichString { - // just statics for rich string. - private final val LF: Char = 0x0A - private final val FF: Char = 0x0C - private final val CR: Char = 0x0D - private final val SU: Char = 0x1A - - private def parseBoolean(s: String): Boolean = - if (s != null) s.toLowerCase match { - case "true" => true - case "false" => false - case _ => throw new NumberFormatException("For input string: \""+s+"\"") - } - else - throw new NumberFormatException("For input string: \"null\"") -} diff --git a/src/library/jvm/scala/runtime/ShortRef.java b/src/library/jvm/scala/runtime/ShortRef.java deleted file mode 100644 index b471056260..0000000000 --- a/src/library/jvm/scala/runtime/ShortRef.java +++ /dev/null @@ -1,20 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2008, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.runtime; - - -public class ShortRef implements java.io.Serializable { - private static final long serialVersionUID = 4218441291229072313L; - - public short elem; - public ShortRef(short elem) { this.elem = elem; } -} diff --git a/src/library/jvm/scala/runtime/StringAdd.scala b/src/library/jvm/scala/runtime/StringAdd.scala deleted file mode 100644 index 272e2cbb08..0000000000 --- a/src/library/jvm/scala/runtime/StringAdd.scala +++ /dev/null @@ -1,41 +0,0 @@ -/* *\ -** ________ ___ __ ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ |_| ** -** ** -\* */ - -// $Id$ - - -package scala.runtime - - -import Predef._ - -object StringAdd { - // Needed for the format hack. Can be removed once we drop 1.4 - lazy val formatMethod: java.lang.reflect.Method = { - val paramTypes = Array[Class[T] forSome { type T }](classOf[String], classOf[Array[Object]]) - classOf[String].getDeclaredMethod("format", paramTypes) - } -} -final class StringAdd(self: Any) { - - def +(other: String) = self.toString + other - - /** Returns string formatted according to given format string. - * Format strings are as for String.format - * (@see java.lang.String.format). - * Only works on Java 1.5 or higher! - */ - def formatted(format: String): String = { - // This should be: - // String.format(format, Array(self.asInstanceOf[Object])) - // However, the line above does not compile on Java 1.4 because String.format exists only in 1.5 - // Therefore, we do the following hack: - val args = Array(self.asInstanceOf[Object]) - StringAdd.formatMethod.invoke(null, Array[Object](format, args)).asInstanceOf[String] - } -} diff --git a/src/library/jvm/scala/util/DynamicVariable.scala b/src/library/jvm/scala/util/DynamicVariable.scala deleted file mode 100644 index 552e946250..0000000000 --- a/src/library/jvm/scala/util/DynamicVariable.scala +++ /dev/null @@ -1,84 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2008, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.util - - -import Predef._ -import java.lang.InheritableThreadLocal - -/**

- * DynamicVariables provide a binding mechanism where the current - * value is found through dynamic scope, but where - * access to the variable itself is resolved through static - * scope. - *

- *

- * The current value can be retrieved with the - * value method. New values should be - * pushed using the withValue method. - * Values pushed via withValue only - * stay valid while the withValue's - * second argument, a parameterless closure, - * executes. When the second argument finishes, - * the variable reverts to the previous value. - *

- *

- * Usage of withValue looks like this: - *

- *
- *  someDynamicVariable.withValue(newValue) {
- *    // ... code called in here that calls value ...
- *    // ... will be given back the newValue ...
- *  }
- *  
- *

- * Each thread gets its own stack of bindings. When a - * new thread is created, the fluid gets a copy of - * the stack of bindings from the parent thread, and - * from then on the bindings for the new thread - * are independent of those for the original thread. - *

- * - * @author Lex Spoon - * @version 1.1, 2007-5-21 - */ -class DynamicVariable[T](init: T) { - private val tl = new InheritableThreadLocal[T] { - override def initialValue = init.asInstanceOf[T with AnyRef] - } - - /** Retrieve the current value */ - def value: T = tl.get.asInstanceOf[T] - - - /** Set the value of the variable while executing the specified - * thunk. - * - * @param newval The value to which to set the fluid - * @param thunk The code to evaluate under the new setting - */ - def withValue[S](newval: T)(thunk: =>S): S = { - val oldval = value - tl.set(newval) - - try { thunk } finally { - tl.set(oldval) - } - } - - /** Change the currently bound value, discarding the old value. - * Usually withValue() gives better semantics. - */ - def value_=(newval: T) = { tl.set(newval) } - - override def toString: String = "DynamicVariable(" + value +")" -} diff --git a/src/library/jvm/scala/util/Properties.scala b/src/library/jvm/scala/util/Properties.scala deleted file mode 100644 index 2fa885dc3a..0000000000 --- a/src/library/jvm/scala/util/Properties.scala +++ /dev/null @@ -1,57 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2008, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.util - -/** A utility to load the library properties from a Java properties file - * included in the jar. - * - * @author Stephane Micheloud - */ -object Properties { - - /** The name of the properties file */ - private val propFilename = "/library.properties" - - /** The loaded properties */ - private val props = { - val props = new java.util.Properties - val stream = classOf[Application].getResourceAsStream(propFilename) - if (stream != null) - props.load(stream) - props - } - - /** The version number of the jar this was loaded from, or - * "(unknown)" if it cannot be determined. - */ - val versionString: String = { - val defaultString = "(unknown)" - "version " + props.getProperty("version.number") - } - - val copyrightString: String = { - val defaultString = "(c) 2002-2008 LAMP/EPFL" - props.getProperty("copyright.string", defaultString) - } - - val encodingString: String = { - val defaultString = "UTF8" //"ISO-8859-1" - props.getProperty("file.encoding", defaultString) - } - - private val writer = new java.io.PrintWriter(Console.err, true) - - val versionMsg = "Scala library " + versionString + " -- " + copyrightString - - def main(args: Array[String]) { - writer.println(versionMsg) - } -} diff --git a/src/library/jvm/scala/util/matching/Regex.scala b/src/library/jvm/scala/util/matching/Regex.scala deleted file mode 100644 index 32fc300bf1..0000000000 --- a/src/library/jvm/scala/util/matching/Regex.scala +++ /dev/null @@ -1,274 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2007-2008, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.util.matching - -import java.util.regex.{Pattern, Matcher} - -/** This class provides methods for creating and using regular expressions. - * It is based on the regular expressions of the JDK since 1.4. - * - * @author Thibaud Hottelier - * @author Philipp Haller - * @author Martin Odersky - * @version 1.1, 29/01/2008 - * - * @param regex A string representing a regular expression - * @param groupNames A mapping from names to indices in capture groups - */ -class Regex(regex: String, groupNames: String*) { - - import Regex._ - - /** The compiled pattern */ - val pattern = Pattern.compile(regex) - - /** Tries to match target (whole match) and returns - * the matches. - * - * @param target The string to match - * @return The matches - */ - def unapplySeq(target: Any): Option[List[String]] = target match { - case s: java.lang.CharSequence => - val m = pattern.matcher(s) - if (m.matches) Some((1 to m.groupCount).toList map m.group) - else None - case Match(s) => - unapplySeq(s) - case _ => - None - } - - /** Return all matches of this regexp in given character sequence as an iterator - */ - def findAllIn(source: CharSequence) = new Regex.MatchIterator(source, this, groupNames) - - /** Return optionally first matching string of this regexp in given character sequence, - * None if it does not exist. - */ - def findFirstIn(source: CharSequence): Option[String] = { - val m = pattern.matcher(source) - if (m.find) Some(m.group) else None - } - - /** Return optionally first match of this regexp in given character sequence, - * None if it does not exist. - */ - def findFirstMatchIn(source: CharSequence): Option[Match] = { - val m = pattern.matcher(source) - if (m.find) Some(new Match(source, m, groupNames)) else None - } - - /** Return optionally match of this regexp at the beginning of the - * given character sequence, or None if regexp matches no prefix - * of the character sequence. - */ - def findPrefixOf(source: CharSequence): Option[String] = { - val m = pattern.matcher(source) - if (m.lookingAt) Some(m.group) else None - } - - /** Return optionally match of this regexp at the beginning of the - * given character sequence, or None if regexp matches no prefix - * of the character sequence. - */ - def findPrefixMatchOf(source: CharSequence): Option[Match] = { - val m = pattern.matcher(source) - if (m.lookingAt) Some(new Match(source, m, groupNames)) else None - } - - /** Replaces all matches by a string. - * - * @param target The string to match - * @param replacement The string that will replace each match - * @return The resulting string - */ - def replaceAllIn(target: CharSequence, replacement: String): String = { - val m = pattern.matcher(target) - m.replaceAll(replacement) - } - - /** Replaces the first match by a string. - * - * @param target The string to match - * @param replacement The string that will replace the match - * @return The resulting string - */ - def replaceFirstIn(target: CharSequence, replacement: String): String = { - val m = pattern.matcher(target) - m.replaceFirst(replacement) - } - - /** The string defining the regular expression */ - override def toString = regex -} - -/** This object defines inner classes that describe - * regex matches. The class hirrachy is as follows. - * - * MatchData - * | \ - * MatchIterator Match - */ -object Regex { - - /** This class provides methods to access - * the details of a match. - */ - trait MatchData { - - /** The source from where the match originated */ - val source: CharSequence - - /** The names of the groups, or some empty sequence if one defined */ - val groupNames: Seq[String] - - /** The index of the first matched character */ - def start: Int - - /** The index of the first matched character in group i */ - def start(i: Int): Int - - /** The index of the last matched character */ - def end: Int - - /** The number of subgroups */ - def groupCount: Int - - /** The index following the last matched character in group i */ - def end(i: Int): Int - - /** The matched string */ - def matched: String = source.subSequence(start, end).toString - - /** The matched string in group i */ - def group(i: Int): String = source.subSequence(start(i), end(i)).toString - - /** All matched subgroups, i.e. not including group(0) */ - def subgroups: List[String] = (1 to groupCount).toList map group - - /** The char sequence before first character of match */ - def before: CharSequence = source.subSequence(0, start) - - /** The char sequence before first character of match in group i */ - def before(i: Int): CharSequence = source.subSequence(0, start(i)) - - /** Returns char sequence after last character of match */ - def after: CharSequence = source.subSequence(end) - - /** The char sequence after last character of match in group i */ - def after(i: Int): CharSequence = source.subSequence(end(i)) - - private lazy val nameToIndex: Map[String, Int] = Map() ++ ("" :: groupNames.toList).zipWithIndex - - /** Returns the group with given name - * - * @param id The group name - * @return The requested group - * @throws NoSuchElementException if the requested - * group name is not defined - */ - def group(id: String): String = nameToIndex.get(id) match { - case None => throw new NoSuchElementException("group name "+id+" not defined") - case Some(index) => group(index) - } - - /** The matched string; equivalent to matched.toString */ - override def toString = matched - - } - - /** A case class for a succesful match. - */ - class Match(val source: CharSequence, - matcher: Matcher, - val groupNames: Seq[String]) extends MatchData { - - /** The index of the first matched character */ - val start = matcher.start - - /** The index following the last matched character */ - val end = matcher.end - - /** The number of subgroups */ - def groupCount = matcher.groupCount - - private lazy val starts: Array[Int] = - ((1 to groupCount) map matcher.start).toArray - private lazy val ends: Array[Int] = - ((1 to groupCount) map matcher.end).toArray - - /** The index of the first matched character in group i */ - def start(i: Int) = starts(i) - - /** The index following the last matched character in group i */ - def end(i: Int) = ends(i) - - /** The match itself with matcher-dependent lazy vals forced, - * so that match is valid even once matcher is advanced - */ - def force: this.type = { starts; ends; this } - } - - /** An extractor object for Matches, yielding the matched string */ - object Match { - def unapply(m: Match): Some[String] = Some(m.matched) - } - - /** A class to step through a sequence of regex matches - */ - class MatchIterator(val source: CharSequence, val regex: Regex, val groupNames: Seq[String]) - extends Iterator[String] with MatchData { self => - - private val matcher = regex.pattern.matcher(source) - private var nextSeen = false - - /** Is there another match? */ - def hasNext: Boolean = { - if (!nextSeen) nextSeen = matcher.find() - nextSeen - } - - /** The next matched substring of `source' */ - def next: String = { - if (!hasNext) throw new NoSuchElementException - nextSeen = false - matcher.group - } - - override def toString = super[Iterator].toString - - /** The index of the first matched character */ - def start: Int = matcher.start - - /** The index of the first matched character in group i */ - def start(i: Int): Int = matcher.start(i) - - /** The index of the last matched character */ - def end: Int = matcher.end - - /** The index following the last matched character in group i */ - def end(i: Int): Int = matcher.end(i) - - /** The number of subgroups */ - def groupCount = matcher.groupCount - - /** Convert to an iterator that yields MatchData elements instead of Strings */ - def matchData = new Iterator[Match] { - def hasNext = self.hasNext - def next = { self.next; new Match(source, matcher, groupNames).force } - } - } -} - - - diff --git a/src/library/jvm/scala/util/parsing/CharInputStreamIterator.scala b/src/library/jvm/scala/util/parsing/CharInputStreamIterator.scala deleted file mode 100644 index b58650e025..0000000000 --- a/src/library/jvm/scala/util/parsing/CharInputStreamIterator.scala +++ /dev/null @@ -1,52 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.util.parsing - - -import java.io.InputStream -import java.io.{IOException, EOFException} - -/** This class ... - * - * @author Burak Emir - * @version 1.0 - * - * @deprecated use classes from - * scala.util.parsing.input instead. - */ -@deprecated -class CharInputStreamIterator(in: InputStream) extends Iterator[Char] { - - private var ch: Int = _ - private var chSet = false - private var error: IOException = null - - private def lookahead() { - try { - ch = in.read(); chSet = ch >= 0 - } catch { - case ex: EOFException => ch = -1 - case ex: IOException => ch = 1; error = ex - } - } - - def hasNext: Boolean = { - if (!chSet) lookahead() - chSet - } - - def next(): Char = { - if (!chSet) lookahead() - chSet = false - ch.asInstanceOf[Char] - } -} diff --git a/src/library/jvm/scala/util/parsing/combinator/RegexParsers.scala b/src/library/jvm/scala/util/parsing/combinator/RegexParsers.scala deleted file mode 100644 index 37b5f1d10c..0000000000 --- a/src/library/jvm/scala/util/parsing/combinator/RegexParsers.scala +++ /dev/null @@ -1,84 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.util.parsing.combinator - -import java.util.regex.Pattern -import scala.util.matching.Regex -import scala.util.parsing.input._ - -trait RegexParsers extends Parsers { - - type Elem = Char - - protected val whiteSpace = """\s+""".r - - def skipWhitespace = whiteSpace.toString.length > 0 - - protected def handleWhiteSpace(source: CharSequence, offset: Int): Int = - if (skipWhitespace) - (whiteSpace findPrefixMatchOf (source subSequence offset)) match { - case Some(matched) => offset + matched.end - case None => offset - } - else - offset - - /** A parser that matches a literal string */ - implicit def literal(s: String): Parser[String] = new Parser[String] { - def apply(in: Input) = { - val source = in.source - val offset = in.offset - val start = handleWhiteSpace(source, offset) - var i = 0 - var j = start - while (i < s.length && source.isDefinedAt(j) && s.charAt(i) == source.charAt(j)) { - i += 1 - j += 1 - } - if (i == s.length) - Success(source.subSequence(start, j).toString, in.drop(j - offset)) - else - Failure("`"+s+"' expected but `"+in.first+"' found", in.drop(start - offset)) - } - } - - /** A parser that matches a regex string */ - implicit def regex(r: Regex): Parser[String] = new Parser[String] { - def apply(in: Input) = { - val source = in.source - val offset = in.offset - val start = handleWhiteSpace(source, offset) - (r findPrefixMatchOf (source subSequence start)) match { - case Some(matched) => - Success(source.subSequence(start, start + matched.end).toString, - in.drop(start + matched.end - offset)) - case None => - Failure("string matching regex `+r+' expected but `"+in.first+"' found", in.drop(start - offset)) - } - } - } - - /** Parse some prefix of character sequence `in' with parser `p' */ - def parse[T](p: Parser[T], in: CharSequence): ParseResult[T] = - p(new CharSequenceReader(in)) - - /** Parse some prefix of reader `in' with parser `p' */ - def parse[T](p: Parser[T], in: Reader[Char]): ParseResult[T] = - p(in) - - /** Parse all of character sequence `in' with parser `p' */ - def parseAll[T](p: Parser[T], in: CharSequence): ParseResult[T] = - parse(phrase(p), in) - - /** Parse all of reader `in' with parser `p' */ - def parseAll[T](p: Parser[T], in: Reader[Char]): ParseResult[T] = - parse(phrase(p), in) -} diff --git a/src/library/jvm/scala/util/parsing/input/StreamReader.scala b/src/library/jvm/scala/util/parsing/input/StreamReader.scala deleted file mode 100644 index f997590f18..0000000000 --- a/src/library/jvm/scala/util/parsing/input/StreamReader.scala +++ /dev/null @@ -1,74 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.util.parsing.input - -import java.io.BufferedReader - -/** An object to create a StreamReader from a java.io.Reader. - * - * @param in the java.io.Reader that provides the underlying - * stream of characters for this Reader. - * - * @author Miles Sabin - */ -object StreamReader { - final val EofCh = '\032' - - def apply(in: java.io.Reader): StreamReader = { - new StreamReader(new LazyCharSequence(in), 0, 1) - } -} - -/** A character array reader reads a stream of characters (keeping track of - * their positions) from an array. - * - * NOTE: - * StreamReaders do not really fulfill the new contract for readers, which - * requires a `source' CharSequence representing the full input. - * Instead source is treated line by line. - * As a consequence, regex matching cannot extend beyond a single lines - * when a StreamReader are used for input. - * - * @param bin the underlying java.io.BufferedReader - * @param sourceLine the line at column `col' in the stream - * @param line the 1-based line number of the character returned by `first' - * @param column the 1-based column number of the character returned by `first' - * - * @author Miles Sabin - */ -sealed class StreamReader(source: CharSequence, offset: Int, lnum: Int) extends CharSequenceReader(source, offset) { - import StreamReader._ - - override def rest: CharSequenceReader = - if (offset == source.length) this - else if (source(offset) == '\n') new StreamReader(source.subSequence(offset + 1), 0, lnum + 1) - else new StreamReader(source, offset + 1, lnum) - - private def nextEol = { - var i = offset - while (i < source.length && source(i) != '\n' && source(i) != EofCh) i += 1 - i - } - - override def drop(n: Int): StreamReader = { - val eolPos = nextEol - if (eolPos < offset + n && eolPos < source.length) - new StreamReader(source.subSequence(eolPos + 1), 0, lnum + 1).drop(offset + n - (eolPos + 1)) - else - new StreamReader(source, offset + n, lnum) - } - - override def pos: Position = new Position { - def line = lnum - def column = offset + 1 - def lineContents = source.subSequence(0, nextEol).toString - } -} diff --git a/src/library/jvm/scala/xml/Parsing.scala b/src/library/jvm/scala/xml/Parsing.scala deleted file mode 100644 index 9f2934a7b5..0000000000 --- a/src/library/jvm/scala/xml/Parsing.scala +++ /dev/null @@ -1,105 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.xml - - -/** The object Parsing ... - * - * @author Burak Emir - * @version 1.0 - * - * @deprecated use either parsing.TokenTests or - * Utilty (helper functions for parsing XML fragments). - */ -object Parsing { - - /**
(#x20 | #x9 | #xD | #xA)
*/ - final def isSpace(ch: Char): Boolean = ch match { - case '\u0009' | '\u000A' | '\u000D' | '\u0020' => true - case _ => false - } - - /**
(#x20 | #x9 | #xD | #xA)+
*/ - final def isSpace(cs: Seq[Char]): Boolean = { - val it = cs.elements - it.hasNext && it.forall { isSpace } - } - - /**
NameChar ::= Letter | Digit | '.' | '-' | '_' | ':'
-   *             | CombiningChar | Extender
- * - * see [4] and Appendix B of XML 1.0 specification - */ - def isNameChar(ch: Char) = isNameStart(ch) || (ch match { - case '.' | '-' | ':' => true - case _ => java.lang.Character.getType(ch).asInstanceOf[Byte] match { - case java.lang.Character.COMBINING_SPACING_MARK => true // Mc - case java.lang.Character.ENCLOSING_MARK => true // Me - case java.lang.Character.NON_SPACING_MARK => true // Mn - case java.lang.Character.MODIFIER_LETTER => true // Lm - case java.lang.Character.DECIMAL_DIGIT_NUMBER => true // Nd - case _ => false - } - }); - - /**
NameStart ::= ( Letter | '_' )
- * where Letter means in one of the Unicode general - * categories { Ll, Lu, Lo, Lt, Nl } - * - * We do not allow a name to start with ':'. - * see [3] and Appendix B of XML 1.0 specification - */ - def isNameStart(ch: Char) = - java.lang.Character.getType(ch).asInstanceOf[Byte] match { - case java.lang.Character.LOWERCASE_LETTER => true - case java.lang.Character.UPPERCASE_LETTER => true - case java.lang.Character.OTHER_LETTER => true - case java.lang.Character.TITLECASE_LETTER => true - case java.lang.Character.LETTER_NUMBER => true - case _ => ch == '_' - } - - /**
Name ::= ( Letter | '_' ) (NameChar)*
- * - * see [5] of XML 1.0 specification - */ - def isName(s: String): Boolean = - if (s.length() > 0) { - val z: Seq[Char] = s - val y = z.elements - if (isNameStart(y.next)) { - while (y.hasNext && isNameChar(y.next)) {} - !y.hasNext - } else false - } else false - - def isPubIDChar(c: Char) = c match { - case '\u0020' | '\u000D' | '\u000A' => true - case _ if - ('0' < c && c < '9')||('a' < c && c < 'z')||('A' < c && c < 'Z') => true - case '-' | '\''| '(' | ')' | '+' | ',' | '.' | '/' | ':' | '=' | - '?' | ';' | '!' | '*' | '#' | '@' | '$' | '_' | '%' => true - case _ => false - } - - def checkSysID(s: String): Boolean = - s.indexOf('"') == -1 || s.indexOf('\'') == -1 - - def checkPubID(s: String): Boolean = - if (s.length() > 0) { - val z:Seq[Char] = s - val y = z.elements - while (y.hasNext && isPubIDChar(y.next)) {} - !y.hasNext - } else true - -} diff --git a/src/library/jvm/scala/xml/PrettyPrinter.scala b/src/library/jvm/scala/xml/PrettyPrinter.scala deleted file mode 100644 index 05c612ce81..0000000000 --- a/src/library/jvm/scala/xml/PrettyPrinter.scala +++ /dev/null @@ -1,308 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.xml - -import scala.collection.Map - -/** Class for pretty printing. After instantiating, you can use the - * toPrettyXML methods to convert XML to a formatted string. The class - * can be reused to pretty print any number of XML nodes. - * - * @author Burak Emir - * @version 1.0 - * - * @param width the width to fit the output into - * @step indentation - */ -class PrettyPrinter( width:Int, step:Int ) { - - class BrokenException() extends java.lang.Exception - - class Item - case object Break extends Item { - override def toString() = "\\" - } - case class Box(col: Int, s: String) extends Item - case class Para(s: String) extends Item - - protected var items: List[Item] = Nil - - protected var cur = 0 - //protected var pmap:Map[String,String] = _ - - protected def reset() = { - cur = 0 - items = Nil - } - - /** Try to cut at whitespace. - * - * @param s ... - * @param ind ... - * @return ... - */ - protected def cut(s: String, ind: Int): List[Item] = { - val tmp = width - cur - if (s.length < tmp) - return List(Box(ind, s)) - val sb = new StringBuilder() - var i = s.indexOf(' ') - if (i > tmp || i == -1) throw new BrokenException() // cannot break - - var last: List[Int] = Nil - while (i != -1 && i < tmp) { - last = i::last - i = s.indexOf(' ', i+1) - } - var res: List[Item] = Nil - while (Nil != last) try { - val b = Box(ind, s.substring(0, last.head)) - cur = ind - res = b :: Break :: cut(s.substring(last.head, s.length), ind) - // backtrack - last = last.tail - } catch { - case _:BrokenException => last = last.tail - } - throw new BrokenException() - } - - /** Try to make indented box, if possible, else para. - * - * @param ind ... - * @param s ... - * @return ... - */ - protected def makeBox(ind: Int, s: String) = { - if (cur < ind) - cur == ind - if (cur + s.length > width) { // fits in this line - items = Box(ind, s) :: items - cur += s.length - } else try { - for (b <- cut(s, ind).elements) // break it up - items = b :: items - } catch { - case _:BrokenException => makePara(ind, s) // give up, para - } - } - - // dont respect indent in para, but afterwards - protected def makePara(ind: Int, s: String) = { - items = Break::Para(s)::Break::items - cur = ind - } - - // respect indent - protected def makeBreak() = { // using wrapping here... - items = Break :: items - cur = 0 - } - - /** - * @param n ... - * @return ... - */ - protected def leafTag(n: Node) = { - val sb = new StringBuilder("<") - n.nameToString(sb) - //Utility.appendPrefixedName( n.prefix, n.label, pmap, sb ); - n.attributes.toString(sb) - //Utility.attr2xml( n.scope, n.attributes, pmap, sb ); - sb.append("/>") - sb.toString() - } - - protected def startTag(n: Node, pscope: NamespaceBinding): (String, Int) = { - val sb = new StringBuilder("<") - n.nameToString(sb) //Utility.appendPrefixedName( n.prefix, n.label, pmap, sb ); - val i = sb.length + 1 - n.attributes.toString(sb) - n.scope.toString(sb, pscope) - sb.append('>') - (sb.toString(), i) - } - - protected def endTag(n: Node) = { - val sb = new StringBuilder("') - sb.toString() - } - - protected def childrenAreLeaves(n: Node): Boolean = { - val it = n.child.elements - while (it.hasNext) - it.next match { - case _:Atom[_] | _:Comment | _:EntityRef | _:ProcInstr => - case _:Node => - return false - } - true - } - - protected def fits(test: String) = - test.length < width - cur - - /** @param tail: what we'd like to sqeeze in */ - protected def traverse(node: Node, pscope: NamespaceBinding, ind: Int): Unit = node match { - - case Text(s) if s.trim() == "" => - ; - case _:Atom[_] | _:Comment | _:EntityRef | _:ProcInstr => - makeBox( ind, node.toString().trim() ) - case g @ Group(xs) => - traverse(xs.elements, pscope, ind) - case _ => - val test = { - val sb = new StringBuilder() - Utility.toXML(node, pscope, sb, false) - if (node.attribute("http://www.w3.org/XML/1998/namespace", "space") == "preserve") - sb.toString() - else - TextBuffer.fromString(sb.toString()).toText(0)._data - } - if (childrenAreLeaves(node) && fits(test)) { - makeBox(ind, test) - } else { - val (stg, len2) = startTag(node, pscope) - val etg = endTag(node) - if (stg.length < width - cur) { // start tag fits - makeBox(ind, stg) - makeBreak() - traverse(node.child.elements, node.scope, ind + step) - makeBox(ind, etg) - } else if (len2 < width - cur) { - // - if (!lastwasbreak) sb.append('\n') // on windows: \r\n ? - lastwasbreak = true - cur = 0 -// while( cur < last ) { -// sb.append(' '); -// cur = cur + 1; -// } - - case Box(i, s) => - lastwasbreak = false - while (cur < i) { - sb.append(' ') - cur += 1 - } - sb.append(s) - case Para( s ) => - lastwasbreak = false - sb.append(s) - } - } - - // public convenience methods - - /** returns a formatted string containing well-formed XML with - * default namespace prefix mapping - * - * @param n the node to be serialized - * @return ... - */ - def format(n: Node): String = format(n, null) //Utility.defaultPrefixes(n)) - - /** Returns a formatted string containing well-formed XML with - * given namespace to prefix mapping. - * - * @param n the node to be serialized - * @param pmap the namespace to prefix mapping - * @return ... - */ - def format(n: Node, pscope: NamespaceBinding): String = { - val sb = new StringBuilder() - format(n, pscope, sb) - sb.toString() - } - - /** Returns a formatted string containing well-formed XML nodes with - * default namespace prefix mapping. - * - * @param nodes ... - * @return ... - */ - def formatNodes(nodes: Seq[Node]): String = - formatNodes(nodes, null) - - /** Returns a formatted string containing well-formed XML. - * - * @param nodes the sequence of nodes to be serialized - * @param pmap the namespace to prefix mapping - */ - def formatNodes(nodes: Seq[Node], pscope: NamespaceBinding): String = { - var sb = new StringBuilder() - formatNodes(nodes, pscope, sb) - sb.toString() - } - - /** Appends a formatted string containing well-formed XML with - * the given namespace to prefix mapping to the given stringbuffer. - * - * @param n the node to be serialized - * @param pmap the namespace to prefix mapping - * @param sb the string buffer to which to append to - */ - def formatNodes(nodes: Seq[Node], pscope: NamespaceBinding, sb: StringBuilder): Unit = - for (n <- nodes.elements) { - sb.append(format(n, pscope)) - } - -} diff --git a/src/library/jvm/scala/xml/Text.scala b/src/library/jvm/scala/xml/Text.scala deleted file mode 100644 index c766e34999..0000000000 --- a/src/library/jvm/scala/xml/Text.scala +++ /dev/null @@ -1,42 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.xml - - -/** The class Text implements an XML node for text (PCDATA). - * It is used in both non-bound and bound XML representations. - * - * @author Burak Emir - * - * @param text the text contained in this node, may not be null. - */ -case class Text(_data: String) extends Atom[String](_data) { - - if (null == data) - throw new java.lang.NullPointerException("tried to construct Text with null") - - final override def equals(x: Any) = x match { - case s:String => s.equals(data) - case s:Text => data == s.data - case _ => false - } - - /** Returns text, with some characters escaped according to the XML - * specification. - * - * @param sb ... - * @return ... - */ - override def toString(sb: StringBuilder) = - Utility.escape(data, sb) - -} diff --git a/src/library/jvm/scala/xml/Unparsed.scala b/src/library/jvm/scala/xml/Unparsed.scala deleted file mode 100644 index 6bda932b89..0000000000 --- a/src/library/jvm/scala/xml/Unparsed.scala +++ /dev/null @@ -1,35 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.xml - -/** An XML node for unparsed content. It will be output verbatim, all bets - * are off regarding wellformedness etc. - * - * @author Burak Emir - * @param _data content in this node, may not be null. - */ -case class Unparsed(_data: String) extends Atom[String](_data) { - - if (null == data) - throw new java.lang.NullPointerException("tried to construct Unparsed with null") - - final override def equals(x: Any) = x match { - case s:String => s.equals(data) - case s:Text => data == s.data - case s:Unparsed => data == s.data - case _ => false - } - - /** returns text, with some characters escaped according to XML spec */ - override def toString(sb: StringBuilder) = sb append data - -} diff --git a/src/library/jvm/scala/xml/XML.scala b/src/library/jvm/scala/xml/XML.scala deleted file mode 100644 index 675d4dcbb7..0000000000 --- a/src/library/jvm/scala/xml/XML.scala +++ /dev/null @@ -1,158 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.xml - - -import Predef._ -import scala.xml.parsing.NoBindingFactoryAdapter -import org.xml.sax.InputSource -import java.io.{File, FileDescriptor, FileInputStream, FileOutputStream} -import java.io.{InputStream, Reader, StringReader, Writer} - -/** The object XML provides constants, and functions to load - * and save XML elements. Use this when data binding is not desired, i.e. - * when XML is handled using Symbol nodes. - * - * @author Burak Emir - * @version 1.0, 25/04/2005 - */ -object XML { - - val xml = "xml" - val xmlns = "xmlns" - val namespace = "http://www.w3.org/XML/1998/namespace" - val preserve = "preserve" - val space = "space" - val lang = "lang" - val encoding = "ISO-8859-1" - - // functions for generic xml loading, saving - - /** loads XML from given file, using XML parser in JDK. */ - final def loadFile(file: File): Elem = - new NoBindingFactoryAdapter().loadXML(new InputSource( - new FileInputStream(file) - )) - - /** loads XML from given file descriptor, using XML parser in JDK. - * - * @param fileDesc ... - * @return ... - */ - final def loadFile(fileDesc: FileDescriptor): Elem = - new NoBindingFactoryAdapter().loadXML(new InputSource( - new FileInputStream(fileDesc) - )) - - /** loads XML from given file, using XML parser in JDK. */ - final def loadFile(fileName: String): Elem = - new NoBindingFactoryAdapter().loadXML(new InputSource( - new FileInputStream(fileName) - )); - - /** loads XML from given InputStream, using XML parser in JDK. */ - final def load( is:InputStream ): Elem = - new NoBindingFactoryAdapter().loadXML(new InputSource(is)) - - /** loads XML from given Reader, using XML parser in JDK. */ - final def load(reader: Reader): Elem = - new NoBindingFactoryAdapter().loadXML(new InputSource(reader)) - - /** loads XML from given sysID, using XML parser in JDK. */ - final def load(sysID: String): Elem = - new NoBindingFactoryAdapter().loadXML(new InputSource(sysID)) - - /** loads XML from a given input source, using XML parser in JDK. - * - * @param source ... - * @return ... - */ - final def load(source: InputSource): Elem = - new NoBindingFactoryAdapter().loadXML(source) - - /** loads XML from a string, using XML parser in JDK. */ - final def loadString(string: String): Elem = - load(new StringReader(string)) - - /** Saves XML to filename with encoding ISO-8859-1 without xml-decl without - * doctype. - * - * @param filename ... - * @param node ... - */ - final def save(filename: String, node: Node): Unit = - save(filename, node, encoding) - - /** saves XML to filename with given encoding, without xml-decl without - * doctype. - * - * @param filename ... - * @param node ... - * @param enc ... - */ - final def save(filename: String, node: Node, enc: String): Unit = - saveFull(filename, node, enc, false, null); - - /** saves a node to a file with given filename using encoding iso-8859-1 - * optionally with xmldecl and doctype declaration. - * - * @param filename the filename - * @param node the xml node we want to write - * @param xmlDecl if true, write xml declaration - * @param doctype if not null, write doctype declaration - */ - final def saveFull(filename: String, node: Node, xmlDecl: Boolean, doctype: dtd.DocType): Unit = - saveFull(filename, node, encoding, xmlDecl, doctype) - - /** Saves a node to a file with given filename using given encoding - * optionally with xmldecl and doctype declaration. - * - * @param filename the filename - * @param node the xml node we want to write - * @param enc encoding to use - * @param xmlDecl if true, write xml declaration - * @param doctype if not null, write doctype declaration - */ - - final def saveFull(filename: String, node: Node, enc: String, xmlDecl: Boolean, doctype: dtd.DocType) { - var fos: FileOutputStream = null - var w: Writer = null - try { - // using NIO classes of JDK 1.4 - import java.io.{FileOutputStream, Writer} - import java.nio.channels.{Channels, FileChannel} - - fos = new FileOutputStream(filename) - w = Channels.newWriter(fos.getChannel(), enc) - write(w, node, enc, xmlDecl, doctype) - } finally { - w.close() - fos.close() - } - } - - /** Writes the given node using writer, optionally with xml decl and doctype. - * It's the caller's responsibility to close the writer. - * - * @param w the writer - * @param node the xml node we want to write - * @param enc the string to be used in xmlDecl - * @param xmlDecl if true, write xml declaration - * @param doctype if not null, write doctype declaration - */ - final def write(w: java.io.Writer, node: Node, enc: String, xmlDecl: Boolean, doctype: dtd.DocType) { - /* TODO: optimize by giving writer parameter to toXML*/ - if (xmlDecl) w.write("\n") - if (doctype ne null) w.write( doctype.toString() + "\n") - w.write(Utility.toXML(node)) - } -} diff --git a/src/library/jvm/scala/xml/include/XIncludeException.scala b/src/library/jvm/scala/xml/include/XIncludeException.scala deleted file mode 100644 index 5563d68c38..0000000000 --- a/src/library/jvm/scala/xml/include/XIncludeException.scala +++ /dev/null @@ -1,64 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.xml.include - -/** - *

- * XIncludeException is the generic superclass - * for all checked exceptions that may be thrown as a result - * of a violation of XInclude's rules. - *

- *

- * Constructs an XIncludeException with the specified detail - * message. The error message string message can later be - * retrieved by the {@link java.lang.Throwable#getMessage} - * method of class java.lang.Throwable. - *

- * - * @param message the detail message. - */ -class XIncludeException(message: String) extends Exception(message) { - - /** - * uses null as its error detail message. - */ - def this() = this(null) - - private var rootCause: Throwable = null - - /** - * When an IOException, MalformedURLException - * or other generic exception is thrown while processing an XML document - * for XIncludes, it is customarily replaced - * by some form of XIncludeException. - * This method allows you to store the original exception. - * - * @param nestedException the underlying exception which - caused the XIncludeException to be thrown - */ - def setRootCause(nestedException: Throwable ) { - this.rootCause = nestedException - } - - /** - * When an IOException, MalformedURLException - * or other generic exception is thrown while processing an XML document - * for XIncludes, it is customarily replaced - * by some form of XIncludeException. - * This method allows you to retrieve the original exception. - * It returns null if no such exception caused this XIncludeException. - * - * @return Throwable the underlying exception which caused the - * XIncludeException to be thrown - */ - def getRootCause(): Throwable = this.rootCause - -} diff --git a/src/library/jvm/scala/xml/include/parsing/ConstructingParser.scala b/src/library/jvm/scala/xml/include/parsing/ConstructingParser.scala deleted file mode 100644 index b7c88c79ec..0000000000 --- a/src/library/jvm/scala/xml/include/parsing/ConstructingParser.scala +++ /dev/null @@ -1,67 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.xml.parsing - -import java.io.File - -import scala.io.Source - -object ConstructingParser { - - def fromFile(inp: File, preserveWS: Boolean) = { - val p = new ConstructingParser(Source.fromFile(inp), preserveWS) - p.nextch - p - } - - def fromSource(inp: Source, preserveWS: Boolean) = { - val p = new ConstructingParser(inp, preserveWS) - p.nextch - p - } -} - -/** An xml parser. parses XML and invokes callback methods of a MarkupHandler. - * Don't forget to call next.ch on a freshly instantiated parser in order to - * initialize it. If you get the parser from the object method, initialization - * is already done for you. - * - *
-object parseFromURL {
-  def main(args:Array[String]): Unit = {
-    val url = args(0);
-    val src = scala.io.Source.fromURL(url);
-    val cpa = scala.xml.parsing.ConstructingParser.fromSource(src, false); // fromSource initializes automatically
-    val doc = cpa.document();
-
-    // let's see what it is
-    val ppr = new scala.xml.PrettyPrinter(80,5);
-    val ele = doc.docElem;
-    Console.println("finished parsing");
-    val out = ppr.format(ele);
-    Console.println(out);
-  }
-}
-
- */ -class ConstructingParser(inp: Source, presWS:Boolean) -extends ConstructingHandler -with ExternalSources -with MarkupParser { - - // default impl. of Logged - override def log(msg: String): Unit = {} - - val preserveWS = presWS - val input = inp -} - diff --git a/src/library/jvm/scala/xml/include/parsing/ExternalSources.scala b/src/library/jvm/scala/xml/include/parsing/ExternalSources.scala deleted file mode 100644 index cbfee413e6..0000000000 --- a/src/library/jvm/scala/xml/include/parsing/ExternalSources.scala +++ /dev/null @@ -1,82 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.xml.parsing - -import java.net.URL - -import scala.io.Source - -/** - * @author Burak Emir - * @version 1.0 - */ -trait ExternalSources { self: ExternalSources with MarkupParser with MarkupHandler => - - private def externalSourceFromURL(url: URL): Source = { - import java.io.{BufferedReader, InputStreamReader} - val in = - new BufferedReader( - new InputStreamReader( - url.openStream())) - - //@todo: replace this hack with proper Source implementation - - val str = new StringBuilder() - var inputLine: String = null - - //while (inputLine = in.readLine()) != null) { - while ({inputLine = in.readLine(); inputLine} ne null) { - // Console.println(inputLine) // DEBUG - str.append(inputLine) - str.append('\n') // readable output - } - in.close() - - class MyClass extends Source { - - def newIter = new Iterator[Char] { - var i = -1 - private val len = str.length-1 - def hasNext = i < len - def next = { i += 1; str.charAt(i) } - } - - val iter = newIter - - def reset: Source = new MyClass - - /*override var*/ descr = url.toExternalForm() - } - - new MyClass - } - - /** ... - * - * @param systemId ... - * @return ... - */ - def externalSource(systemId: String): Source = { - if (systemId startsWith "http:") - return externalSourceFromURL(new URL(systemId)) - - var fileStr = input.descr - - if (input.descr startsWith "file:") { - fileStr = input.descr.substring(5, input.descr.length) - } else - fileStr = fileStr.substring(0, - fileStr.lastIndexOf(java.io.File.separator)+1) - Source.fromFile(fileStr + systemId) - } - -} diff --git a/src/library/jvm/scala/xml/include/parsing/FactoryAdapter.scala b/src/library/jvm/scala/xml/include/parsing/FactoryAdapter.scala deleted file mode 100644 index 32c58c3ff6..0000000000 --- a/src/library/jvm/scala/xml/include/parsing/FactoryAdapter.scala +++ /dev/null @@ -1,321 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.xml.parsing - -import java.io.{InputStream, Reader, File, FileDescriptor, FileInputStream} -import scala.collection.mutable.{HashMap,Stack} - -import org.xml.sax.{Attributes, InputSource} - -import org.xml.sax.SAXException -import org.xml.sax.SAXNotRecognizedException -import org.xml.sax.SAXNotSupportedException -import org.xml.sax.SAXParseException -import org.xml.sax.helpers.DefaultHandler - -import javax.xml.parsers.SAXParserFactory -import javax.xml.parsers.ParserConfigurationException -import javax.xml.parsers.SAXParser - - -/** SAX adapter class, for use with Java SAX parser. Keeps track of - * namespace bindings, without relying on namespace handling of the - * underlying SAX parser. - */ -abstract class FactoryAdapter extends DefaultHandler() { - - val buffer = new StringBuilder() - val attribStack = new Stack[MetaData] - val hStack = new Stack[Node] // [ element ] contains siblings - val tagStack = new Stack[String] - var scopeStack = new Stack[NamespaceBinding] - - var curTag : String = null - var capture: Boolean = false - - // abstract methods - - /** Tests if an XML element contains text. - * @return true if element named localName contains text. - */ - def nodeContainsText(localName: String): Boolean // abstract - - /** creates an new non-text(tree) node. - * @param elemName - * @param attribs - * @param chIter - * @return a new XML element. - */ - def createNode(pre: String, elemName: String, attribs: MetaData, - scope: NamespaceBinding, chIter: List[Node]): Node //abstract - - /** creates a Text node. - * @param text - * @return a new Text node. - */ - def createText(text: String): Text // abstract - - /** creates a new processing instruction node. - */ - def createProcInstr(target: String, data: String): Seq[ProcInstr] - - // - // ContentHandler methods - // - - val normalizeWhitespace = false - - /** Characters. - * @param ch - * @param offset - * @param length - */ - override def characters(ch: Array[Char], offset: Int, length: Int): Unit = { - if (capture) { - if (normalizeWhitespace) { - // normalizing whitespace is not compliant, but useful */ - var i: Int = offset - var ws = false - while (i < offset + length) { - if (ch(i).isWhitespace) { - if (!ws) { - buffer.append(' ') - ws = true - } - } else { - buffer.append(ch(i)) - ws = false - } - i += 1 - } - } else { // compliant:report every character - buffer.append(ch, offset, length) - } - } - } - - //var elemCount = 0; //STATISTICS - - /* ContentHandler methods */ - - /* Start prefix mapping - use default impl. - def startPrefixMapping( prefix:String , uri:String ):Unit = {} - */ - - /* Start element. */ - override def startElement(uri: String, _localName: String, - qname: String, attributes: Attributes): Unit = { - /*elemCount = elemCount + 1; STATISTICS */ - captureText() - //Console.println("FactoryAdapter::startElement("+uri+","+_localName+","+qname+","+attributes+")"); - tagStack.push(curTag) - curTag = qname; //localName ; - - val colon = qname.indexOf(':'.asInstanceOf[Int]) - val localName = if(-1 == colon) qname else qname.substring(colon+1,qname.length()) - - //Console.println("FactoryAdapter::startElement - localName ="+localName); - - capture = nodeContainsText(localName) - - hStack.push(null) - var m: MetaData = Null - - var scpe = scopeStack.top - for (i <- List.range(0, attributes.getLength())) { - //val attrType = attributes.getType(i); // unused for now - val qname = attributes.getQName(i) - val value = attributes.getValue(i) - val colon = qname.indexOf(':'.asInstanceOf[Int]) - if (-1 != colon) { // prefixed attribute - val pre = qname.substring(0, colon) - val key = qname.substring(colon+1, qname.length()) - if ("xmlns" /*XML.xmlns*/ == pre) - scpe = value.length() match { - case 0 => new NamespaceBinding(key, null, scpe) - case _ => new NamespaceBinding(key, value, scpe) - } - else - m = new PrefixedAttribute(pre, key, Text(value), m) - } else if ("xmlns" /*XML.xmlns*/ == qname) - scpe = value.length() match { - case 0 => new NamespaceBinding(null, null, scpe) - case _ => new NamespaceBinding(null, value, scpe) - } - else - m = new UnprefixedAttribute(qname, Text(value), m) - } - scopeStack.push(scpe) - attribStack.push(m) - () - } // startElement(String,String,String,Attributes) - - - /** captures text, possibly normalizing whitespace - */ - def captureText(): Unit = { - if (capture) { - val text = buffer.toString() - if (text.length() > 0 && !text.equals(" ")) { - hStack.push(createText(text)) - } - } - buffer.setLength(0) - } - - /** End element. - * @param uri - * @param localName - * @param qname - * @throws org.xml.sax.SAXException if .. - */ - override def endElement(uri: String , _localName: String , qname: String): Unit = { - captureText() - - val metaData = attribStack.pop - - // reverse order to get it right - var v: List[Node] = Nil - var child: Node = hStack.pop - while (child ne null) { - v = child::v - child = hStack.pop - } - - val colon = qname.indexOf(':'.asInstanceOf[Int]) - val localName = - if (-1 == colon) qname - else qname.substring(colon+1, qname.length()) - - val scp = scopeStack.pop - // create element - val pre = if (-1 == colon) null else qname.substring(0, colon) - rootElem = createNode(pre, localName, metaData, scp, v) - - hStack.push(rootElem) - - // set - curTag = tagStack.pop - - capture = - if (curTag ne null) nodeContainsText(curTag) // root level - else false - } // endElement(String,String,String) - - /** Processing instruction. - */ - override def processingInstruction(target: String, data: String) { - for (pi <- createProcInstr(target, data)) - hStack.push(pi) - } - - // - // ErrorHandler methods - // - - /** Warning.*/ - override def warning(ex: SAXParseException): Unit = { - // ignore warning, crimson warns even for entity resolution! - //printError("Warning", ex); - } - - /** Error. */ - override def error(ex: SAXParseException): Unit = - printError("Error", ex) - - /** Fatal error.*/ - override def fatalError(ex: SAXParseException): Unit = - printError("Fatal Error", ex) - - // - // Protected methods - // - - /** Prints the error message */ - protected def printError(errtype: String, ex: SAXParseException): Unit = - Console.withOut(Console.err) { - Console.print("[") - Console.print(errtype) - Console.print("] ") - - var systemId = ex.getSystemId() - if (systemId ne null) { - val index = systemId.lastIndexOf('/'.asInstanceOf[Int]) - if (index != -1) - systemId = systemId.substring(index + 1) - //Console.print(systemId) - } - - Console.print(':') - Console.print(ex.getLineNumber()) - Console.print(':') - Console.print(ex.getColumnNumber()) - Console.print(": ") - Console.print(ex.getMessage()) - Console.println - Console.flush - } - - var rootElem: Node = null:Node - - //FactoryAdapter - // MAIN - // - - /** load XML document - * @param source - * @return a new XML document object - */ - def loadXML(source: InputSource): Node = { - // create parser - val parser: SAXParser = try { - val f = SAXParserFactory.newInstance() - f.setNamespaceAware(false) - f.newSAXParser() - } catch { - case e: Exception => - Console.err.println("error: Unable to instantiate parser") - throw e - } - - // parse file - scopeStack.push(TopScope) - parser.parse(source, this) - scopeStack.pop - return rootElem - } // loadXML - - /** loads XML from given file */ - def loadFile(file: File): Node = - loadXML(new InputSource(new FileInputStream(file))) - - /** loads XML from given file descriptor */ - def loadFile(fileDesc: FileDescriptor): Node = - loadXML(new InputSource(new FileInputStream(fileDesc))) - - /** loads XML from given file */ - def loadFile(fileName: String): Node = - loadXML(new InputSource(new FileInputStream(fileName))) - - /** loads XML from given InputStream */ - def load(is: InputStream): Node = - loadXML(new InputSource(is)) - - /** loads XML from given Reader */ - def load(reader: Reader): Node = - loadXML(new InputSource(reader)) - - /** loads XML from given sysID */ - def load(sysID: String): Node = - loadXML(new InputSource(sysID)) - -} diff --git a/src/library/jvm/scala/xml/include/parsing/FatalError.scala b/src/library/jvm/scala/xml/include/parsing/FatalError.scala deleted file mode 100644 index 2768becb8b..0000000000 --- a/src/library/jvm/scala/xml/include/parsing/FatalError.scala +++ /dev/null @@ -1,15 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.xml.parsing; - - -case class FatalError(msg:String) extends java.lang.RuntimeException(msg); diff --git a/src/library/jvm/scala/xml/include/parsing/MarkupParser.scala b/src/library/jvm/scala/xml/include/parsing/MarkupParser.scala deleted file mode 100644 index 541cc65ac2..0000000000 --- a/src/library/jvm/scala/xml/include/parsing/MarkupParser.scala +++ /dev/null @@ -1,1215 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.xml.parsing - -import scala.io.Source -import scala.xml.dtd._ - -/** - * An XML parser. - * - * Parses XML 1.0, invokes callback methods of a MarkupHandler - * and returns whatever the markup handler returns. Use - * ConstructingParser if you just want to parse XML to - * construct instances of scala.xml.Node. - * - * While XML elements are returned, DTD declarations - if handled - are - * collected using side-effects. - * - * @author Burak Emir - * @version 1.0 - */ -trait MarkupParser extends AnyRef with TokenTests { self: MarkupParser with MarkupHandler => - - val input: Source - - /** if true, does not remove surplus whitespace */ - val preserveWS: Boolean - - def externalSource(systemLiteral: String): Source - - // - // variables, values - // - - var curInput: Source = input - - /** the handler of the markup, returns this */ - private val handle: MarkupHandler = this - - /** stack of inputs */ - var inpStack: List[Source] = Nil - - /** holds the position in the source file */ - var pos: Int = _ - - - /* used when reading external subset */ - var extIndex = -1 - - /** holds temporary values of pos */ - var tmppos: Int = _ - - /** holds the next character */ - var ch: Char = _ - - /** character buffer, for names */ - protected val cbuf = new StringBuilder() - - var dtd: DTD = null - - protected var doc: Document = null - - var eof: Boolean = false - - // - // methods - // - - /** <? prolog ::= xml S ... ?> - */ - def xmlProcInstr(): MetaData = { - xToken("xml") - xSpace - val (md,scp) = xAttributes(TopScope) - if (scp != TopScope) - reportSyntaxError("no xmlns definitions here, please."); - xToken('?') - xToken('>') - md - } - - /** <? prolog ::= xml S? - * // this is a bit more lenient than necessary... - */ - def prolog(): Tuple3[Option[String], Option[String], Option[Boolean]] = { - - //Console.println("(DEBUG) prolog") - var n = 0 - var info_ver: Option[String] = None - var info_enc: Option[String] = None - var info_stdl: Option[Boolean] = None - - var m = xmlProcInstr() - - xSpaceOpt - - m("version") match { - case null => ; - case Text("1.0") => info_ver = Some("1.0"); n += 1 - case _ => reportSyntaxError("cannot deal with versions != 1.0") - } - - m("encoding") match { - case null => ; - case Text(enc) => - if (!isValidIANAEncoding(enc)) - reportSyntaxError("\"" + enc + "\" is not a valid encoding") - else { - info_enc = Some(enc) - n += 1 - } - } - m("standalone") match { - case null => ; - case Text("yes") => info_stdl = Some(true); n += 1 - case Text("no") => info_stdl = Some(false); n += 1 - case _ => reportSyntaxError("either 'yes' or 'no' expected") - } - - if (m.length - n != 0) { - reportSyntaxError("VersionInfo EncodingDecl? SDDecl? or '?>' expected!"); - } - //Console.println("[MarkupParser::prolog] finished parsing prolog!"); - Tuple3(info_ver,info_enc,info_stdl) - } - - /** prolog, but without standalone */ - def textDecl(): Tuple2[Option[String],Option[String]] = { - - var info_ver: Option[String] = None - var info_enc: Option[String] = None - - var m = xmlProcInstr() - var n = 0 - - m("version") match { - case null => ; - case Text("1.0") => info_ver = Some("1.0"); n += 1 - case _ => reportSyntaxError("cannot deal with versions != 1.0") - } - - m("encoding") match { - case null => ; - case Text(enc) => - if (!isValidIANAEncoding(enc)) - reportSyntaxError("\"" + enc + "\" is not a valid encoding") - else { - info_enc = Some(enc) - n += 1 - } - } - - if (m.length - n != 0) { - reportSyntaxError("VersionInfo EncodingDecl? or '?>' expected!"); - } - //Console.println("[MarkupParser::textDecl] finished parsing textdecl"); - Tuple2(info_ver, info_enc); - } - - /** - *[22] prolog ::= XMLDecl? Misc* (doctypedecl Misc*)? - *[23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>' - *[24] VersionInfo ::= S 'version' Eq ("'" VersionNum "'" | '"' VersionNum '"') - *[25] Eq ::= S? '=' S? - *[26] VersionNum ::= '1.0' - *[27] Misc ::= Comment | PI | S - */ - - def document(): Document = { - - //Console.println("(DEBUG) document") - doc = new Document() - - this.dtd = null - var info_prolog: Tuple3[Option[String], Option[String], Option[Boolean]] = Tuple3(None, None, None); - if ('<' != ch) { - reportSyntaxError("< expected") - return null - } - - nextch // is prolog ? - var children: NodeSeq = null - if ('?' == ch) { - //Console.println("[MarkupParser::document] starts with xml declaration"); - nextch; - info_prolog = prolog() - doc.version = info_prolog._1 - doc.encoding = info_prolog._2 - doc.standAlone = info_prolog._3 - - children = content(TopScope) // DTD handled as side effect - } else { - //Console.println("[MarkupParser::document] does not start with xml declaration"); - // - - val ts = new NodeBuffer(); - content1(TopScope, ts); // DTD handled as side effect - ts &+ content(TopScope); - children = NodeSeq.fromSeq(ts); - } - //Console.println("[MarkupParser::document] children now: "+children.toList); - var elemCount = 0; - var theNode: Node = null; - for (c <- children) c match { - case _:ProcInstr => ; - case _:Comment => ; - case _:EntityRef => // todo: fix entities, shouldn't be "special" - reportSyntaxError("no entity references alllowed here"); - case s:SpecialNode => - if (s.toString().trim().length > 0) //non-empty text nodes not allowed - elemCount = elemCount + 2; - case m:Node => - elemCount = elemCount + 1; - theNode = m; - } - if (1 != elemCount) { - reportSyntaxError("document must contain exactly one element") - Console.println(children.toList) - } - - doc.children = children - doc.docElem = theNode - doc - } - - /** append Unicode character to name buffer*/ - protected def putChar(c: Char) = cbuf.append(c) - - //var xEmbeddedBlock = false; - - /** this method assign the next character to ch and advances in input */ - def nextch { - if (curInput.hasNext) { - ch = curInput.next - pos = curInput.pos - } else { - val ilen = inpStack.length; - //Console.println(" ilen = "+ilen+ " extIndex = "+extIndex); - if ((ilen != extIndex) && (ilen > 0)) { - /** for external source, inpStack == Nil ! need notify of eof! */ - pop() - } else { - eof = true - ch = 0.asInstanceOf[Char] - } - } - } - - //final val enableEmbeddedExpressions: Boolean = false; - - /** munch expected XML token, report syntax error for unexpected - */ - def xToken(that: Char) { - if (ch == that) - nextch - else { - reportSyntaxError("'" + that + "' expected instead of '" + ch + "'") - error("FATAL") - } - } - - def xToken(that: Seq[Char]): Unit = { - val it = that.elements; - while (it.hasNext) - xToken(it.next); - } - - /** parse attribute and create namespace scope, metadata - * [41] Attributes ::= { S Name Eq AttValue } - */ - def xAttributes(pscope:NamespaceBinding): (MetaData,NamespaceBinding) = { - var scope: NamespaceBinding = pscope - var aMap: MetaData = Null - while (isNameStart(ch)) { - val pos = this.pos - - val qname = xName - val _ = xEQ - val value = xAttributeValue() - - Utility.prefix(qname) match { - case Some("xmlns") => - val prefix = qname.substring(6 /*xmlns:*/ , qname.length); - scope = new NamespaceBinding(prefix, value, scope); - - case Some(prefix) => - val key = qname.substring(prefix.length+1, qname.length); - aMap = new PrefixedAttribute(prefix, key, Text(value), aMap); - - case _ => - if( qname == "xmlns" ) - scope = new NamespaceBinding(null, value, scope); - else - aMap = new UnprefixedAttribute(qname, Text(value), aMap); - } - - if ((ch != '/') && (ch != '>') && ('?' != ch)) - xSpace; - } - - if(!aMap.wellformed(scope)) - reportSyntaxError( "double attribute"); - - (aMap,scope) - } - - /** attribute value, terminated by either ' or ". value may not contain <. - * AttValue ::= `'` { _ } `'` - * | `"` { _ } `"` - */ - def xAttributeValue(): String = { - val endch = ch - nextch - while (ch != endch) { - if ('<' == ch) - reportSyntaxError( "'<' not allowed in attrib value" ); - putChar(ch) - nextch - } - nextch - val str = cbuf.toString() - cbuf.length = 0 - - // well-formedness constraint - normalizeAttributeValue(str) - } - - /** entity value, terminated by either ' or ". value may not contain <. - * AttValue ::= `'` { _ } `'` - * | `"` { _ } `"` - */ - def xEntityValue(): String = { - val endch = ch - nextch - while (ch != endch) { - putChar(ch) - nextch - } - nextch - val str = cbuf.toString() - cbuf.length = 0 - str - } - - - /** parse a start or empty tag. - * [40] STag ::= '<' Name { S Attribute } [S] - * [44] EmptyElemTag ::= '<' Name { S Attribute } [S] - */ - protected def xTag(pscope:NamespaceBinding): Tuple3[String, MetaData, NamespaceBinding] = { - val qname = xName - - xSpaceOpt - val (aMap: MetaData, scope: NamespaceBinding) = { - if (isNameStart(ch)) - xAttributes(pscope) - else - (Null, pscope) - } - (qname, aMap, scope) - } - - /** [42] '<' xmlEndTag ::= '<' '/' Name S? '>' - */ - def xEndTag(n: String) = { - xToken('/') - val m = xName - if (n != m) - reportSyntaxError("expected closing tag of " + n/* +", not "+m*/); - xSpaceOpt - xToken('>') - } - - /** '<! CharData ::= [CDATA[ ( {char} - {char}"]]>"{char} ) ']]>' - * - * see [15] - */ - def xCharData: NodeSeq = { - xToken("[CDATA[") - val pos1 = pos - val sb: StringBuilder = new StringBuilder() - while (true) { - if (ch==']' && - { sb.append(ch); nextch; ch == ']' } && - { sb.append(ch); nextch; ch == '>' } ) { - sb.length = sb.length - 2 - nextch; - return handle.text( pos1, sb.toString() ); - } else sb.append( ch ); - nextch; - } - throw FatalError("this cannot happen"); - }; - - /** CharRef ::= "&#" '0'..'9' {'0'..'9'} ";" - * | "&#x" '0'..'9'|'A'..'F'|'a'..'f' { hexdigit } ";" - * - * see [66] - */ - def xCharRef(ch: () => Char, nextch: () => Unit): String = { - Utility.parseCharRef(ch, nextch, reportSyntaxError _) - /* - val hex = (ch() == 'x') && { nextch(); true }; - val base = if (hex) 16 else 10; - var i = 0; - while (ch() != ';') { - ch() match { - case '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' => - i = i * base + Character.digit( ch(), base ); - case 'a' | 'b' | 'c' | 'd' | 'e' | 'f' - | 'A' | 'B' | 'C' | 'D' | 'E' | 'F' => - if (! hex) - reportSyntaxError("hex char not allowed in decimal char ref\n" - +"Did you mean to write &#x ?"); - else - i = i * base + Character.digit(ch(), base); - case _ => - reportSyntaxError("character '" + ch() + " not allowed in char ref\n"); - } - nextch(); - } - new String(Array(i.asInstanceOf[char])) - */ - } - - - /** Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->' - * - * see [15] - */ - def xComment: NodeSeq = { - val sb: StringBuilder = new StringBuilder() - xToken('-') - xToken('-') - while (true) { - if (ch == '-' && { sb.append(ch); nextch; ch == '-' }) { - sb.length = sb.length - 1 - nextch - xToken('>') - return handle.comment(pos, sb.toString()) - } else sb.append(ch) - nextch - } - throw FatalError("this cannot happen") - } - - /* todo: move this into the NodeBuilder class */ - def appendText(pos: Int, ts: NodeBuffer, txt: String): Unit = { - if (preserveWS) - ts &+ handle.text(pos, txt); - else - for (t <- TextBuffer.fromString(txt).toText) { - ts &+ handle.text(pos, t.text); - } - } - - /** '<' content1 ::= ... */ - def content1(pscope: NamespaceBinding, ts: NodeBuffer): Unit = - ch match { - case '!' => - nextch - if ('[' == ch) // CDATA - ts &+ xCharData - else if ('D' == ch) // doctypedecl, parse DTD // @todo REMOVE HACK - parseDTD() - else // comment - ts &+ xComment - case '?' => // PI - nextch - ts &+ xProcInstr - case _ => - ts &+ element1(pscope) // child - } - - /** content1 ::= '<' content1 | '&' charref ... */ - def content(pscope: NamespaceBinding): NodeSeq = { - var ts = new NodeBuffer - var exit = eof - while (! exit) { - //Console.println("in content, ch = '"+ch+"' line="+scala.io.Position.line(pos)); - /* if( xEmbeddedBlock ) { - ts.append( xEmbeddedExpr ); - } else {*/ - tmppos = pos; - exit = eof; - if(!eof) - ch match { - case '<' => // another tag - //Console.println("before ch = '"+ch+"' line="+scala.io.Position.line(pos)+" pos="+pos); - nextch; - //Console.println("after ch = '"+ch+"' line="+scala.io.Position.line(pos)+" pos="+pos); - - if('/' ==ch) - exit = true; // end tag - else - content1(pscope, ts) - //case '{' => -/* if( xCheckEmbeddedBlock ) { - ts.appendAll(xEmbeddedExpr); - } else {*/ - // val str = new StringBuilder("{"); - // str.append(xText); - // appendText(tmppos, ts, str.toString()); - /*}*/ - // postcond: xEmbeddedBlock == false! - case '&' => // EntityRef or CharRef - nextch; - ch match { - case '#' => // CharacterRef - nextch; - val theChar = handle.text( tmppos, - xCharRef ({ ()=> ch },{ () => nextch }) ); - xToken(';'); - ts &+ theChar ; - case _ => // EntityRef - val n = xName - xToken(';') - n match { - case "lt" => ts &+ '<' - case "gt" => ts &+ '>' - case "amp" => ts &+ '&' - case "quot" => ts &+ '"' - case _ => - /* - ts + handle.entityRef( tmppos, n ) ; - */ - push(n) - } - } - case _ => // text content - //Console.println("text content?? pos = "+pos); - appendText(tmppos, ts, xText); - // here xEmbeddedBlock might be true - } - /*}*/ - } - val list = ts.toList - // 2do: optimize seq repr. - new NodeSeq { - val theSeq = list - } - } // content(NamespaceBinding) - - /** externalID ::= SYSTEM S syslit - * PUBLIC S pubid S syslit - */ - - def externalID(): ExternalID = ch match { - case 'S' => - nextch - xToken("YSTEM") - xSpace - val sysID = systemLiteral() - new SystemID(sysID) - case 'P' => - nextch; xToken("UBLIC") - xSpace - val pubID = pubidLiteral() - xSpace - val sysID = systemLiteral() - new PublicID(pubID, sysID) - } - - - /** parses document type declaration and assigns it to instance variable - * dtd. - * - * <! parseDTD ::= DOCTYPE name ... > - */ - def parseDTD(): Unit = { // dirty but fast - //Console.println("(DEBUG) parseDTD"); - var extID: ExternalID = null - if (this.dtd ne null) - reportSyntaxError("unexpected character (DOCTYPE already defined"); - xToken("DOCTYPE") - xSpace - val n = xName - xSpace - //external ID - if ('S' == ch || 'P' == ch) { - extID = externalID() - xSpaceOpt - } - - /* parse external subset of DTD - */ - - if ((null != extID) && isValidating) { - - pushExternal(extID.systemId) - //val extSubsetSrc = externalSource( extID.systemId ); - - extIndex = inpStack.length - /* - .indexOf(':') != -1) { // assume URI - Source.fromFile(new java.net.URI(extID.systemLiteral)); - } else { - Source.fromFile(extID.systemLiteral); - } - */ - //Console.println("I'll print it now"); - //val old = curInput; - //tmppos = curInput.pos; - //val oldch = ch; - //curInput = extSubsetSrc; - //pos = 0; - //nextch; - - extSubset() - - pop() - - extIndex = -1 - - //curInput = old; - //pos = curInput.pos; - //ch = curInput.ch; - //eof = false; - //while(extSubsetSrc.hasNext) - //Console.print(extSubsetSrc.next); - - //Console.println("returned from external, current ch = "+ch ) - } - - if ('[' == ch) { // internal subset - nextch - /* TODO */ - //Console.println("hello"); - intSubset() - //while(']' != ch) - // nextch; - // TODO: do the DTD parsing?? ?!?!?!?!! - xToken(']') - xSpaceOpt - } - xToken('>') - this.dtd = new DTD { - /*override var*/ externalID = extID - /*override val */decls = handle.decls.reverse - } - //this.dtd.initializeEntities(); - if (doc ne null) - doc.dtd = this.dtd - - handle.endDTD(n) - } - - def element(pscope: NamespaceBinding): NodeSeq = { - xToken('<') - element1(pscope) - } - - /** '<' element ::= xmlTag1 '>' { xmlExpr | '{' simpleExpr '}' } ETag - * | xmlTag1 '/' '>' - */ - def element1(pscope: NamespaceBinding): NodeSeq = { - val pos = this.pos - val Tuple3(qname, aMap, scope) = xTag(pscope) - val Tuple2(pre, local) = Utility.prefix(qname) match { - case Some(p) => (p,qname.substring(p.length+1, qname.length)) - case _ => (null,qname) - } - val ts = { - if (ch == '/') { // empty element - xToken('/') - xToken('>') - handle.elemStart(pos, pre, local, aMap, scope) - NodeSeq.Empty - } - else { // element with content - xToken('>') - handle.elemStart(pos, pre, local, aMap, scope) - val tmp = content(scope) - xEndTag(qname) - tmp - } - } - val res = handle.elem(pos, pre, local, aMap, scope, ts) - handle.elemEnd(pos, pre, local) - res - } - - //def xEmbeddedExpr: MarkupType; - - /** Name ::= (Letter | '_' | ':') (NameChar)* - * - * see [5] of XML 1.0 specification - */ - def xName: String = { - if (isNameStart(ch)) { - while (isNameChar(ch)) { - putChar(ch) - nextch - } - val n = cbuf.toString().intern() - cbuf.length = 0 - n - } else { - reportSyntaxError("name expected") - "" - } - } - - /** scan [S] '=' [S]*/ - def xEQ = { xSpaceOpt; xToken('='); xSpaceOpt } - - /** skip optional space S? */ - def xSpaceOpt = while (isSpace(ch) && !eof) { nextch; } - - /** scan [3] S ::= (#x20 | #x9 | #xD | #xA)+ */ - def xSpace = - if (isSpace(ch)) { nextch; xSpaceOpt } - else reportSyntaxError("whitespace expected") - - /** '<?' ProcInstr ::= Name [S ({Char} - ({Char}'>?' {Char})]'?>' - * - * see [15] - */ - def xProcInstr: NodeSeq = { - val sb:StringBuilder = new StringBuilder() - val n = xName - if (isSpace(ch)) { - xSpace - while (true) { - if (ch == '?' && { sb.append( ch ); nextch; ch == '>' }) { - sb.length = sb.length - 1; - nextch; - return handle.procInstr(tmppos, n, sb.toString); - } else - sb.append(ch); - nextch - } - }; - xToken('?') - xToken('>') - handle.procInstr(tmppos, n, sb.toString) - } - - /** parse character data. - * precondition: xEmbeddedBlock == false (we are not in a scala block) - */ - def xText: String = { - //if( xEmbeddedBlock ) throw FatalError("internal error: encountered embedded block"); // assert - - /*if( xCheckEmbeddedBlock ) - return "" - else {*/ - //Console.println("in xText! ch = '"+ch+"'"); - var exit = false; - while (! exit) { - //Console.println("LOOP in xText! ch = '"+ch+"' + pos="+pos); - putChar(ch); - val opos = pos; - nextch; - - //Console.println("STILL LOOP in xText! ch = '"+ch+"' + pos="+pos+" opos="+opos); - - - exit = eof || /*{ nextch; xCheckEmbeddedBlock }||*/( ch == '<' ) || ( ch == '&' ); - } - val str = cbuf.toString(); - cbuf.length = 0; - str - /*}*/ - } - - /** attribute value, terminated by either ' or ". value may not contain <. - * AttValue ::= `'` { _ } `'` - * | `"` { _ } `"` - */ - def systemLiteral(): String = { - val endch = ch - if (ch != '\'' && ch != '"') - reportSyntaxError("quote ' or \" expected"); - nextch - while (ch != endch) { - putChar(ch) - nextch - } - nextch - val str = cbuf.toString() - cbuf.length = 0 - str - } - - - /* [12] PubidLiteral ::= '"' PubidChar* '"' | "'" (PubidChar - "'")* "'" */ - def pubidLiteral(): String = { - val endch = ch - if (ch!='\'' && ch != '"') - reportSyntaxError("quote ' or \" expected"); - nextch - while (ch != endch) { - putChar(ch) - //Console.println("hello '"+ch+"'"+isPubIDChar(ch)); - if (!isPubIDChar(ch)) - reportSyntaxError("char '"+ch+"' is not allowed in public id"); - nextch - } - nextch - val str = cbuf.toString() - cbuf.length = 0 - str - } - - // - // dtd parsing - // - - def extSubset(): Unit = { - var textdecl:Tuple2[Option[String],Option[String]] = null; - if (ch=='<') { - nextch - if (ch=='?') { - nextch - textdecl = textDecl() - } else - markupDecl1() - } - while (!eof) - markupDecl() - } - - def markupDecl1() = { - def doInclude() = { - xToken('['); while(']' != ch) markupDecl(); nextch // ']' - } - def doIgnore() = { - xToken('['); while(']' != ch) nextch; nextch; // ']' - } - if ('?' == ch) { - nextch - xProcInstr // simply ignore processing instructions! - } else { - xToken('!') - ch match { - case '-' => - xComment // ignore comments - - case 'E' => - nextch - if ('L' == ch) { - nextch - elementDecl() - } else - entityDecl() - - case 'A' => - nextch - attrDecl() - - case 'N' => - nextch - notationDecl() - - case '[' if inpStack.length >= extIndex => - nextch - xSpaceOpt - ch match { - case '%' => - nextch - val ent = xName - xToken(';') - xSpaceOpt - /* - Console.println("hello, pushing!"); - { - val test = replacementText(ent); - while(test.hasNext) - Console.print(test.next); - } */ - push(ent) - xSpaceOpt - //Console.println("hello, getting name"); - val stmt = xName - //Console.println("hello, got name"); - xSpaceOpt - //Console.println("how can we be eof = "+eof); - - // eof = true because not external?! - //if(!eof) - // error("expected only INCLUDE or IGNORE"); - - //pop(); - - //Console.println("hello, popped"); - stmt match { - // parameter entity - case "INCLUDE" => - doInclude() - case "IGNORE" => - doIgnore() - } - case 'I' => - nextch - ch match { - case 'G' => - nextch - xToken("NORE") - xSpaceOpt - doIgnore() - case 'N' => - nextch - xToken("NCLUDE") - doInclude() - } - } - xToken(']') - xToken('>') - - case _ => - curInput.reportError(pos, "unexpected character '"+ch+"', expected some markupdecl") - while (ch!='>') - nextch - } - } - } - - def markupDecl(): Unit = ch match { - case '%' => // parameter entity reference - nextch - val ent = xName - xToken(';') - if (!isValidating) - handle.peReference(ent) // n-v: just create PE-reference - else - push(ent) // v: parse replacementText - - //peReference - case '<' => - nextch - markupDecl1() - case _ if isSpace(ch) => - xSpace - case _ => - reportSyntaxError("markupdecl: unexpected character '"+ch+"' #" + ch.asInstanceOf[Int]) - nextch - } - - /** "rec-xml/#ExtSubset" pe references may not occur within markup - declarations - */ - def intSubset() { - //Console.println("(DEBUG) intSubset()") - xSpace - while (']' != ch) - markupDecl() - } - - /** <! element := ELEMENT - */ - def elementDecl() { - xToken("EMENT") - xSpace - val n = xName - xSpace - while ('>' != ch) { - //Console.println("["+ch+"]") - putChar(ch) - nextch - } - //Console.println("END["+ch+"]") - nextch - val cmstr = cbuf.toString() - cbuf.length = 0 - handle.elemDecl(n, cmstr) - } - - /** <! attlist := ATTLIST - */ - def attrDecl() = { - xToken("TTLIST") - xSpace - val n = xName - xSpace - var attList: List[AttrDecl] = Nil - // later: find the elemDecl for n - while ('>' != ch) { - val aname = xName - //Console.println("attribute name: "+aname); - var defdecl: DefaultDecl = null - xSpace - // could be enumeration (foo,bar) parse this later :-/ - while ('"' != ch && '\'' != ch && '#' != ch && '<' != ch) { - if (!isSpace(ch)) - cbuf.append(ch); - nextch; - } - val atpe = cbuf.toString() - cbuf.length = 0 - //Console.println("attr type: "+atpe); - ch match { - case '\'' | '"' => - val defValue = xAttributeValue() // default value - defdecl = DEFAULT(false, defValue) - - case '#' => - nextch - xName match { - case "FIXED" => - xSpace - val defValue = xAttributeValue() // default value - defdecl = DEFAULT(true, defValue) - case "IMPLIED" => - defdecl = IMPLIED - case "REQUIRED" => - defdecl = REQUIRED - } - case _ => - } - xSpaceOpt - - attList = AttrDecl(aname, atpe, defdecl) :: attList - cbuf.length = 0 - } - nextch - handle.attListDecl(n, attList.reverse) - } - - /** <! element := ELEMENT - */ - def entityDecl() = { - //Console.println("entityDecl()") - var isParameterEntity = false - var entdef: EntityDef = null - xToken("NTITY") - xSpace - if ('%' == ch) { - nextch - isParameterEntity = true - xSpace - } - val n = xName - xSpace - ch match { - case 'S' | 'P' => //sy - val extID = externalID() - if (isParameterEntity) { - xSpaceOpt - xToken('>') - handle.parameterEntityDecl(n, ExtDef(extID)) - } else { // notation? - xSpace - if ('>' != ch) { - xToken("NDATA") - xSpace - val notat = xName - xSpaceOpt - xToken('>') - handle.unparsedEntityDecl(n, extID, notat) - } else { - nextch - handle.parsedEntityDecl(n, ExtDef(extID)) - } - } - - case '"' | '\'' => - val av = xEntityValue() - xSpaceOpt - xToken('>') - if (isParameterEntity) - handle.parameterEntityDecl(n, IntDef(av)) - else - handle.parsedEntityDecl(n, IntDef(av)) - } - {} - } // entityDecl - - /** 'N' notationDecl ::= "OTATION" - */ - def notationDecl() { - xToken("OTATION") - xSpace - val notat = xName - xSpace - val extID = if (ch == 'S') { - externalID(); - } - else if (ch == 'P') { - /** PublicID (without system, only used in NOTATION) */ - nextch - xToken("UBLIC") - xSpace - val pubID = pubidLiteral() - xSpaceOpt - val sysID = if (ch != '>') - systemLiteral() - else - null; - new PublicID(pubID, sysID); - } else { - reportSyntaxError("PUBLIC or SYSTEM expected"); - error("died parsing notationdecl") - } - xSpaceOpt - xToken('>') - handle.notationDecl(notat, extID) - } - - /** - * report a syntax error - */ - def reportSyntaxError(pos: Int, str: String) { - curInput.reportError(pos, str) - //error("MarkupParser::synerr") // DEBUG - } - - def reportSyntaxError(str: String): Unit = reportSyntaxError(pos, str) - - /** - * report a syntax error - */ - def reportValidationError(pos: Int, str: String) { - curInput.reportError(pos, str) - } - - def push(entityName: String) { - //Console.println("BEFORE PUSHING "+ch) - //Console.println("BEFORE PUSHING "+pos) - //Console.print("[PUSHING "+entityName+"]") - if (!eof) - inpStack = curInput :: inpStack - - curInput = replacementText(entityName) - nextch - } - - /* - def push(src:Source) = { - curInput = src - nextch - } - */ - - def pushExternal(systemId: String) { - //Console.print("BEFORE PUSH, curInput = $"+curInput.descr) - //Console.println(" stack = "+inpStack.map { x => "$"+x.descr }) - - //Console.print("[PUSHING EXTERNAL "+systemId+"]") - if (!eof) - inpStack = curInput :: inpStack - - curInput = externalSource(systemId) - - //Console.print("AFTER PUSH, curInput = $"+curInput.descr) - //Console.println(" stack = "+inpStack.map { x => "$"+x.descr }) - - nextch - } - - def pop() { - curInput = inpStack.head - inpStack = inpStack.tail - ch = curInput.ch - pos = curInput.pos - eof = false // must be false, because of places where entity refs occur - //Console.println("\n AFTER POP, curInput = $"+curInput.descr); - //Console.println(inpStack.map { x => x.descr }); - } - - /** for the moment, replace only character references - * see spec 3.3.3 - * precond: cbuf empty - */ - def normalizeAttributeValue(attval: String): String = { - val s: Seq[Char] = attval - val it = s.elements - while (it.hasNext) { - it.next match { - case ' '|'\t'|'\n'|'\r' => - cbuf.append(' '); - case '&' => it.next match { - case '#' => - var c = it.next - val s = xCharRef ({ () => c }, { () => c = it.next }) - cbuf.append(s) - case nchar => - val nbuf = new StringBuilder() - var d = nchar - do { - nbuf.append(d) - d = it.next - } while(d != ';'); - nbuf.toString() match { - case "lt" => cbuf.append('<') - case "gt" => cbuf.append('>') - case "amp" => cbuf.append('&') - case "apos" => cbuf.append('\'') - case "quot" => cbuf.append('"') - case "quote" => cbuf.append('"') - case name => - cbuf.append('&') - cbuf.append(name) - cbuf.append(';') - } - } - case c => - cbuf.append(c) - } - } - val name = cbuf.toString() - cbuf.length = 0 - name - } - -} diff --git a/src/library/jvm/scala/xml/include/parsing/NoBindingFactoryAdapter.scala b/src/library/jvm/scala/xml/include/parsing/NoBindingFactoryAdapter.scala deleted file mode 100644 index be71e55fef..0000000000 --- a/src/library/jvm/scala/xml/include/parsing/NoBindingFactoryAdapter.scala +++ /dev/null @@ -1,62 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.xml.parsing; - - -import scala.xml.factory.NodeFactory; -import org.xml.sax.InputSource; - -/** nobinding adaptor providing callbacks to parser to create elements. -* implements hash-consing -*/ -class NoBindingFactoryAdapter extends FactoryAdapter with NodeFactory[Elem] { - - // -- FactoryAdapter methods - - /** returns true. Every XML node may contain text that the application needs - **/ - def nodeContainsText( label:java.lang.String ): Boolean = true; - - - // methods for NodeFactory[Elem] - - /** constructs an instance of scala.xml.Elem */ - protected def create(pre: String, label: String, attrs: MetaData, scpe: NamespaceBinding, children:Seq[Node]): Elem = { - Elem( pre, label, attrs, scpe, children:_* ); - } - - // -- methods for FactoryAdapter - - /** creates a node. never creates the same node twice, using hash-consing - */ - def createNode(pre:String, label: String, attrs: MetaData, scpe: NamespaceBinding, children: List[Node] ): Elem = { - //Console.println("NoBindingFactoryAdapter::createNode("+pre+","+label+","+attrs+","+scpe+","+children+")"); - Elem( pre, label, attrs, scpe, children:_* ); - //makeNode(pre, label, attrs, scpe, children); - } - - /** creates a text node - */ - def createText( text:String ) = - Text( text ); - - /** create a processing instruction - */ - def createProcInstr(target: String, data: String) = - makeProcInstr(target, data) - - /** loads an XML document, returning a Symbol node. - */ - override def loadXML( source:InputSource ):Elem = - super.loadXML( source ).asInstanceOf[ Elem ]; - -} diff --git a/src/library/jvm/scala/xml/include/parsing/TokenTests.scala b/src/library/jvm/scala/xml/include/parsing/TokenTests.scala deleted file mode 100644 index d56b9bb7d7..0000000000 --- a/src/library/jvm/scala/xml/include/parsing/TokenTests.scala +++ /dev/null @@ -1,146 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.xml.parsing; - - -/** - * Helper functions for parsing XML fragments - */ -trait TokenTests { - - /** (#x20 | #x9 | #xD | #xA) */ - final def isSpace( ch:Char ): Boolean = ch match { - case '\u0009' | '\u000A' | '\u000D' | '\u0020' => true - case _ => false; - } - - /** (#x20 | #x9 | #xD | #xA)+ */ - final def isSpace(cs: Seq[Char]): Boolean = { - val it = cs.elements; - it.hasNext && it.forall { isSpace }; - } - - /** NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' - * | CombiningChar | Extender - * - * see [4] and Appendix B of XML 1.0 specification - */ - def isNameChar(ch: Char) = isNameStart(ch) || (ch match { - case '.' | '-' | ':' => true; - case _ => java.lang.Character.getType( ch ).asInstanceOf[Byte] match { - case java.lang.Character.COMBINING_SPACING_MARK => true; // Mc - case java.lang.Character.ENCLOSING_MARK => true; // Me - case java.lang.Character.NON_SPACING_MARK => true; // Mn - case java.lang.Character.MODIFIER_LETTER => true; // Lm - case java.lang.Character.DECIMAL_DIGIT_NUMBER => true; // Nd - case _ => false; - } - }); - - /** NameStart ::= ( Letter | '_' ) - * where Letter means in one of the Unicode general - * categories { Ll, Lu, Lo, Lt, Nl } - * - * We do not allow a name to start with ':'. - * see [3] and Appendix B of XML 1.0 specification - */ - def isNameStart(ch: Char) = - java.lang.Character.getType(ch).asInstanceOf[Byte] match { - case java.lang.Character.LOWERCASE_LETTER => true; - case java.lang.Character.UPPERCASE_LETTER => true; - case java.lang.Character.OTHER_LETTER => true; - case java.lang.Character.TITLECASE_LETTER => true; - case java.lang.Character.LETTER_NUMBER => true; - case _ => ch match { - case '_' => true - case _ => false; - } - } - - /** Name ::= ( Letter | '_' ) (NameChar)* - * - * see [5] of XML 1.0 specification - */ - def isName(s: String): Boolean = { - if( s.length() > 0 ) { - val y = s.elements; - if (isNameStart(y.next)) { - while (y.hasNext && isNameChar(y.next)) {}; - !y.hasNext - } else false; - } else false; - } - - def isPubIDChar(ch: Char): Boolean = { - //Console.println("char: '" + ch + "'"); - ch match { - case '\u0020' | '\u000D' | '\u000A' => true; - case _ if - (('0' <= ch && ch <= '9') || ('a' <= ch && ch <= 'z') || - ('A' <= ch && ch <= 'Z')) => true; - case '-' | '\''| '(' | ')' | '+' | ',' | '.' | - '/' | ':' | '=' | '?' | ';' | '!' | '*' | - '#' | '@' | '$' | '_' | '%' => true - case _ => - //Console.println("false: '" + ch + "'"); - false; - } - } - - /** - * Returns true if the encoding name is a valid IANA encoding. - * This method does not verify that there is a decoder available - * for this encoding, only that the characters are valid for an - * IANA encoding name. - * - * @param ianaEncoding The IANA encoding name. - */ - def isValidIANAEncoding(ianaEncoding: Seq[Char]): Boolean = { - val it = ianaEncoding.elements; - if (!it.hasNext) - return false; - - var c = it.next; - if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) { - while (it.hasNext) { - c = it.next; - if ((c < 'A' || c > 'Z') && (c < 'a' || c > 'z') && - (c < '0' || c > '9') && c != '.' && c != '_' && - c != '-') { - return false; - } - } - return true; - } else - return false; - } // isValidIANAEncoding(String): Boolean - - def checkSysID( s:String ): Boolean = { - s.indexOf('"'.asInstanceOf[Int]) == -1 || s.indexOf('\''.asInstanceOf[Int]) == -1 - } - - def checkPubID(s: String): Boolean = { - //Console.println("checkPubID of \""+s+"\""); - if (s.length() > 0) { - val y = s.elements; - var c = ' '; - while (y.hasNext && isPubIDChar(c)) { - //Console.println(c); - c = y.next - }; - !y.hasNext - } - else - true - } - -} diff --git a/src/library/jvm/scala/xml/include/persistent/CachedFileStorage.scala b/src/library/jvm/scala/xml/include/persistent/CachedFileStorage.scala deleted file mode 100644 index 137286492a..0000000000 --- a/src/library/jvm/scala/xml/include/persistent/CachedFileStorage.scala +++ /dev/null @@ -1,123 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.xml.persistent - -import java.io.{File, FileOutputStream} -import java.nio.ByteBuffer -import java.nio.channels.Channels - -/**

- * Mutable storage of immutable xml trees. Everything is kept in memory, - * with a thread periodically checking for changes and writing to file. - * To ensure atomicity, two files are used, filename1 and '$'+filename1. - * The implementation switches between the two, deleting the older one - * after a complete dump of the database has been written. - *

- * - * @author Burak Emir - */ -abstract class CachedFileStorage(private val file1: File) -extends java.lang.Thread with scala.util.logging.Logged { - - private val file2 = new File(file1.getParent, file1.getName+"$") - - /** either equals file1 or file2, references the next file in which updates will be stored - */ - private var theFile: File = null - - private def switch = { theFile = if (theFile == file1) file2 else file1; } - - /** this storage modified since last modification check */ - protected var dirty = false - - /** period between modification checks, in milliseconds */ - protected val interval = 1000 - - /** finds and loads the storage file. subclasses should call this method - * prior to any other, but only once, to obtain the initial sequence of nodes. - */ - protected def initialNodes: Iterator[Node] = (file1.exists, file2.exists) match { - case (false,false) => - theFile = file1 - Iterator.empty - case (true, true ) if (file1.lastModified < file2.lastModified) => - theFile = file2 - load - case (true, _ ) => - theFile = file1 - load - case _ => - theFile = file2 - load - } - - /** returns an iterator over the nodes in this storage */ - def nodes: Iterator[Node] - - /** adds a node, setting this.dirty to true as a side effect */ - def += (e: Node): Unit - - /** removes a tree, setting this.dirty to true as a side effect */ - def -= (e: Node): Unit - - /* loads and parses XML from file */ - private def load: Iterator[Node] = { - import scala.io.Source - import scala.xml.parsing.ConstructingParser - log("[load]\nloading "+theFile) - val src = Source.fromFile( theFile ) - log("parsing "+theFile) - val res = ConstructingParser.fromSource(src,false).document.docElem(0) - switch - log("[load done]") - res.child.elements - } - - /** saves the XML to file */ - private def save = if (this.dirty) { - log("[save]\ndeleting "+theFile); - theFile.delete(); - log("creating new "+theFile); - theFile.createNewFile(); - val fos = new FileOutputStream(theFile) - val c = fos.getChannel() - - // @todo: optimize - val storageNode = { nodes.toList } - val w = Channels.newWriter(c, "utf-8") - XML.write(w, storageNode, "utf-8", true, null) - - log("writing to "+theFile); - - w.close - c.close - fos.close - dirty = false - switch - log("[save done]") - } - - /** run method of the thread. remember to use start() to start a thread, not run. */ - override def run = { - log("[run]\nstarting storage thread, checking every "+interval+" ms"); - while(true) { - Thread.sleep( this.interval ); - save - } - } - - /** forces writing of contents to the file, even if there has not been any update. */ - def flush = { - this.dirty = true; - save - } -} - diff --git a/src/library/jvm/scala/xml/include/persistent/IndexedStorage.scala b/src/library/jvm/scala/xml/include/persistent/IndexedStorage.scala deleted file mode 100644 index c14c88e5b1..0000000000 --- a/src/library/jvm/scala/xml/include/persistent/IndexedStorage.scala +++ /dev/null @@ -1,48 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.xml.persistent - -import scala.collection.mutable -import java.io.File - -/** indexed multiset of xml trees. The index may be an arbitrary totally - * type, especially one can construct indices by selecting parts of - * xml nodes. - */ -class IndexedStorage[A](file: File, index: Index[A]) //@todo -extends CachedFileStorage(file) { - - private var theMap: mutable.Map[A,Node] = new mutable.HashMap[A,Node]() - - super.initialNodes.foreach { x:Node => this += x } - - this.dirty = false - - def += (e: Node): Unit = synchronized { - log("added element at index '"+index(e)+"'") - dirty = true - theMap(index(e)) = e - } - - def -= (e: Node): Unit = synchronized { - log("removed element at index '"+index(e)+"'") - dirty = true - theMap -= index( e ) - } - - def nodes: Iterator[Node] = synchronized { - theMap.values - } - - def lookup(n: A): Option[Node] = theMap.get(n) - -} diff --git a/src/library/jvm/scala/xml/include/persistent/SetStorage.scala b/src/library/jvm/scala/xml/include/persistent/SetStorage.scala deleted file mode 100644 index 1391f1f76e..0000000000 --- a/src/library/jvm/scala/xml/include/persistent/SetStorage.scala +++ /dev/null @@ -1,43 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.xml.persistent - -import scala.collection.mutable -import java.io.File - -/** A persistent store with set semantics. This class allows to add and remove - * trees, but never contains two structurally equal trees. - * - * @author Burak Emir - */ -class SetStorage(file: File) extends CachedFileStorage(file) { - - private var theSet: mutable.HashSet[Node] = new mutable.HashSet[Node] - - // initialize - - { - val it = super.initialNodes - dirty = it.hasNext - for(val x <- it) { - theSet += x; - } - } - - /* forwarding methods to hashset*/ - - def += (e: Node): Unit = synchronized { this.dirty = true; theSet += e } - - def -= (e: Node): Unit = synchronized { this.dirty = true; theSet -= e } - - def nodes = synchronized { theSet.elements } - -} diff --git a/src/library/jvm/scala/xml/include/pull/XMLEventReader.scala b/src/library/jvm/scala/xml/include/pull/XMLEventReader.scala deleted file mode 100644 index bcc48af1e7..0000000000 --- a/src/library/jvm/scala/xml/include/pull/XMLEventReader.scala +++ /dev/null @@ -1,133 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - - -package scala.xml.pull - - -import java.lang.{Runnable, Thread} - -import scala.io.Source -import scala.xml.parsing.{ExternalSources, MarkupHandler, MarkupParser} - -/**

- * A pull parser that offers to view an XML document as a series of events. - * Please note that this API might change. Here's how to use this class - *

- *  import scala.xml._
- *  import scala.xml.pull._
- *  import scala.io.Source
- *
- *  object reader {
- *    val src = Source.fromString("")
- *    val er = new XMLEventReader().initialize(src)
- *
- *    def main(args: Array[String]) {
- *      Console.println(er.next)
- *      Console.println(er.next)
- *    }
- *  }
- *  
- * - * @author Burak Emir - */ -class XMLEventReader extends Iterator[XMLEvent] { - - var src:Source = null - def getSource = this.src - def initialize(src: Source): this.type = { - this.src = src - this.parserThread = new Thread(new Parser()) - this.parserThread.start() - this - } - - // -- this part of the class is for communication with the thread - var xmlEvent: XMLEvent = null - var continue: Boolean = true - - def myresume = synchronized { - while (continue) { - wait() - } - continue = true - notifyAll - } - def getAndClearEvent: XMLEvent = synchronized { - while (xmlEvent eq null) { - wait() - } - val r = xmlEvent - xmlEvent = null - r - } - def setEvent(e: XMLEvent) { - xmlEvent = e - } - - def doNotify() = synchronized { - XMLEventReader.this.continue = false - notifyAll() - while (!XMLEventReader.this.continue) wait(); - NodeSeq.Empty - } - - // iterator methods - - def next: XMLEvent = { - myresume - val r = getAndClearEvent - r - } - - def hasNext = true - - var parserThread: Thread = null - - class Parser extends MarkupHandler with MarkupParser with ExternalSources with Runnable { - - val preserveWS = true - val input = XMLEventReader.this.getSource - - override def elemStart(pos: Int, pre: String, label: String, attrs: MetaData, scope: NamespaceBinding) { - setEvent(ElemStart(pre, label, attrs, scope)); doNotify - } - - override def elemEnd(pos: Int, pre: String, label: String) { - setEvent(ElemEnd(pre, label)); doNotify - } - - final def elem(pos: Int, pre: String, label: String, attrs: MetaData, pscope: NamespaceBinding, nodes: NodeSeq): NodeSeq = - NodeSeq.Empty - - def procInstr(pos: Int, target: String, txt: String): NodeSeq = { - setEvent(ElemStart(null, "comm", null, null)); doNotify - } - - def comment(pos: Int, txt: String): NodeSeq = { - setEvent(ElemStart(null, "comm", null, null)); doNotify - } - - def entityRef(pos: Int, n: String): NodeSeq = { - setEvent(ElemStart(null, "eref", null, null)); doNotify - } - - def text(pos: Int, txt:String): NodeSeq = { - setEvent(ElemStart(null, "tex", null, null)); doNotify - } - - override def run() { - curInput = input - this.nextch - doNotify() - this.document() - } - } -} diff --git a/src/library/jvm/scala/xml/include/sax/EncodingHeuristics.scala b/src/library/jvm/scala/xml/include/sax/EncodingHeuristics.scala deleted file mode 100644 index adab470106..0000000000 --- a/src/library/jvm/scala/xml/include/sax/EncodingHeuristics.scala +++ /dev/null @@ -1,177 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.xml.include.sax - -import java.io.{IOException, InputStreamReader, InputStream} - -/** - *

- * EncodingHeuristics reads from a stream - * (which should be buffered) and attempts to guess - * what the encoding of the text in the stream is. - * Byte order marks are stripped from the stream. - * If it fails to determine the type of the encoding, - * it returns the default UTF-8. - *

- *

- * Translated from Elliotte Rusty Harold's Java source - *

- * - * @author Burak Emir - */ -object EncodingHeuristics { - - /** - *

- * This utility method ????. - *

- * - * @param in InputStream to read from. - * @return String The name of the encoding. - * @throws IOException if the stream cannot be reset back to where it was when - * the method was invoked. - */ - def readEncodingFromStream(in: InputStream): String = { - //System.err.println("EncodingHeuristics::readEncodingFromStream"); - // This may fail if there are a lot of space characters before the end - // of the encoding declaration - in.mark(1024) - var ret: String = null - try { - // lots of things can go wrong here. If any do, I just return null - // so that we'll fall back on the encoding declaration or the - // UTF-8 default - val byte1 = in.read() - val byte2 = in.read() - if (byte1 == 0xFE && byte2 == 0xFF) { - // don't reset because the byte order mark should not be included???? - ret = "UnicodeBig"; // name for big-endian???? - } - else if (byte1 == 0xFF && byte2 == 0xFE) { - // don't reset because the byte order mark should not be included???? - // will the reader throw away the byte order mark or will it return it???? - ret = "UnicodeLittle" - } - - /* In accordance with the Character Model [Character Model], - when the text format is a Unicode encoding, the XInclude - processor must fail the inclusion when the text in the - selected range is non-normalized. When transcoding characters - to a Unicode encoding from a legacy encoding, a normalizing transcoder must be used. */ - - val byte3 = in.read() - // check for UTF-8 byte order mark - if (byte1 == 0xEF && byte2 == 0xBB && byte3 == 0xBF) { - // don't reset because the byte order mark should not be included???? - // in general what happens if text document includes non-XML legal chars???? - ret = "UTF-8"; - } - - val byte4 = in.read(); - if (byte1 == 0x00 && byte2 == 0x00 && byte3 == 0xFE && byte4 == 0xFF) { - // don't reset because the byte order mark should not be included???? - ret = "UCS-4"; // right name for big-endian UCS-4 in Java 1.4???? - } - else if (byte1 == 0x00 && byte2 == 0x00 && byte3 == 0xFF && byte4 == 0xFE) { - // don't reset because the byte order mark should not be included???? - ret = "UCS-4"; // right name for little-endian UCS-4 in Java 1.4???? - } - - // no byte order mark present; first character must be - // less than sign or white space - // Let's look for less-than signs first - if (byte1 == 0x00 && byte2 == 0x00 && byte3 == 0x00 && byte4 == '<') { - in.reset() - ret = "UCS-4" // right name for big-endian UCS-4 in Java 1.4???? - } - else if (byte1 == '<' && byte2 == 0x00 && byte3 == 0x00 && byte4 == 0x00) { - in.reset() - ret = "UCS-4" // right name for little-endian UCS-4 in Java 1.4???? - } - else if (byte1 == 0x00 && byte2 == '<' && byte3 == 0x00 && byte4 == '?') { - in.reset() - ret = "UnicodeBigUnmarked" - } - else if (byte1 == '<' && byte2 == 0x00 && byte3 == '?' && byte4 == 0x00) { - in.reset() - ret = "UnicodeLittleUnmarked" - } - else if (byte1 == '<' && byte2 == '?' && byte3 == 'x' && byte4 == 'm') { - // ASCII compatible, must read encoding declaration - // 1024 bytes will be far enough to read most XML declarations - val data = new Array[Byte](1024) - data(0) = byte1.asInstanceOf[Byte] - data(1) = byte2.asInstanceOf[Byte] - data(2) = byte3.asInstanceOf[Byte] - data(3) = byte4.asInstanceOf[Byte] - val length = in.read(data, 4, 1020) + 4; - // Use Latin-1 (ISO-8859-1) because it's ASCII compatible and - // all byte sequences are legal Latin-1 sequences so I don't have - // to worry about encoding errors if I slip past the - // end of the XML/text declaration - val declaration = new String(data, 0, length, "8859_1"); - // if any of these throw a StringIndexOutOfBoundsException - // we just fall into the catch bloclk and return null - // since this can't be well-formed XML - var position = declaration.indexOf("encoding") + 8; - var c: Char = '\0' // bogus init value - // get rid of white space before equals sign - do { - c = declaration.charAt(position) - position += 1 - } while (c == ' ' || c == '\t' || c == '\r' || c == '\n') ; - if (c != '=') { // malformed - in.reset() - ret = "UTF-8" - } - // get rid of white space after equals sign - do { - c = declaration.charAt(position) - position += 1 - } while (c == ' ' || c == '\t' || c == '\r' || c == '\n') ; - var delimiter: Char = c - if (delimiter != '\'' && delimiter != '"') { // malformed - in.reset() - ret = "UTF-8" - } - // now positioned to read encoding name - val encodingName = new StringBuffer() - do { - c = declaration.charAt(position) - position += 1 - encodingName.append(c) - } while(c != delimiter) - encodingName.setLength(encodingName.length() - 1) // rm delim - in.reset() - ret = encodingName.toString() - } - else if (byte1 == 0x4C && byte2 == 0x6F && byte3 == 0xA7 && byte4 == 0x94) { - // EBCDIC compatible, must read encoding declaration - // ???? - } - - } catch { - case e: Exception => - in.reset() - ret = "UTF-8" - } - - // no XML or text declaration present - //System.err.println("exit EncodingHeuristics::readEncodingFromStream"); - - if (ret != null) - ret - else { - in.reset() - "UTF-8" - } - } -} diff --git a/src/library/jvm/scala/xml/include/sax/XIncludeFilter.scala b/src/library/jvm/scala/xml/include/sax/XIncludeFilter.scala deleted file mode 100644 index 19dc5ecead..0000000000 --- a/src/library/jvm/scala/xml/include/sax/XIncludeFilter.scala +++ /dev/null @@ -1,422 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.xml.include.sax - -import org.xml.sax.Attributes -import org.xml.sax.SAXException -import org.xml.sax.XMLReader -import org.xml.sax.EntityResolver -import org.xml.sax.Locator -import org.xml.sax.helpers.XMLReaderFactory -import org.xml.sax.helpers.XMLFilterImpl -import org.xml.sax.helpers.NamespaceSupport -import org.xml.sax.helpers.AttributesImpl - -import java.net.URL -import java.net.URLConnection -import java.net.MalformedURLException -import java.io.UnsupportedEncodingException -import java.io.IOException -import java.io.InputStream -import java.io.BufferedInputStream -import java.io.InputStreamReader -import java.util.Stack - -/** - *

- * This is a SAX filter which resolves all XInclude include elements - * before passing them on to the client application. Currently this - * class has the following known deviation from the XInclude specification: - *

- *
    - *
  1. XPointer is not supported.
  2. - *
- * - *

- * Furthermore, I would definitely use a new instance of this class - * for each document you want to process. I doubt it can be used - * successfully on multiple documents. Furthermore, I can virtually - * guarantee that this class is not thread safe. You have been - * warned. - *

- * - *

- * Since this class is not designed to be subclassed, and since - * I have not yet considered how that might affect the methods - * herein or what other protected methods might be needed to support - * subclasses, I have declared this class final. I may remove this - * restriction later, though the use-case for subclassing is weak. - * This class is designed to have its functionality extended via a - * a horizontal chain of filters, not a - * vertical hierarchy of sub and superclasses. - *

- * - *

- * To use this class: - *

- *
    - *
  1. Construct an XIncludeFilter object with a known base URL
  2. - *
  3. Pass the XMLReader object from which the raw document will - * be read to the setParent() method of this object.
  4. - *
  5. Pass your own ContentHandler object to the - * setContentHandler() method of this object. This is the - * object which will receive events from the parsed and included - * document. - *
  6. - *
  7. Optional: if you wish to receive comments, set your own - * LexicalHandler object as the value of this object's - * http://xml.org/sax/properties/lexical-handler property. - * Also make sure your LexicalHandler asks this object - * for the status of each comment using insideIncludeElement - * before doing anything with the comment. - *
  8. - *
  9. Pass the URL of the document to read to this object's - * parse() method
  10. - *
- * - *

e.g.

- *
XIncludeFilter includer = new XIncludeFilter(base);
- *  includer.setParent(parser);
- *  includer.setContentHandler(new SAXXIncluder(System.out));
- *  includer.parse(args[i]);
- *  
- *

- * translated from Elliotte Rusty Harold's Java source - * @author Burak Emir - */ -class XIncludeFilter extends XMLFilterImpl { - - final val XINCLUDE_NAMESPACE = "http://www.w3.org/2001/XInclude"; - - private val bases = new Stack[URL](); - private val locators = new Stack[Locator](); - -/* private EntityResolver resolver; - - public XIncludeFilter() { - this(null); - } - - public XIncludeFilter(EntityResolver resolver) { - this.resolver = resolver; - } */ - - - // what if this isn't called???? - // do I need to check this in startDocument() and push something - // there???? - override def setDocumentLocator(locator: Locator) { - locators.push(locator) - val base = locator.getSystemId() - try { - bases.push(new URL(base)) - } - catch { - case e:MalformedURLException => - throw new UnsupportedOperationException("Unrecognized SYSTEM ID: " + base) - } - super.setDocumentLocator(locator) - } - - - // necessary to throw away contents of non-empty XInclude elements - private var level = 0 - - /** - *

- * This utility method returns true if and only if this reader is - * currently inside a non-empty include element. (This is - * not the same as being inside the node set which replaces - * the include element.) This is primarily needed for comments - * inside include elements. It must be checked by the actual - * LexicalHandler to see whether a comment is passed or not. - *

- * - * @return boolean - */ - def insideIncludeElement(): Boolean = level != 0 - - override def startElement(uri: String, localName: String, qName: String, atts1: Attributes) { - var atts = atts1 - if (level == 0) { // We're not inside an xi:include element - - // Adjust bases stack by pushing either the new - // value of xml:base or the base of the parent - val base = atts.getValue(NamespaceSupport.XMLNS, "base") - val parentBase = bases.peek().asInstanceOf[URL] - var currentBase = parentBase - if (base != null) { - try { - currentBase = new URL(parentBase, base) - } - catch { - case e: MalformedURLException => - throw new SAXException("Malformed base URL: " - + currentBase, e) - } - } - bases.push(currentBase); - - if (uri.equals(XINCLUDE_NAMESPACE) && localName.equals("include")) { - // include external document - val href = atts.getValue("href") - // Verify that there is an href attribute - if (href==null) { - throw new SAXException("Missing href attribute") - } - - var parse = atts.getValue("parse") - if (parse == null) parse = "xml" - - if (parse.equals("text")) { - val encoding = atts.getValue("encoding"); - includeTextDocument(href, encoding); - } - else if (parse.equals("xml")) { - includeXMLDocument(href); - } - // Need to check this also in DOM and JDOM???? - else { - throw new SAXException( - "Illegal value for parse attribute: " + parse); - } - level += 1 - } - else { - if (atRoot) { - // add xml:base attribute if necessary - val attsImpl = new AttributesImpl(atts) - attsImpl.addAttribute(NamespaceSupport.XMLNS, "base", - "xml:base", "CDATA", currentBase.toExternalForm()) - atts = attsImpl - atRoot = false - } - super.startElement(uri, localName, qName, atts) - } - } - } - - override def endElement(uri: String, localName: String, qName: String) { - if (uri.equals(XINCLUDE_NAMESPACE) - && localName.equals("include")) { - level -= 1; - } - else if (level == 0) { - bases.pop() - super.endElement(uri, localName, qName) - } - } - - private var depth = 0; - - override def startDocument() { - level = 0 - if (depth == 0) super.startDocument() - depth += 1 - } - - override def endDocument() { - locators.pop() - bases.pop(); // pop the URL for the document itself - depth -= 1 - if (depth == 0) super.endDocument() - } - - // how do prefix mappings move across documents???? - override def startPrefixMapping(prefix: String , uri: String) { - if (level == 0) super.startPrefixMapping(prefix, uri) - } - - override def endPrefixMapping(prefix: String) { - if (level == 0) super.endPrefixMapping(prefix) - } - - override def characters(ch: Array[Char], start: Int, length: Int) { - if (level == 0) super.characters(ch, start, length) - } - - override def ignorableWhitespace(ch: Array[Char], start: Int, length: Int) { - if (level == 0) super.ignorableWhitespace(ch, start, length) - } - - override def processingInstruction(target: String, data: String) { - if (level == 0) super.processingInstruction(target, data) - } - - override def skippedEntity(name: String) { - if (level == 0) super.skippedEntity(name) - } - - // convenience method for error messages - private def getLocation(): String = { - var locationString = "" - val locator = locators.peek().asInstanceOf[Locator] - var publicID = "" - var systemID = "" - var column = -1 - var line = -1 - if (locator != null) { - publicID = locator.getPublicId() - systemID = locator.getSystemId() - line = locator.getLineNumber() - column = locator.getColumnNumber() - } - locationString = (" in document included from " + publicID - + " at " + systemID - + " at line " + line + ", column " + column); - - locationString - } - - /** - *

- * This utility method reads a document at a specified URL - * and fires off calls to characters(). - * It's used to include files with parse="text" - *

- * - * @param url URL of the document that will be read - * @param encoding Encoding of the document; e.g. UTF-8, - * ISO-8859-1, etc. - * @return void - * @throws SAXException if the requested document cannot - be downloaded from the specified URL - or if the encoding is not recognized - */ - private def includeTextDocument(url: String, encoding1: String) { - var encoding = encoding1 - if (encoding == null || encoding.trim().equals("")) encoding = "UTF-8"; - var source: URL = null - try { - val base = bases.peek().asInstanceOf[URL] - source = new URL(base, url) - } - catch { - case e: MalformedURLException => - val ex = new UnavailableResourceException("Unresolvable URL " + url - + getLocation()); - ex.setRootCause(e); - throw new SAXException("Unresolvable URL " + url + getLocation(), ex); - } - - try { - val uc = source.openConnection() - val in = new BufferedInputStream(uc.getInputStream()) - var encodingFromHeader = uc.getContentEncoding() - var contentType = uc.getContentType() - if (encodingFromHeader != null) - encoding = encodingFromHeader - else { - // What if file does not have a MIME type but name ends in .xml???? - // MIME types are case-insensitive - // Java may be picking this up from file URL - if (contentType != null) { - contentType = contentType.toLowerCase(); - if (contentType.equals("text/xml") - || contentType.equals("application/xml") - || (contentType.startsWith("text/") && contentType.endsWith("+xml") ) - || (contentType.startsWith("application/") && contentType.endsWith("+xml"))) { - encoding = EncodingHeuristics.readEncodingFromStream(in); - } - } - } - val reader = new InputStreamReader(in, encoding) - val c = new Array[Char](1024) - var charsRead: Int = 0 // bogus init value - do { - charsRead = reader.read(c, 0, 1024); - if (charsRead > 0) this.characters(c, 0, charsRead); - } while (charsRead != -1) ; - } - catch { - case e: UnsupportedEncodingException => - throw new SAXException("Unsupported encoding: " - + encoding + getLocation(), e); - case e: IOException => - throw new SAXException("Document not found: " - + source.toExternalForm() + getLocation(), e); - } - - } - - private var atRoot = false - - /** - *

- * This utility method reads a document at a specified URL - * and fires off calls to various ContentHandler methods. - * It's used to include files with parse="xml" - *

- * - * @param url URL of the document that will be read - * @return void - * @throws SAXException if the requested document cannot - be downloaded from the specified URL. - */ - private def includeXMLDocument(url: String) { - var source: URL = null - try { - val base = bases.peek().asInstanceOf[URL] - source = new URL(base, url) - } - catch { - case e:MalformedURLException => - val ex = new UnavailableResourceException("Unresolvable URL " + url - + getLocation()); - ex.setRootCause(e) - throw new SAXException("Unresolvable URL " + url + getLocation(), ex) - } - - try { - // make this more robust - var parser: XMLReader = null - try { - parser = XMLReaderFactory.createXMLReader() - } catch { - case e:SAXException => - try { - parser = XMLReaderFactory.createXMLReader( - "org.apache.xerces.parsers.SAXParser" - ); - } catch { - case e2: SAXException => - System.err.println("Could not find an XML parser") - } - } - if(parser != null) { - parser.setContentHandler(this) - val resolver = this.getEntityResolver() - if (resolver != null) parser.setEntityResolver(resolver); - // save old level and base - val previousLevel = level - this.level = 0 - if (bases.contains(source)) { - val e = new CircularIncludeException( - "Circular XInclude Reference to " + source + getLocation() - ); - throw new SAXException("Circular XInclude Reference", e) - } - bases.push(source) - atRoot = true - parser.parse(source.toExternalForm()) - // restore old level and base - this.level = previousLevel - bases.pop() - } - } - catch { - case e:IOException => - throw new SAXException("Document not found: " - + source.toExternalForm() + getLocation(), e) - } - - } -} diff --git a/src/library/jvm/scala/xml/include/sax/XIncluder.scala b/src/library/jvm/scala/xml/include/sax/XIncluder.scala deleted file mode 100644 index bac9c9d82e..0000000000 --- a/src/library/jvm/scala/xml/include/sax/XIncluder.scala +++ /dev/null @@ -1,201 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -// $Id$ - -package scala.xml.include.sax - -import org.xml.sax.SAXException -import org.xml.sax.SAXParseException -import org.xml.sax.ContentHandler -import org.xml.sax.EntityResolver -import org.xml.sax.helpers.XMLReaderFactory -import org.xml.sax.XMLReader -import org.xml.sax.Locator -import org.xml.sax.Attributes -import org.xml.sax.ext.LexicalHandler - -import java.io.{File, IOException, OutputStream, OutputStreamWriter, - UnsupportedEncodingException, Writer} -import java.net.{MalformedURLException, URL} -import java.util.Stack - -/** XIncluder is a SAX ContentHandler - * that writes its XML document onto an output stream after resolving - * all xinclude:include elements. - * - *

- * based on Eliotte Rusty Harold's SAXXIncluder - *

- */ -class XIncluder(outs:OutputStream, encoding:String) extends Object -with ContentHandler with LexicalHandler { - - var out = new OutputStreamWriter(outs, encoding) - - def setDocumentLocator(locator: Locator) {} - - def startDocument() { - try { - out.write("\r\n"); - } - catch { - case e:IOException => - throw new SAXException("Write failed", e) - } - } - - def endDocument() { - try { - out.flush() - } - catch { - case e:IOException => - throw new SAXException("Flush failed", e) - } - } - - def startPrefixMapping(prefix: String , uri: String) {} - - def endPrefixMapping(prefix: String) {} - - def startElement(namespaceURI: String, localName: String, qualifiedName: String, atts: Attributes) = { - try { - out.write("<" + qualifiedName); - var i = 0; while (i < atts.getLength()) { - out.write(" "); - out.write(atts.getQName(i)); - out.write("='"); - val value = atts.getValue(i); - // @todo Need to use character references if the encoding - // can't support the character - out.write(xml.Utility.escape(value)) - out.write("'"); - i += 1 - } - out.write(">") - } - catch { - case e:IOException => - throw new SAXException("Write failed", e) - } - } - - def endElement(namespaceURI: String, localName:String, qualifiedName: String) { - try { - out.write("") - } - catch { - case e: IOException => - throw new SAXException("Write failed", e) - } - } - - // need to escape characters that are not in the given - // encoding using character references???? - def characters(ch: Array[Char], start: Int, length: Int) { - try { - var i = 0; while (i < length) { - val c = ch(start+i); - if (c == '&') out.write("&"); - else if (c == '<') out.write("<"); - // This next fix is normally not necessary. - // However, it is required if text contains ]]> - // (The end CDATA section delimiter) - else if (c == '>') out.write(">"); - else out.write(c); - i = i+1; - } - } - catch { - case e: IOException => - throw new SAXException("Write failed", e); - } - } - - def ignorableWhitespace(ch: Array[Char], start: Int , length: Int) { - this.characters(ch, start, length) - } - - // do I need to escape text in PI???? - def processingInstruction(target: String, data: String) { - try { - out.write("") - } - catch { - case e:IOException => - throw new SAXException("Write failed", e) - } - } - - def skippedEntity(name: String) { - try { - out.write("&" + name + ";") - } - catch { - case e:IOException => - throw new SAXException("Write failed", e) - } - } - - // LexicalHandler methods - private var inDTD: Boolean = false - private val entities = new Stack[String]() - - def startDTD(name: String, publicID: String, systemID: String) { - inDTD = true - // if this is the source document, output a DOCTYPE declaration - if (entities.size() == 0) { - var id = "" - if (publicID != null) id = " PUBLIC \"" + publicID + "\" \"" + systemID + '"'; - else if (systemID != null) id = " SYSTEM \"" + systemID + '"'; - try { - out.write("\r\n") - } - catch { - case e:IOException => - throw new SAXException("Error while writing DOCTYPE", e) - } - } - } - def endDTD() {} - - def startEntity(name: String) { - entities.push(name) - } - - def endEntity(name: String) { - entities.pop() - } - - def startCDATA() {} - def endCDATA() {} - - // Just need this reference so we can ask if a comment is - // inside an include element or not - private var filter: XIncludeFilter = null - - def setFilter(filter: XIncludeFilter) { - this.filter = filter - } - - def comment(ch: Array[Char], start: Int, length: Int) { - if (!inDTD && !filter.insideIncludeElement()) { - try { - out.write("") - } - catch { - case e: IOException => - throw new SAXException("Write failed", e) - } - } - } -} diff --git a/src/library/scala/collection/jcl/ArrayList.scala b/src/library/scala/collection/jcl/ArrayList.scala new file mode 100644 index 0000000000..bd54d46a69 --- /dev/null +++ b/src/library/scala/collection/jcl/ArrayList.scala @@ -0,0 +1,21 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + +package scala.collection.jcl; + +/** Creates a buffer backed by a Java array list. + * + * @author Sean McDirmid + */ +class ArrayList[A](override val underlying : java.util.ArrayList[A]) extends BufferWrapper[A] { + def this() = this(new java.util.ArrayList[A]); + override def clone: ArrayList[A] = + new ArrayList[A](underlying.clone().asInstanceOf[java.util.ArrayList[A]]) +} diff --git a/src/library/scala/collection/jcl/Buffer.scala b/src/library/scala/collection/jcl/Buffer.scala new file mode 100644 index 0000000000..dfc36765d3 --- /dev/null +++ b/src/library/scala/collection/jcl/Buffer.scala @@ -0,0 +1,229 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + +package scala.collection.jcl; + +/** A mutable sequence that supports element insertion and update. + * + * @author Sean McDirmid + */ +trait Buffer[A] extends RandomAccessSeq.Mutable[A] with Ranged[Int,A] with MutableSeq[A] with Collection[A] { + final protected type SortedSelf = Buffer[A]; + + override def projection : Buffer.Projection[A] = new Buffer.Projection[A] { + override def elements = Buffer.this.elements + override def length = Buffer.this.length + override def apply(idx : Int) = Buffer.this.apply(idx) + override def transform(f : A => A) = Buffer.this.transform(f) + } + + protected class DefaultBufferIterator extends DefaultSeqIterator with BufferIterator[Int,A] { + override def set(a : A) = { + if (index == 0) throw new NoSuchElementException + Buffer.this.set(index - 1, a) + } + override def add(a : A) = { + Buffer.this.add(index, a) + } + } + override def elements : BufferIterator[Int,A] = new DefaultBufferIterator + + /** The first index of a buffer is 0. */ + override def firstKey = 0; + + /** The last index of a buffer is its size - 1. */ + override def lastKey = size - 1; + + /** Indices are compared through subtraction. */ + final def compare(k0 : Int, k1 : Int) = k0 - k1; + + /** Removes the element at index idx */ + def remove(idx : Int) = { + val i = elements; + val ret = i.seek(idx); i.remove; ret; + } + /** Removes N elements from index idx */ + def remove(idx : Int, length : Int) = { + val i = elements + i.seek(idx) + for (j <- 0.until(length)) i.remove + } + /** replaces */ + def replace(from : Int, length : Int, added : Seq[A]) = { + val min = if (length < added.length) length else added.length + val i = added.elements + var j = 0 + while (j < length && i.hasNext) { + set(from + j, i.next); j = j + 1 + } + assert(j == min) + if (i.hasNext) { + val slice = added.drop(length) + assert(!slice.isEmpty) + addAll(from + min, slice) + } else if (j < length) { + assert(length > min) + remove(from + min, length - min) + } + } + + /** Replaces the element at index "idx" with "a." + * @returns the element replaced. + */ + def set(idx : Int, a : A) : A = { + val i = elements; + val ret = i.seek(idx); i.set(a); ret; + } + + /** Equivalent to set except the replaced element is not returned. */ + def update(idx : Int, a : A) : Unit = set(idx, a); + + /** @returns always true. */ + def add(a : A) : Boolean = { + val i = elements; + while (i.hasNext) i.next; + i.add(a); + true; + } + + /** Inserts "a" into this buffer just before the element at index "idx." */ + def add(idx: Int, a: A): Unit = { + val i = elements; i.seek(idx); + i.add(a); + } + + /** Inserts all elements of that into this buffer just before + * the element at index idx. + * + * @param idx .. + * @param that .. + */ + def addAll(idx: Int, that: Iterable[A]): Unit = { + val i = elements; i.seek(idx); + for (that <- that) { + i.add(that); i.next; + } + } + + override def transform(f: A => A): Boolean = { + var changed = false; + val i = elements; + while (i.hasNext) { + val a0 = i.next; + val a1 = f(a0); + if (a0 != a1) { + i.set(a1); changed = true; + } + } + changed; + } + override def +(a : A) : this.type = super[Collection].+(a); + override def -=(a : A) = super[Collection].-=(a); + override def isEmpty = super[MutableSeq].isEmpty; + override def rangeImpl(from : Option[Int], until : Option[Int]) : Buffer[A] = new Range(from, until); + + + protected class Range(var from : Option[Int], var until : Option[Int]) extends Buffer[A] { + if (from == None && until == None) throw new IllegalArgumentException; + if (from != None && until != None && !(from.get < until.get)) throw new IllegalArgumentException; + override def add(a : A) = + if (until == None) Buffer.this.add(a); + else { + Buffer.this.add(until.get, a); + true; + } + private def translate(idx : Int) = { + if (until != None && idx > until.get) throw new IllegalArgumentException; + else if (from != None) from.get + idx; + else idx; + } + override def apply(idx : Int) : A = Buffer.this.apply(translate(idx)); + override def set(idx : Int, a : A) = Buffer.this.set(translate(idx), a); + override def add(idx : Int, a : A) = Buffer.this.add(translate(idx), a); + override def remove(idx : Int) = Buffer.this.remove(translate(idx)); + override def length = { + if (until != None) { + if (from != None) until.get - from.get; + else until.get; + } else super.length; + } + override def elements : BufferIterator[Int,A] = new RangeIterator; + class RangeIterator extends BufferIterator[Int,A] { + val underlying = Buffer.this.elements; + if (from != None) underlying.seek(from.get); + def hasNext = underlying.hasNext && + (until == None || underlying.nextIndex < until.get); + def hasPrevious = underlying.hasPrevious && + (from == None || underlying.previousIndex >= from.get); + def next = { + if (until != None && underlying.nextIndex >= until.get) throw new NoSuchElementException; + underlying.next; + } + def previous = { + if (from != None && underlying.previousIndex < from.get) throw new NoSuchElementException; + underlying.previous; + } + def add(a : A) = { + if (until != None && underlying.nextIndex > until.get) throw new NoSuchElementException; + if (from != None && underlying.previousIndex < from.get) throw new NoSuchElementException; + underlying.add(a); + if (until != None) until = Some(until.get + 1); + } + def set(a : A) = { + if (until != None && underlying.nextIndex > until.get) throw new NoSuchElementException; + if (from != None && underlying.previousIndex < from.get) throw new NoSuchElementException; + underlying.set(a); + } + def remove = { + if (until != None && underlying.nextIndex > until.get) throw new NoSuchElementException; + if (from != None && underlying.previousIndex < from.get) throw new NoSuchElementException; + underlying.remove; + } + def nextIndex = { + val ret = underlying.nextIndex; + if (until != None && ret >= until.get) throw new NoSuchElementException; + if (from != None) ret - from.get; + else ret; + } + def previousIndex = { + val ret = underlying.previousIndex; + if (from != None && ret < from.get) throw new NoSuchElementException; + if (from != None) ret - from.get; + else ret; + } + } + } + /* + protected class Map[B](f : A => B) extends super.Map[B](f) with Buffer.Projection[B] { + override def elements = Buffer.this.elements.map[B](f); + //override def apply(idx : Int) = f(MutableSeq.this.apply(idx)); + //override def size = length; + } + */ +} +object Buffer { + def apply[T](list : java.util.List[T]) = new BufferWrapper[T] { + val underlying = list + } + + trait Projection0[A] extends MutableSeq.Projection[A] with RandomAccessSeq.Projection[A] { + override def projection : Projection0[A] = this + override def elements : SeqIterator[Int,A] = new DefaultSeqIterator + + protected class MapProjection[B](f : A => B) extends super.MapProjection[B](f) with Projection0[B] { + override def projection = this + } + override def map[B](f: A => B) : Projection0[B] = new MapProjection[B](f) + } + class Projection[A] extends Collection.Projection[A] with RandomAccessSeq.MutableProjection[A] with Projection0[A] with Buffer[A] { + override def elements : BufferIterator[Int,A] = new DefaultBufferIterator + override def projection : Buffer.Projection[A] = this + } +} diff --git a/src/library/scala/collection/jcl/BufferIterator.scala b/src/library/scala/collection/jcl/BufferIterator.scala new file mode 100644 index 0000000000..bb7b79d099 --- /dev/null +++ b/src/library/scala/collection/jcl/BufferIterator.scala @@ -0,0 +1,31 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + +package scala.collection.jcl; + +/** An iterator for a buffer that supports element update and insertion. + * + * @author Sean McDirmid + */ +trait BufferIterator[K,A] extends SeqIterator[K,A] { + + /** Sets the element before this iterator's cursor to "a." + * Replaces either the last element returned by "next" or, + * if previous was called, + * the next element that would be return by "previous." + */ + def set(a: A): Unit; + + /** Inserts "a" after the iterator's cursor. + * If next was last called, "a" is inserted after the element returned. + * If previous was last called, "a" is inserted before the element returned. + */ + def add(a: A): Unit; +} diff --git a/src/library/scala/collection/jcl/BufferWrapper.scala b/src/library/scala/collection/jcl/BufferWrapper.scala new file mode 100644 index 0000000000..0472c15dea --- /dev/null +++ b/src/library/scala/collection/jcl/BufferWrapper.scala @@ -0,0 +1,52 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + +package scala.collection.jcl; + +/** Wraps Java lists. + * + * @author Sean McDirmid + */ +trait BufferWrapper[A] extends Buffer[A] with CollectionWrapper[A] { + def underlying : java.util.List[A]; + override def elements : BufferIterator[Int,A] = new IteratorWrapper(underlying.listIterator); + override def remove(idx : Int) = underlying.remove(idx).asInstanceOf[A]; + override def add(a : A) = underlying.add(a); + override def add(idx : Int, a : A) = underlying.add(idx,a); + override def addAll(idx : Int, that : Iterable[A]) = that match { + case that : CollectionWrapper[_] => underlying.addAll(idx, that.underlying); {} + case _ => super.addAll(idx, that); + } + override def indexOf(a : A) = { + val result = underlying.indexOf(a); + if (result == -1) None; + else Some(result); + } + override def apply(idx : Int) = underlying.get(idx).asInstanceOf[A]; + override def set(idx : Int, a : A) = underlying.set(idx, a).asInstanceOf[A]; + override def rangeImpl(from : Option[Int], until : Option[Int]) : Buffer[A] = new Range(from, until); + protected class Range(from : Option[Int], until : Option[Int]) extends super.Range(from,until) with BufferWrapper[A] { + val underlying = { + val fromi = if (from == None) 0 else from.get; + val toi = if (until == None) BufferWrapper.this.size else until.get; + BufferWrapper.this.underlying.subList(fromi, toi); + } + override def elements = super[BufferWrapper].elements; + } + class IteratorWrapper(underlying : java.util.ListIterator[A]) extends MutableIterator.Wrapper[A](underlying) with BufferIterator[Int,A] { + def add(a : A) = underlying.add(a); + def set(a : A) = underlying.set(a); + def hasPrevious = underlying.hasPrevious; + def previous = underlying.previous.asInstanceOf[A]; + def previousIndex = underlying.previousIndex; + def nextIndex = underlying.nextIndex; + } + override def length = underlying.size; +} diff --git a/src/library/scala/collection/jcl/Collection.scala b/src/library/scala/collection/jcl/Collection.scala new file mode 100644 index 0000000000..0df2f74f4b --- /dev/null +++ b/src/library/scala/collection/jcl/Collection.scala @@ -0,0 +1,67 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + +package scala.collection.jcl; + +object Collection { + val DEFAULT_FILTER : Any => Boolean = x => true; + trait Projection[A] extends Collection[A] with MutableIterable.Projection[A] { + override def projection = this + } +} + +/** Analogous to a Java collection. + * + * @author Sean McDirmid + */ +trait Collection[A] extends MutableIterable[A] { + /** Type-safe version of containsAll. + ** + ** @author Sean McDirmid + **/ + def hasAll(i: Iterable[A]): Boolean = i.forall(elements.has); + + /** Adds "a" to the collection, return true if "a" is actually added. */ + def add(a: A): Boolean; + + /** Adds all elements in "i" to the collection, return true if any elements are added. */ + def addAll(i: Iterable[A]): Boolean = { + var changed = false; + i.foreach(t => changed = add(t) || changed); + changed; + } + /** Operator shortcut for addAll. */ + def ++(that: Iterable[A]): this.type = { + addAll(that); this; + } + + /** removes "a" from the collection. */ + def -=(a : A) : Unit = remove(a); + + /** adds "a" from the collection. */ + def +=(t : A) : Unit = add(t); + + /** adds "a" from the collection. Useful for chaining. */ + def +(t : A) : this.type = { add(t); this; } + + /** Transforms each element of the collection in-place according to + * f. + * + * @param f + * @return true if the collection is actually updated. + */ + def transform(f: A => A): Boolean + override def projection : Collection.Projection[A] = new Collection.Projection[A] { + override def elements = Collection.this.elements + override def size = Collection.this.size + override def add(a: A): Boolean = Collection.this.add(a) + override def transform(f : A => A) = Collection.this.transform(f); + } +} diff --git a/src/library/scala/collection/jcl/CollectionWrapper.scala b/src/library/scala/collection/jcl/CollectionWrapper.scala new file mode 100644 index 0000000000..ec6a22f325 --- /dev/null +++ b/src/library/scala/collection/jcl/CollectionWrapper.scala @@ -0,0 +1,43 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + +package scala.collection.jcl; + +/** Used to wrap Java collections in Scala. + * + * @author Sean McDirmid + */ +trait CollectionWrapper[A] extends Collection[A] with IterableWrapper[A] { + /** Override to specify the collection being accessed through this wrapper. + ** Collection operations are then routed through the wrapped Java collection. + **/ + def underlying : java.util.Collection[A]; + override def has(a : A) = underlying.contains(a); + override def elements : MutableIterator[A] = super.elements; + override def size = underlying.size; + + override def hasAll(that : Iterable[A]) = that match { + case that : CollectionWrapper[_] => + val u = underlying; + u.containsAll(that.underlying); + case _ => super.hasAll(that); + } + override def add(a : A) = underlying.add(a); + override def addAll(that : Iterable[A]) = that match { + case that : CollectionWrapper[_] => underlying.addAll(that.underlying); + case _ => super.addAll(that); + } + override def toString = underlying.toString; + override def hashCode = underlying.hashCode; + override def equals(that : Any) = that match { + case that: CollectionWrapper[_] => underlying == that.underlying; + case _ => super.equals(that); + } +} diff --git a/src/library/scala/collection/jcl/Conversions.scala b/src/library/scala/collection/jcl/Conversions.scala new file mode 100644 index 0000000000..edb96322b6 --- /dev/null +++ b/src/library/scala/collection/jcl/Conversions.scala @@ -0,0 +1,17 @@ +package scala.collection.jcl + +object Conversions { + implicit def convertSet[T](set : java.util.Set[T]) = Set(set) + implicit def convertList[T](set : java.util.List[T]) = Buffer(set) + implicit def convertSortedSet[T](set : java.util.SortedSet[T]) = SortedSet(set) + implicit def convertMap[T,E](set : java.util.Map[T,E]) = Map(set) + implicit def convertSortedMap[T,E](set : java.util.SortedMap[T,E]) = SortedMap(set) + + implicit def unconvertSet[T](set : SetWrapper[T]) = set.underlying + implicit def unconvertCollection[T](set : CollectionWrapper[T]) = set.underlying + implicit def unconvertList[T](set : BufferWrapper[T]) = set.underlying + implicit def unconvertSortedSet[T](set : SortedSetWrapper[T]) = set.underlying + implicit def unconvertMap[T,E](set : MapWrapper[T,E]) = set.underlying + implicit def unconvertSortedMap[T,E](set : SortedMapWrapper[T,E]) = set.underlying + +} \ No newline at end of file diff --git a/src/library/scala/collection/jcl/HashMap.scala b/src/library/scala/collection/jcl/HashMap.scala new file mode 100644 index 0000000000..e9c156f655 --- /dev/null +++ b/src/library/scala/collection/jcl/HashMap.scala @@ -0,0 +1,21 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2006-2008, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://www.scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + +package scala.collection.jcl + +/** A map that is backed by a Java hash map. + * + * @author Sean McDirmid + */ +class HashMap[K, E](override val underlying: java.util.HashMap[K, E]) extends MapWrapper[K, E] { + def this() = this(new java.util.HashMap[K, E]) + override def clone: HashMap[K, E] = + new HashMap[K, E](underlying.clone().asInstanceOf[java.util.HashMap[K, E]]) +} diff --git a/src/library/scala/collection/jcl/HashSet.scala b/src/library/scala/collection/jcl/HashSet.scala new file mode 100644 index 0000000000..7d57278273 --- /dev/null +++ b/src/library/scala/collection/jcl/HashSet.scala @@ -0,0 +1,21 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2006-2008, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://www.scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + +package scala.collection.jcl + +/** A hash set that is backed by a Java hash set. + * + * @author Sean McDirmid + */ +class HashSet[A](override val underlying: java.util.HashSet[A]) extends SetWrapper[A] { + def this() = this(new java.util.HashSet[A]) + override def clone: HashSet[A] = + new HashSet[A](underlying.clone().asInstanceOf[java.util.HashSet[A]]) +} diff --git a/src/library/scala/collection/jcl/Hashtable.scala b/src/library/scala/collection/jcl/Hashtable.scala new file mode 100644 index 0000000000..c46c762163 --- /dev/null +++ b/src/library/scala/collection/jcl/Hashtable.scala @@ -0,0 +1,22 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2006-2008, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://www.scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + +package scala.collection.jcl + +/** A hash set that is backed by a Java hash table. + * + * @author Sean McDirmid + */ +class Hashtable[K,E](override val underlying: java.util.Hashtable[K,E]) extends MapWrapper[K,E] { + def this() = this(new java.util.Hashtable[K,E]) + + override def clone() : Hashtable[K,E] = + new Hashtable[K,E](underlying.clone().asInstanceOf[java.util.Hashtable[K,E]]) +} diff --git a/src/library/scala/collection/jcl/IdentityHashMap.scala b/src/library/scala/collection/jcl/IdentityHashMap.scala new file mode 100644 index 0000000000..c3113388e9 --- /dev/null +++ b/src/library/scala/collection/jcl/IdentityHashMap.scala @@ -0,0 +1,24 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2006-2008, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://www.scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + +package scala.collection.jcl + +/** A map that is backed by a Java identity hash map, which compares keys + * by their reference-based identity as opposed to using equals and hashCode. + * An identity hash map will often perform better than traditional hash map + * because it can utilize linear probing. + * + * @author Sean McDirmid + */ +class IdentityHashMap[K, E](override val underlying : java.util.IdentityHashMap[K, E]) extends MapWrapper[K, E] { + def this() = this(new java.util.IdentityHashMap[K, E]) + override def clone: IdentityHashMap[K, E] = + new IdentityHashMap[K, E](underlying.clone().asInstanceOf[java.util.IdentityHashMap[K, E]]) +} diff --git a/src/library/scala/collection/jcl/IterableWrapper.scala b/src/library/scala/collection/jcl/IterableWrapper.scala new file mode 100644 index 0000000000..caa31d10cf --- /dev/null +++ b/src/library/scala/collection/jcl/IterableWrapper.scala @@ -0,0 +1,32 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + +package scala.collection.jcl; + +/** A wrapper around a Java collection that only supports remove mutations. + * + * @author Sean McDirmid + */ +trait IterableWrapper[A] extends MutableIterable[A] { + def underlying: java.util.Collection[A]; + override def remove(a: A) = underlying.remove(a); + override def removeAll(that: Iterable[A]) = that match { + case that: IterableWrapper[_] => underlying.removeAll(that.underlying); + case _ => super.removeAll(that); + } + override def retainAll(that : Iterable[A]) = that match { + case that : IterableWrapper[_] => underlying.retainAll(that.underlying); + case _ => super.retainAll(that); + } + override def size = underlying.size; + override def isEmpty = underlying.isEmpty; + override def clear = underlying.clear; + override def elements : MutableIterator[A] = new MutableIterator.Wrapper[A](underlying.iterator); +} diff --git a/src/library/scala/collection/jcl/LinkedHashMap.scala b/src/library/scala/collection/jcl/LinkedHashMap.scala new file mode 100644 index 0000000000..424043ba9a --- /dev/null +++ b/src/library/scala/collection/jcl/LinkedHashMap.scala @@ -0,0 +1,22 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2006-2008, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://www.scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + +package scala.collection.jcl + +/** A map that is backed by a Java linked hash map, which fixes iteration + * order in terms of insertion order. + * + * @author Sean McDirmid + */ +class LinkedHashMap[K, E](override val underlying: java.util.LinkedHashMap[K, E]) extends MapWrapper[K, E] { + def this() = this(new java.util.LinkedHashMap[K, E]) + override def clone: LinkedHashMap[K, E] = + new LinkedHashMap[K, E](underlying.clone().asInstanceOf[java.util.LinkedHashMap[K, E]]) +} diff --git a/src/library/scala/collection/jcl/LinkedHashSet.scala b/src/library/scala/collection/jcl/LinkedHashSet.scala new file mode 100644 index 0000000000..2d0d1dddff --- /dev/null +++ b/src/library/scala/collection/jcl/LinkedHashSet.scala @@ -0,0 +1,22 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2006-2008, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://www.scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + +package scala.collection.jcl + +/** A set that is backed by a Java linked hash set, which fixes iteration + * order in terms of insertion order. + * + * @author Sean McDirmid + */ +class LinkedHashSet[A](override val underlying: java.util.LinkedHashSet[A]) extends SetWrapper[A] { + def this() = this(new java.util.LinkedHashSet[A]) + override def clone: LinkedHashSet[A] = + new LinkedHashSet[A](underlying.clone().asInstanceOf[java.util.LinkedHashSet[A]]) +} diff --git a/src/library/scala/collection/jcl/LinkedList.scala b/src/library/scala/collection/jcl/LinkedList.scala new file mode 100644 index 0000000000..a7fc726af6 --- /dev/null +++ b/src/library/scala/collection/jcl/LinkedList.scala @@ -0,0 +1,32 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + +package scala.collection.jcl; + +/** Creates a buffer backed by a Java linked list. Includes additional + * peek/poll/removeFirst/removeLast APIs that are useful in implementing + * queues and stacks. + * + * @author Sean McDirmid + */ +class LinkedList[A](override val underlying : java.util.LinkedList[A]) extends BufferWrapper[A] { + def this() = this(new java.util.LinkedList[A]); + override def elements = super[BufferWrapper].elements; + override def add(idx : Int, a : A) = + if (idx == 0) underlying.addFirst(a); + else super.add(idx, a); + //def peek = underlying.peek.asInstanceOf[A]; + //def poll = underlying.poll.asInstanceOf[A]; + //def removeFirst = underlying.removeFirst.asInstanceOf[A]; + //def removeLast = underlying.removeLast.asInstanceOf[A]; + + override def clone: LinkedList[A] = + new LinkedList[A](underlying.clone().asInstanceOf[java.util.LinkedList[A]]) +} diff --git a/src/library/scala/collection/jcl/Map.scala b/src/library/scala/collection/jcl/Map.scala new file mode 100644 index 0000000000..4dc0625b71 --- /dev/null +++ b/src/library/scala/collection/jcl/Map.scala @@ -0,0 +1,129 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + +package scala.collection.jcl; + +/** A mutable map that is compatible with Java maps. + * + * @author Sean McDirmid + */ +trait Map[K,E] extends MutableIterable[Tuple2[K,E]] with scala.collection.mutable.Map[K,E] { + override def clear() = super[MutableIterable].clear; + override def isEmpty = super[MutableIterable].isEmpty; + override def keySet : Set[K] = new KeySet; + override final def keys = keySet.elements; + /** The values of this map as a projection, which means + removals from the returned collection will remove the element from this map. + @returns a projection of this map's elements. */ + def valueSet : MutableIterable.Projection[E] = projection.map(_._2); + + override def put(key : K, elem : E) : Option[E] = throw new java.lang.AbstractMethodError + + override def ++=(that : Iterable[(K,E)]) : Unit = + that.foreach(p => put(p._1, p._2)); + + override def removeKey(key : K) : Option[E] = { + val i = elements; + while (!i.hasNext) { + val result = i.next; + if (result._1 == key) { + i.remove; + return Some(result._2); + } + } + return None; + } + override def has(pair : Tuple2[K,E]) = get(pair._1) match { + case Some(e) if e == pair._2 => true; + case _ => false; + } + override def get(key : K) = elements.find(p => p._1 == key).map(_._2); + override def update(key : K, e : E) : Unit = put(key,e); + override def +(pair : Tuple2[K,E]) : this.type = { + put(pair._1,pair._2); this; + } + override def +=(pair : Tuple2[K,E]) : Unit = put(pair._1, pair._2); + override def -(key : K) : this.type = { + removeKey(key); this; + } + override def remove(p : (K,E)) = get(p._1) match { + case Some(p._2) => this -= p._1; true + case _ => false; + } + + override def -=(key : K) : Unit = removeKey(key); + override def elements : MutableIterator[Tuple2[K,E]]; + + override def projection : Map.Projection[K,E] = new Map.Projection[K,E] { + override def elements = Map.this.elements + override def size = Map.this.size + override def get(k : K) = Map.this.get(k) + override def put(k : K, e : E) = Map.this.put(k, e) + } + /** + */ + def lense[F](f : E => F, g : F => E) : jcl.Map.Projection[K,F] = new Lense[F](f,g); + + protected class Lense[F](f : E => F, g : F => E) extends jcl.Map.Projection[K,F] { + override def elements = Map.this.elements.map(k => Tuple2(k._1, f(k._2))); + override def removeKey(key : K) = Map.this.removeKey(key).map(f); + override def put(key : K, elem : F) = Map.this.put(key, g(elem)).map(f); + override def get(key : K) = Map.this.get(key).map(f); + override def lense[G](f0 : F => G, g0 : G => F) : jcl.Map.Projection[K,G] = + Map.this.lense[G](x => f0(f(x)), y => g(g0(y))); + override def size = size0; + } + protected class KeySet extends Set[K] { + override def size = Map.this.size; + override def add(k : K) = Map.this.put(k, default(k)) == None; + override def elements = Map.this.elements.map(_._1); + override def has(k : K) = Map.this.contains(k); + } + override def filterKeys(p : K => Boolean) : Map.Projection[K,E] = new Filter(p); + + protected class Filter(p : K => Boolean) extends Map.Projection[K,E] { + override def elements = { + val i = Map.this.elements.filter(e => p(e._1)); + new MutableIterator[(K,E)] { + def next = i.next + def hasNext = i.hasNext + def remove : Unit = throw new NoSuchMethodException + } + } + override def removeKey(key : K) = { + if (!p(key)) throw new IllegalArgumentException; + Map.this.removeKey(key); + } + override def contains(key : K) = p(key) && Map.this.contains(key); + override def put(key : K, elem : E) = { + if (!p(key)) throw new IllegalArgumentException; + Map.this.put(key, elem); + } + override def get(key : K) = { + if (!p(key)) None; + else Map.this.get(key); + } + override def filterKeys(p0 : K => Boolean) : Map.Projection[K,E] = + Map.this.filterKeys(e => p(e) && p0(e)); + + override def size = size0; + } +} + +object Map { + trait MutableIterableProjection[A] extends MutableIterable.Projection[A]; + trait Projection[K,E] extends MutableIterableProjection[(K,E)] with scala.collection.Map.Projection[K,E] with Map[K,E] { + override def projection = this + override def map[B](f : ((K,E)) => B) : MutableIterable.Projection[B] = super[MutableIterableProjection].map(f); + } + def apply[T,E](map0 : java.util.Map[T,E]) = new MapWrapper[T,E] { + val underlying = map0 + } +} diff --git a/src/library/scala/collection/jcl/MapWrapper.scala b/src/library/scala/collection/jcl/MapWrapper.scala new file mode 100644 index 0000000000..7fed4d2e8f --- /dev/null +++ b/src/library/scala/collection/jcl/MapWrapper.scala @@ -0,0 +1,76 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2006-2008, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://www.scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + +package scala.collection.jcl + +/** A wrapper around a Java map. + * + * @author Sean McDirmid + */ +trait MapWrapper[K, E] extends jcl.Map[K, E] { + def underlying: java.util.Map[K, E] + override def size = underlying.size + override def isEmpty = underlying.isEmpty + override def clear() = underlying.clear + + override def put(key: K, elem: E) = { + //if (elem == null) throw new IllegalArgumentException; + val ret = underlying.put(key, elem) + if (ret == null) None else Some(ret.asInstanceOf[E]) + } + + override def get(key : K) : Option[E] = { + val ret = underlying.get(key); + if (ret == null) None else Some(ret.asInstanceOf[E]); + } + + override def ++=(that : Iterable[Tuple2[K,E]]) : Unit = that match { + case that : MapWrapper[_,_] => underlying.putAll(that.underlying); + case _ => super.++=(that) + } + + override def removeKey(key: K) = { + val ret = underlying.remove(key) + if (ret == null) None else Some(ret.asInstanceOf[E]) + } + + override def contains(key: K) = underlying.containsKey(key) + override def keySet: Set.Projection[K] = new KeySet + override def valueSet: MutableIterable.Projection[E] = new ValueSet + override def elements: MutableIterator[Tuple2[K,E]] = new IteratorWrapper + + class IteratorWrapper extends MutableIterator[Tuple2[K,E]] { + val underlying = MapWrapper.this.underlying.entrySet.iterator + def hasNext = underlying.hasNext + def remove = underlying.remove + def next = { + val next = underlying.next.asInstanceOf[java.util.Map.Entry[K,E]] + Tuple2(next.getKey.asInstanceOf[K],next.getValue.asInstanceOf[E]) + } + } + + class KeySet extends super.KeySet with SetWrapper[K] with Set.Projection[K] { + val underlying = MapWrapper.this.underlying.keySet + } + + class ValueSet extends IterableWrapper[E] with MutableIterable.Projection[E] { + override def size = MapWrapper.this.size + val underlying = MapWrapper.this.underlying.values + override def has(e : E) = MapWrapper.this.underlying.containsValue(e) + } + + override def toString = underlying.toString + override def hashCode = underlying.hashCode + + override def equals(that : Any) = that match { + case that: MapWrapper[_,_] => underlying == that.underlying + case _ => super.equals(that) + } +} diff --git a/src/library/scala/collection/jcl/MutableIterable.scala b/src/library/scala/collection/jcl/MutableIterable.scala new file mode 100644 index 0000000000..3988ed8d93 --- /dev/null +++ b/src/library/scala/collection/jcl/MutableIterable.scala @@ -0,0 +1,110 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + +package scala.collection.jcl; + +/** + * An iterable collection that supports remove operations. + * Useful for representing projections of mutable collections that where only + * the remove operation makes sense. + * + * @author Sean McDirmid + */ +trait MutableIterable[A] extends scala.Collection[A] { + /** @return true if t is in the collection. + **/ + def has(t : A ) : Boolean = elements.contains(t); + + /** @return true if t was removed from this collection. + **/ + def remove(t : A ) : Boolean = elements.remove(t); + /** @return true if any element in that was removed from this collection. + **/ + def removeAll(that : Iterable[A]) : Boolean = { + var changed = false; + that.foreach(t => changed = elements.remove(t) || changed); + changed; + } + /** Operator shortcut for removeAll. */ + def --(that : Iterable[A]) : this.type = { + removeAll(that); this; + } + + /** @return the collection that t was removed from. + */ + def -(t : A) : this.type = { remove(t); this; } + /** retain only elements in the collection that predicate p is true for. + */ + def retainOnly(p : A => Boolean) : Unit = elements.retain(p); + /** retain only elements that are also in that. + */ + def retainAll(that : Iterable[A]) : Boolean = elements.retain(s => that.exists(t => t == s)); + + /** @return the current number of elements in the collection. + */ + protected def size0 : Int = { + var count = 0; + val i = elements; + while (i.hasNext) { count = count + 1; i.next; } + count; + } + + /** clear all elements from the collection. + */ + def clear(): Unit = { + val i = elements; + while (i.hasNext) { + i.next; i.remove; + } + } + override def projection : MutableIterable.Projection[A] = new MutableIterable.Projection[A] { + override def elements = MutableIterable.this.elements + override def size = MutableIterable.this.size + override def remove(t : A ) : Boolean = MutableIterable.this.remove(t) + override def filter(p : A => Boolean) : MutableIterable.Projection[A] = super.filter(p) + } + /** The default implementation of a map over mutable iterable collections. + **/ + override def elements : MutableIterator[A]; + protected class Map[B](f : A => B) extends MutableIterable.Projection[B] { + override def elements = MutableIterable.this.elements.map(f) + override def size = MutableIterable.this.size + } + trait Filter extends MutableIterable.Projection[A] { + protected def p(a : A) : Boolean + override def has(a : A) = if (!p(a)) false else MutableIterable.this.has(a); + override def remove(a : A) = { + if (!p(a)) throw new IllegalArgumentException; + MutableIterable.this.remove(a); + } + override def filter(p0 : A => Boolean) : MutableIterable.Projection[A] = + MutableIterable.this.projection.filter(a => p(a) && p0(a)); + def elements = { + val i = MutableIterable.this.elements.filter(p); + new MutableIterator[A] { + def next = i.next + def hasNext = i.hasNext + def remove : Unit = throw new NoSuchMethodException + } + } + def size = size0; + } +} + +object MutableIterable { + trait Projection[A] extends MutableIterable[A] with Iterable.Projection[A] { + override def projection = this + override def map[B](f : A => B) : Projection[B] = new Map[B](f); + override def filter(pp : A => Boolean) : Projection[A] = new Filter { + def p(a : A) = pp(a) + } + } +} + diff --git a/src/library/scala/collection/jcl/MutableIterator.scala b/src/library/scala/collection/jcl/MutableIterator.scala new file mode 100644 index 0000000000..5f92746358 --- /dev/null +++ b/src/library/scala/collection/jcl/MutableIterator.scala @@ -0,0 +1,70 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + +package scala.collection.jcl; + +object MutableIterator { + class Wrapper[A](val underlying : java.util.Iterator[A]) extends MutableIterator[A] { + def hasNext = underlying.hasNext; + def next = underlying.next.asInstanceOf[A]; + def remove = underlying.remove; + } +} + +/** An iterator that supports the remove operation. + * These iterators wrap Java iterators, and so have the same fail fast + * behavior when dealing with concurrent modifications. + * + * @author Sean McDirmid + */ +trait MutableIterator[A] extends Iterator[A] { + def remove : Unit; + + /* filter doesnt' support remove yet. + override def filter(f : A => Boolean) : MutableIterator[A] = { + val buffered = this.buffered0; + new buffered.Filter(f); + } + */ + + override def map[B](f: A => B) : MutableIterator[B] = new Map(f); + /** A type-safe version of contains. + **/ + def has(a: A) = exists(b => a == a); + + /** Finds and removes the first instance of "a" through the iterator. + * After execution, the iterator's cursor is located where the removed + * element existed. + * + * @param a .. + * @return false if "a" is not encountered in the iterator + * and the iterator's cursor is located at the end of its elements. + */ + def remove(a: A): Boolean = { + while (hasNext) + if (next == a) { remove; return true; } + return false; + } + /** Removes all elements in the iterator that predicate "p" returns false on. + **/ + def retain(p : A => Boolean) : Boolean = { + var changed = false; + while (hasNext) + if (!p(next)) { remove; changed = true; } + changed; + } + + /** Standard implementation of a mapped iterator. **/ + class Map[B](f : A => B) extends MutableIterator[B] { + def hasNext = MutableIterator.this.hasNext + def next = f(MutableIterator.this.next) + def remove = MutableIterator.this.remove + } +} diff --git a/src/library/scala/collection/jcl/MutableSeq.scala b/src/library/scala/collection/jcl/MutableSeq.scala new file mode 100644 index 0000000000..559965c9ea --- /dev/null +++ b/src/library/scala/collection/jcl/MutableSeq.scala @@ -0,0 +1,123 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + +package scala.collection.jcl; + +/** A mutable sequence that supports the remove operation and is ordered. + * + * @author Sean McDirmid + */ +trait MutableSeq[A] extends Seq[A] with MutableIterable[A] { + protected class DefaultSeqIterator extends SeqIterator[Int,A] { + protected var index = 0 + override def hasNext = index < length + override def next = { + if (!hasNext) throw new NoSuchElementException("no lookahead") + index = index + 1 + MutableSeq.this.apply(index - 1) + } + override def hasPrevious = index > 0 + override def previous = { + if (!hasPrevious) throw new NoSuchElementException + index = index - 1 + MutableSeq.this.apply(index) + } + + override def nextIndex = index + override def previousIndex = { + if (index == 0) throw new NoSuchElementException + else index - 1 + } + def remove = throw new UnsupportedOperationException + } + override def elements : SeqIterator[Int,A] = new DefaultSeqIterator + + override def isEmpty = super[MutableIterable].isEmpty; + + override def apply(idx : Int) = elements.seek(idx); + override def projection : MutableSeq.Projection[A] = new MutableSeq.Projection[A] { + override def length = MutableSeq.this.length + override def elements = MutableSeq.this.elements + override def apply(idx : Int) = MutableSeq.this.apply(idx) + } + + /** Find the index of "a" in this sequence. + * @returns None if the "a" is not in this sequence. + */ + def indexOf(a : A) = elements.indexOf(a); + + override def length = { + var i = elements; + var sz = 0; + while (i.hasNext) { + sz = sz + 1; + i.next; + } + sz; + } + protected trait Filter extends MutableSeq.Projection[A] { + protected def p(a : A) : Boolean + override def elements : SeqIterator[Int,A] = new FilterIterator(MutableSeq.this.elements); + class FilterIterator(underlying : SeqIterator[Int,A]) extends SeqIterator[Int,A] { + private var index = 0; + protected def seekNext : Option[A] = { + while (underlying.hasNext) { + val next = underlying.next; + if (p(next)) return Some(next); + } + return None; + } + protected def seekPrevious : Option[A] = { + while (underlying.hasPrevious) { + val previous = underlying.previous; + if (p(previous)) return Some(previous); + } + return None; + } + def hasNext : Boolean = seekNext match { + case None => false; + case Some(_) => underlying.previous; true; + } + def nextIndex = index; + def next = seekNext match { + case None => throw new NoSuchElementException; + case Some(result) => index = index + 1; result; + } + def hasPrevious : Boolean = seekPrevious match { + case None => false; + case Some(_) => underlying.previous; true; + } + def previousIndex = { + if (index == 0) throw new NoSuchElementException; + index - 1; + } + def previous = seekPrevious match { + case None => throw new NoSuchElementException; + case Some(result) => index = index - 1; result; + } + def remove = underlying.remove; + } + } + protected class Map[B](f : A => B) extends super.Map[B](f) with MutableSeq.Projection[B] { + override def elements = MutableSeq.this.elements.map(f); + override def apply(idx : Int) = f(MutableSeq.this.apply(idx)); + override def size = length; + } +} +object MutableSeq { + trait Projection[A] extends MutableSeq[A] with MutableIterable.Projection[A] with Seq.Projection[A] { + override def projection = this + override def filter(pp : A => Boolean) : Projection[A] = new Filter { + override def p(a : A) = pp(a) + } + override def map[B](f : A => B) : Projection[B] = new Map[B](f); + } +} + diff --git a/src/library/scala/collection/jcl/Ranged.scala b/src/library/scala/collection/jcl/Ranged.scala new file mode 100644 index 0000000000..054d9c381d --- /dev/null +++ b/src/library/scala/collection/jcl/Ranged.scala @@ -0,0 +1,54 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + +package scala.collection.jcl; + +/** Any collection (including maps) whose keys (or elements) are ordered. + * + * @author Sean McDirmid + */ +trait Ranged[K,A] extends scala.collection.Ranged[K,A] with MutableIterable[A] { + protected type SortedSelf <: Ranged[K,A]; + + /** Comparison function that orders keys. */ + def compare(k0: K, k1: K): Int; + + /** Creates a ranged projection of this collection. Any mutations in the + * ranged projection will update this collection and vice versa. Note: keys + * are not garuanteed to be consistent between this collection and the projection. + * This is the case for buffers where indexing is relative to the projection. + * + * @param from The lower-bound (inclusive) of the ranged projection. + * None if there is no lower bound. + * @param until The upper-bound (exclusive) of the ranged projection. + * None if there is no upper bound. + */ + def rangeImpl(from: Option[K], until: Option[K]) : SortedSelf; + /** Creates a ranged projection of this collection with no upper-bound. + ** @param from The lower-bound (inclusive) of the ranged projection. + **/ + override final def from(from: K): SortedSelf = rangeImpl(Some(from), None); + /** Creates a ranged projection of this collection with no lower-bound. + ** @param until The upper-bound (exclusive) of the ranged projection. + **/ + override final def until(until: K): SortedSelf = rangeImpl(None, Some(until)); + + /** Creates a ranged projection of this collection with both a lower-bound and an upper-bound. + ** @param from The upper-bound (exclusive) of the ranged projection. + **/ + override final def range(from: K, until: K) : SortedSelf = rangeImpl(Some(from),Some(until)); + + /** A wrapper around Java comparators. */ + protected class Comparator[K <% Ordered[K]] extends java.util.Comparator[Any] { + def compare(x0 : Any, x1 : Any) = { + x0.asInstanceOf[K].compare(x1.asInstanceOf[K]); //!!! + } + } +} diff --git a/src/library/scala/collection/jcl/SeqIterator.scala b/src/library/scala/collection/jcl/SeqIterator.scala new file mode 100644 index 0000000000..5461928735 --- /dev/null +++ b/src/library/scala/collection/jcl/SeqIterator.scala @@ -0,0 +1,58 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + +package scala.collection.jcl; + +/** An iterator for a sequence that can move both forwards and backwards. + * over a set of ordered keys. + * + * @author Sean McDirmid + */ +trait SeqIterator[K,A] extends MutableIterator[A] { + /** @returns The index at the iterator's cursor. */ + def nextIndex: K; + + /** @returns The index of the element before the iterator's cursor. */ + def previousIndex: K; + + /** @return The previous element, will move the iterator's cursor backwards. */ + def previous: A; + + /** @return True if and only if the iterator's cursor is not at the beging of the iteration. */ + def hasPrevious : Boolean; + + /** Winds the iteration forward until index "idx" is found */ + def seek(idx: K) = { + while (nextIndex != idx) next; + next; + } + /** finds the index of the next "a" in this iteration. + * + * @param a .. + * @return None if "a" is not found in the iteration. + */ + def indexOf(a: A): Option[K] = { + while (hasNext) { + val ret = next; + if (ret == a) return Some(previousIndex); + } + return None; + } + + override def map[B](f: A => B) : SeqIterator[K,B] = new Map[B](f); + class Map[B](f: A => B) extends super.Map[B](f) with SeqIterator[K,B] { + override def hasPrevious = SeqIterator.this.hasPrevious; + override def previous = f(SeqIterator.this.previous); + override def previousIndex = SeqIterator.this.previousIndex; + override def nextIndex = SeqIterator.this.nextIndex; + override def map[C](g : B => C) : SeqIterator[K,C] = + SeqIterator.this.map(a => g(f(a))); + } +} diff --git a/src/library/scala/collection/jcl/Set.scala b/src/library/scala/collection/jcl/Set.scala new file mode 100644 index 0000000000..7ef9360c2a --- /dev/null +++ b/src/library/scala/collection/jcl/Set.scala @@ -0,0 +1,72 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + +package scala.collection.jcl + +/** Analogous to a Java set. + * + * @author Sean McDirmid + */ +trait Set[A] extends scala.collection.mutable.Set[A] with Collection[A] { + final def contains(a : A) = has(a) + + /** Add will return false if "a" already exists in the set. **/ + override def add(a: A): Boolean + + override def ++(i: Iterable[A]) : this.type = super[Collection].++(i) + override def --(i: Iterable[A]) : this.type = super[Collection].--(i) + override def +(t: A) : this.type = super[Collection].+(t) + override def -(t: A) : this.type = super[Collection].-(t) + override final def retain(f: A => Boolean) = retainOnly(f) + override def isEmpty = super[Collection].isEmpty + override def clear() = super.clear() + override def subsetOf(set : scala.collection.Set[A]) = set match { + case set : Set[_] => set.hasAll(this) + case set => super.subsetOf(set) + } + + override def transform(f: A => A) = { + var toAdd : List[A] = Nil + val i = elements + while (i.hasNext) { + val i0 = i.next + val i1 = f(i0) + if (i0 != i1) { + i.remove; toAdd = i1 :: toAdd + } + } + addAll(toAdd) + } + class Filter(pp : A => Boolean) extends super.Filter with Set.Projection[A] { + override def p(a : A) = pp(a) + override def retainOnly(p0 : A => Boolean): Unit = + Set.this.retainOnly(e => !p(e) || p0(e)) + override def add(a : A) = { + if (!p(a)) throw new IllegalArgumentException + else Set.this.add(a) + } + } + override def projection : Set.Projection[A] = new Set.Projection[A] { + override def add(a: A): Boolean = Set.this.add(a) + override def elements = Set.this.elements + override def size = Set.this.size + override def has(a : A) : Boolean = Set.this.has(a) + } +} + +object Set { + trait Projection[A] extends Collection.Projection[A] with Set[A] { + override def filter(p : A => Boolean) : Projection[A] = new Filter(p); + override def projection = this + } + def apply[T](set : java.util.Set[T]) = new SetWrapper[T] { + val underlying = set + } +} diff --git a/src/library/scala/collection/jcl/SetWrapper.scala b/src/library/scala/collection/jcl/SetWrapper.scala new file mode 100644 index 0000000000..5aeaf57a1b --- /dev/null +++ b/src/library/scala/collection/jcl/SetWrapper.scala @@ -0,0 +1,22 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + +package scala.collection.jcl; + +/** Used to wrap Java sets. + * + * @author Sean McDirmid + */ +trait SetWrapper[A] extends Set[A] with CollectionWrapper[A] { + def underlying: java.util.Set[A]; + override def isEmpty = super[CollectionWrapper].isEmpty; + override def clear() = super[CollectionWrapper].clear; + override def size = underlying.size; +} diff --git a/src/library/scala/collection/jcl/Sorted.scala b/src/library/scala/collection/jcl/Sorted.scala new file mode 100644 index 0000000000..7bbe49da75 --- /dev/null +++ b/src/library/scala/collection/jcl/Sorted.scala @@ -0,0 +1,46 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + +package scala.collection.jcl; + +/** Any collection (including maps) whose keys (or elements) are ordered. + * + * @author Sean McDirmid + */ +trait Sorted[K,A] extends scala.collection.Sorted[K,A] with Ranged[K,A] { + override protected type SortedSelf <: Sorted[K,A]; + /** return as a projection the set of keys in this collection */ + override def keySet : SortedSet[K]; + + /** Creates a ranged projection of this collection. Any mutations in the + * ranged projection will update this collection and vice versa. Keys + * are garuanteed to be consistent between the collection and its projection. + * + * @param from The lower-bound (inclusive) of the ranged projection. + * None if there is no lower bound. + * @param until The upper-bound (exclusive) of the ranged projection. + * None if there is no upper bound. + */ + override def rangeImpl(from: Option[K], until: Option[K]) : SortedSelf; + + /** Create a range projection of this collection with no lower-bound. + ** @param to The upper-bound (inclusive) of the ranged projection. + **/ + final override def to(to : K): SortedSelf = { + // tough! + val i = keySet.from(to).elements; + if (!i.hasNext) return this.asInstanceOf[SortedSelf]; + val next = i.next; + if (next == to) { + if (!i.hasNext) return this.asInstanceOf[SortedSelf]; + else return until(i.next); + } else return until(next); + } +} diff --git a/src/library/scala/collection/jcl/SortedMap.scala b/src/library/scala/collection/jcl/SortedMap.scala new file mode 100644 index 0000000000..be5591e7b8 --- /dev/null +++ b/src/library/scala/collection/jcl/SortedMap.scala @@ -0,0 +1,103 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + +package scala.collection.jcl; + +object SortedMap { + trait Projection[K,E] extends Map.Projection[K,E] with SortedMap[K,E] { + override def projection = this + } + def apply[T,E](map0 : java.util.SortedMap[T,E]) = new SortedMapWrapper[T,E] { + val underlying = map0 + } +} +/** A map whose keys are sorted. + * + * @author Sean McDirmid + */ +trait SortedMap[K,E] extends scala.collection.SortedMap[K,E] with Map[K,E] with Sorted[K,Tuple2[K,E]] { + final protected type SortedSelf = SortedMap[K,E]; + override def compare(k0 : K, k1 : K) : Int; + override def firstKey : K = elements.next._1; + override def lastKey : K = { + val i = elements; + var last : K = i.next._1; + while (i.hasNext) last = i.next._1; + last; + } + override def rangeImpl(from : Option[K], until : Option[K]) : SortedMap[K,E] = Range(from, until); + override def keySet : SortedSet.Projection[K] = new KeySet; + + override def projection : SortedMap.Projection[K,E] = new SortedMap.Projection[K,E] { + override def elements = SortedMap.this.elements + override def size = SortedMap.this.size + override def get(k : K) = SortedMap.this.get(k) + override def put(k : K, e : E) = SortedMap.this.put(k, e) + override def compare(k0 : K, k1 : K) = SortedMap.this.compare(k0, k1) + } + + override def lense[F](f : E => F, g : F => E) : jcl.SortedMap.Projection[K,F] = new Lense[F](f,g); + + protected class Lense[F](f : E => F, g : F => E) extends super.Lense[F](f,g) with SortedMap.Projection[K,F] { + def compare(k0 : K, k1 : K) = SortedMap.this.compare(k0, k1); + override def filterKeys(p : K => Boolean) : SortedMap.Projection[K,F] = + SortedMap.this.projection.filterKeys(p).lense(f,g); + override def lense[G](f0 : F => G, g0 : G => F) : jcl.SortedMap.Projection[K,G] = + SortedMap.this.lense[G]({x:E => f0(f(x))}, {y:G => g(g0(y))}); + override def rangeImpl(from : Option[K], until : Option[K]) = + SortedMap.this.rangeImpl(from,until).lense(f,g); + } + protected class KeySet extends super.KeySet with SortedSet.Projection[K] { + def compare(k0 : K, k1 : K) = SortedMap.this.compare(k0,k1); + override def firstKey = SortedMap.this.firstKey; + override def lastKey = SortedMap.this.lastKey; + override def rangeImpl(from : Option[K], until : Option[K]) = + SortedMap.this.rangeImpl(from,until).keySet; + } + override def filterKeys(p : K => Boolean) : SortedMap.Projection[K,E] = new Filter(p); + protected class Filter(p : K => Boolean) extends super.Filter(p) with SortedMap.Projection[K,E] { + def compare(k0 : K, k1 : K) = SortedMap.this.compare(k0,k1); + override def filterKeys(p0 : K => Boolean) : SortedMap.Projection[K,E] = + SortedMap.this.filterKeys(k => p(k) && p0(k)); + override def rangeImpl(from : Option[K], until : Option[K]) : SortedMap.Projection[K,E] = + SortedMap.this.Range(from, until).projection.filterKeys(p); + } + protected def Range(from : Option[K], until : Option[K]) : SortedMap.Projection[K,E] = new Range(from,until); + protected class Range(from : Option[K], until : Option[K]) extends super.Filter(key => { + ((from == None || (compare(from.get,key) <= 0)) && + (until == None || (compare(key,until.get) < 0))); + }) with SortedMap.Projection[K,E] { + def compare(k0 : K, k1 : K) = SortedMap.this.compare(k0,k1); + private def contains0(key : K) = + (from == None || (compare(from.get,key) <= 0)) && + (until == None || (compare(key,until.get) < 0)); + + override def contains(key : K) = SortedMap.this.contains(key) && contains0(key); + override def get(key : K) = if (!contains0(key)) None else SortedMap.this.get(key); + override def put(key : K, elem : E) = { + if (!contains0(key)) throw new IllegalArgumentException; + SortedMap.this.put(key, elem); + } + override def rangeImpl(from : Option[K], until : Option[K]) : SortedMap[K,E] = { + if (this.from != None && from == None) return rangeImpl(this.from, until); + if (this.until != None && until == None) return rangeImpl(from, this.until); + if (from != None && compare(this.from.get, from.get) > 0) return rangeImpl(this.from, until); + if (until != None && compare(this.until.get, until.get) < 0) return rangeImpl(from, this.until); + SortedMap.this.Range(from, until); + } + override def filterKeys(p : K => Boolean) : SortedMap.Projection[K,E] = new Filter(p); + protected class Filter(p : K => Boolean) extends super.Filter(p) with SortedMap.Projection[K,E] { + //def compare(k0 : K, k1 : K) = Range.this.compare(k0, k1); + override def filterKeys(p0 : K => Boolean) = Range.this.projection.filterKeys(k => p(k) && p0(k)); + override def rangeImpl(from : Option[K], until : Option[K]) : SortedMap.Projection[K,E] = + Range.this.rangeImpl(from,until).projection.filterKeys(p); + } + } +} diff --git a/src/library/scala/collection/jcl/SortedMapWrapper.scala b/src/library/scala/collection/jcl/SortedMapWrapper.scala new file mode 100644 index 0000000000..c706a4fec9 --- /dev/null +++ b/src/library/scala/collection/jcl/SortedMapWrapper.scala @@ -0,0 +1,39 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + +package scala.collection.jcl; + +/** A sorted map that wraps an underlying Java sorted map. + * + * @author Sean McDirmid + */ +trait SortedMapWrapper[K,E] extends SortedMap[K,E] with MapWrapper[K,E] { + override def underlying : java.util.SortedMap[K,E]; + /** the comparator function of this sorted map is defined in terms + * of the underlying sorted map's comparator. + */ + def compare(k0 : K, k1 : K) = underlying.comparator.compare(k0,k1); + override def firstKey = underlying.firstKey.asInstanceOf[K]; + override def lastKey = underlying.lastKey.asInstanceOf[K]; + override def keySet : SortedSet.Projection[K] = new KeySet; + override protected def Range(from : Option[K], until : Option[K]) = new Range(from,until); + protected class Range(from : Option[K], until : Option[K]) extends super.Range(from,until) with SortedMapWrapper[K,E] { + val underlying = Tuple2(from,until) match { + case Tuple2(None,None) => throw new IllegalArgumentException; + case Tuple2(Some(from),None) => SortedMapWrapper.this.underlying.tailMap(from); + case Tuple2(None,Some(until)) => SortedMapWrapper.this.underlying.headMap(until); + case Tuple2(Some(from),Some(until)) => SortedMapWrapper.this.underlying.subMap(from,until); + } + override def compare(k0 : K, k1 : K) = super[SortedMapWrapper].compare(k0, k1); + } + protected class KeySet extends super[SortedMap].KeySet with SetWrapper[K] with SortedSet.Projection[K] { + val underlying = SortedMapWrapper.this.underlying.keySet; + } +} diff --git a/src/library/scala/collection/jcl/SortedSet.scala b/src/library/scala/collection/jcl/SortedSet.scala new file mode 100644 index 0000000000..5050a1c36a --- /dev/null +++ b/src/library/scala/collection/jcl/SortedSet.scala @@ -0,0 +1,99 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + +package scala.collection.jcl; +import Predef._ + +object SortedSet { + trait Projection[A] extends Set.Projection[A] with SortedSet[A] { + override def projection = this + override def filter(p : A => Boolean) : Projection[A] = new Filter(p); + } + def apply[T](set : java.util.SortedSet[T]) = new SortedSetWrapper[T] { + val underlying = set + } + +} + +/** Analogous to a Java sorted set. + * + * @author Sean McDirmid + */ +trait SortedSet[A] extends scala.collection.SortedSet[A] with jcl.Set[A] with Sorted[A,A] { + final protected type SortedSelf = SortedSet[A]; + override def keySet = this; + def compare(a0 : A, a1 : A) : Int; + override def firstKey : A = { + val i = elements; + if (i.hasNext) i.next; + else throw new NoSuchElementException; + } + override def subsetOf(that : scala.collection.Set[A]) = super[SortedSet].subsetOf(that); + override def hasAll(that : Iterable[A]) = super[Sorted].hasAll(that.elements); + + override def lastKey : A = { + var last : A = null.asInstanceOf[A]; + val i = elements; + while (i.hasNext) last = i.next; + if (last == null) throw new NoSuchElementException; + else last; + } + override def rangeImpl(from : Option[A], until : Option[A]) : SortedSet[A] = new Range(from, until); + override def projection : SortedSet.Projection[A] = new SortedSet.Projection[A] { + override def compare(a0 : A, a1 : A) = SortedSet.this.compare(a0, a1) + override def add(a: A): Boolean = SortedSet.this.add(a) + override def elements = SortedSet.this.elements + override def size = SortedSet.this.size + override def has(a : A) : Boolean = SortedSet.this.has(a) + } + + protected class Filter(pp : A => Boolean) extends super.Filter(pp) with SortedSet.Projection[A] { + override def p(a : A) = pp(a) + def compare(a0 : A, a1 : A) : Int = SortedSet.this.compare(a0, a1); + override def filter(p0 : A => Boolean) = SortedSet.this.projection.filter(k => p(k) && p0(k)); + } + protected class Range(from : Option[A], until : Option[A]) extends Filter(key => { + (from == None || (compare(from.get,key) <= 0)) && + (until == None || (compare(key,until.get) < 0)); + }) with SortedSet.Projection[A] { + if (from == None && until == None) throw new IllegalArgumentException; + if (from != None && until != None && !(SortedSet.this.compare(from.get, until.get) < 0)) + throw new IllegalArgumentException; + //override def elements : MutableIterator[A] = + // new RangeIterator(SortedSet.this.elements.buffered0); + private def contains1(key : A) = + (from == None || (compare(from.get,key) <= 0)) && + (until == None || (compare(key,until.get) < 0)); + override def has(elem : A) = contains1(elem) && SortedSet.this.has(elem); + override def rangeImpl(from : Option[A], until : Option[A]) : SortedSet[A] = { + if (this.from != None && from == None) return rangeImpl(this.from, until); + if (this.until != None && until == None) return rangeImpl(from, this.until); + if (from != None && compare(this.from.get, from.get) > 0) return rangeImpl(this.from, until); + if (until != None && compare(this.until.get, until.get) < 0) return rangeImpl(from, this.until); + SortedSet.this.rangeImpl(from, until); + } + /* + class RangeIterator(underlying : MutableIterator[A]#Buffered) extends MutableIterator[A] { + if (from != None) + underlying.seekNext(a => compare(from.get, a) <= 0); + + private def okNext(a : A) = + if (until == None) true; + else compare(a, until.get) < 0; + + def hasNext = underlying.hasNext && okNext(underlying.peekNext); + def next = underlying.seekNext(okNext) match { + case Some(result) => underlying.next; result; + case None => throw new NoSuchElementException; + } + def remove = underlying.remove; + }*/ + } +} diff --git a/src/library/scala/collection/jcl/SortedSetWrapper.scala b/src/library/scala/collection/jcl/SortedSetWrapper.scala new file mode 100644 index 0000000000..39b066bfd7 --- /dev/null +++ b/src/library/scala/collection/jcl/SortedSetWrapper.scala @@ -0,0 +1,39 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + +package scala.collection.jcl; + +/**

+ * A wrapper around a Java sorted set. + *

+ *

+ * The comparator of the sorted set matches the comparator of this set. + *

+ * + * @author Sean McDirmid + */ +trait SortedSetWrapper[A] extends SortedSet[A] with SetWrapper[A] { + def underlying : java.util.SortedSet[A]; + /** delegates to the comparator of the underlying Java sorted set */ + override def compare(a0 : A, a1 : A) = underlying.comparator.compare(a0, a1); + override def firstKey = underlying.first.asInstanceOf[A]; + override def lastKey = underlying.last .asInstanceOf[A]; + override def rangeImpl(from : Option[A], until : Option[A]) : SortedSet[A] = new Range(from,until); + protected class Range(from : Option[A], until : Option[A]) extends super.Range(from, until) with SortedSetWrapper[A] { + val underlying = Tuple2(from,until) match { + case Tuple2(None,Some(until)) => SortedSetWrapper.this.underlying.headSet(until); + case Tuple2(Some(from),None) => SortedSetWrapper.this.underlying.tailSet(from); + case Tuple2(Some(from),Some(until)) => SortedSetWrapper.this.underlying.subSet(from,until); + case _ => throw new IllegalArgumentException; + } + override def elements : MutableIterator[A] = super[SortedSetWrapper].elements; + } + override def toString = super.toString; +} diff --git a/src/library/scala/collection/jcl/Tests.scala b/src/library/scala/collection/jcl/Tests.scala new file mode 100644 index 0000000000..a3007d8e1b --- /dev/null +++ b/src/library/scala/collection/jcl/Tests.scala @@ -0,0 +1,79 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + +package scala.collection.jcl; + +import java.lang.Integer; + +private[jcl] object Tests { + + def main(args : Array[String]) : Unit = { + hashSet; + treeSet; + treeMap; + } + + def treeSet : Unit = { + val set = new TreeSet[String]; + set + "aaa" + "bbb" + "ccc" + "ddd" + "eee" + "fff"; + Console.println(set); + val rset : SortedSet[String] = set.range("b", "e"); + Console.println(rset); + rset + "bad"; + Console.println(rset); + Console.println(set); + val fset : SortedSet[String] = rset.projection.filter(_.endsWith("d")); + Console.println(fset); + fset += "cd"; + Console.println(set); + //set.projection.map(_.length).retain(x => x == 3); + Console.println(set); + Console.println(rset); + Console.println(fset); + } + + def treeMap : Unit = { + val map = new TreeMap[String,Integer]; + map + ("bb" -> 3) + ("cc" -> 4) + ("aa" -> 2) + ("dd" -> 5); + //Console.println(map); + val rmap : SortedMap[String,Integer] = map.range("b", "d"); + rmap + ("bad" -> 10); + Console.println(rmap); + //Console.println(map); + val fmap : SortedMap[String,Integer] = rmap.projection.filterKeys(k => k.length == 2); + Console.println(fmap); + } + + def hashSet = { + val set = new HashSet[String]; + set + "hello" + "world" + "you" + "to"; + Console.println(set); + val fset = set.projection.filter(s => s.length <= 3); + Console.println(fset); + fset += "xxx"; + Console.println(set); + try { + fset += "xxxx"; + throw new Error; + } catch { + case e : IllegalArgumentException => + case _ => throw new Error; + } + //val mset : MutableIterable[Int] = set // set.projection.map(s => s.length); + //Console.println(mset); + //mset.retain(n => n < 5); + Console.println(set); + val set1 = new HashSet[String] + "1" + "2" + "3"; + set ++ (set1); + Console.println(set); + set.transform(s => "x_" + s); + Console.println(set); + } +} diff --git a/src/library/scala/collection/jcl/TreeMap.scala b/src/library/scala/collection/jcl/TreeMap.scala new file mode 100644 index 0000000000..c01584851d --- /dev/null +++ b/src/library/scala/collection/jcl/TreeMap.scala @@ -0,0 +1,24 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2006-2008, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://www.scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + +package scala.collection.jcl + +/** A sorted map that is backed by a Java tree map. + * + * @author Sean McDirmid + */ +class TreeMap[K <% Ordered[K], E] extends SortedMapWrapper[K, E] { tm => + val underlying = (new java.util.TreeMap[K, E](new Comparator[K])) + override def clone: TreeMap[K, E] = + new TreeMap[K, E] { + override val underlying = + tm.underlying.clone().asInstanceOf[java.util.TreeMap[K, E]] + } +} diff --git a/src/library/scala/collection/jcl/TreeSet.scala b/src/library/scala/collection/jcl/TreeSet.scala new file mode 100644 index 0000000000..e708349763 --- /dev/null +++ b/src/library/scala/collection/jcl/TreeSet.scala @@ -0,0 +1,26 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2006-2008, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://www.scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + +package scala.collection.jcl + +/** Creates a sorted set that is backed by an underlying Java tree set. + * Elements of the sorted set are ordered with respect to the ordered + * view bound of A. + * + * @author Sean McDirmid + */ +class TreeSet[A <% Ordered[A]] extends SortedSetWrapper[A] { ts => + val underlying = new java.util.TreeSet[A](new Comparator[A]) + override def clone: TreeSet[A] = + new TreeSet[A] { + override val underlying = + ts.underlying.clone().asInstanceOf[java.util.TreeSet[A]] + } +} diff --git a/src/library/scala/collection/jcl/WeakHashMap.scala b/src/library/scala/collection/jcl/WeakHashMap.scala new file mode 100644 index 0000000000..1d8ff4207e --- /dev/null +++ b/src/library/scala/collection/jcl/WeakHashMap.scala @@ -0,0 +1,31 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2006-2008, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://www.scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + +package scala.collection.jcl + +/**

+ * A map that is backed by a Java weak hash map, whose keys are maintained + * as weak references. + *

+ *

+ * Because keys are weak references, the garbage collector can collect + * them if they are not referred to elsewhere. + *

+ *

+ * Useful for implementing caches. + *

+ * + * @author Sean McDirmid + */ +class WeakHashMap[K, E](override val underlying: java.util.WeakHashMap[K, E]) extends MapWrapper[K, E] { + def this() = this(new java.util.WeakHashMap[K, E]) + override def clone: WeakHashMap[K, E] = + throw new CloneNotSupportedException("The underlying map doesn't implement the Cloneable interface") +} diff --git a/src/library/scala/collection/mutable/JavaMapAdaptor.scala b/src/library/scala/collection/mutable/JavaMapAdaptor.scala new file mode 100644 index 0000000000..b912057c28 --- /dev/null +++ b/src/library/scala/collection/mutable/JavaMapAdaptor.scala @@ -0,0 +1,69 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.collection.mutable + + +/** This class can be used as an adaptor to create mutable maps from + * Java classes that implementat the java.util.Map interface. + * + * @author Matthias Zenger + * @version 1.0, 21/07/2003 + * @deprecated Use scala.collection.jcl.Map(jmap) instead + */ +@deprecated class JavaMapAdaptor[A, B](jmap: java.util.Map[A, B]) extends Map[A, B] { + + def size: Int = jmap.size() + + def get(key: A): Option[B] = + if (jmap.containsKey(key)) Some(jmap.get(key).asInstanceOf[B]) else None + + override def isEmpty: Boolean = jmap.isEmpty() + + override def apply(key: A): B = jmap.get(key).asInstanceOf[B] + + override def contains(key: A): Boolean = jmap.containsKey(key) + + override def isDefinedAt(key: A) = jmap.containsKey(key) + + override def keys: Iterator[A] = new Iterator[A] { + val iter = jmap.keySet().iterator() + def hasNext = iter.hasNext() + def next = iter.next().asInstanceOf[A] + } + + override def values: Iterator[B] = new Iterator[B] { + val iter = jmap.values().iterator() + def hasNext = iter.hasNext() + def next = iter.next().asInstanceOf[B] + } + + def elements: Iterator[(A, B)] = new Iterator[(A, B)] { + val iter = jmap.keySet().iterator() + def hasNext = iter.hasNext() + def next = { + val key = iter.next().asInstanceOf[A] + (key, apply(key)) + } + } + + def update(key: A, value: B): Unit = { val x = jmap.put(key, value); } + + def -= (key: A): Unit = { val x = jmap.remove(key); } + + override def clear(): Unit = jmap.clear() + + override def clone(): Map[A, B] = { + val res = new HashMap[A, B] + res ++= this + res + } +} diff --git a/src/library/scala/collection/mutable/JavaSetAdaptor.scala b/src/library/scala/collection/mutable/JavaSetAdaptor.scala new file mode 100644 index 0000000000..f3a6f3386d --- /dev/null +++ b/src/library/scala/collection/mutable/JavaSetAdaptor.scala @@ -0,0 +1,47 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.collection.mutable + + +/** This class can be used as an adaptor to create mutable sets from + * Java classes that implement interface java.util.Set. + * + * @author Matthias Zenger + * @version 1.0, 19/09/2003 + * @deprecated Use scala.collection.jcl.Set(jmap) instead + */ +@deprecated class JavaSetAdaptor[A](jset: java.util.Set[A]) extends Set[A] { + + def size: Int = jset.size() + + override def isEmpty: Boolean = jset.isEmpty() + + def contains(elem: A): Boolean = jset.contains(elem) + + def elements: Iterator[A] = new Iterator[A] { + val iter = jset.iterator() + def hasNext = iter.hasNext() + def next = iter.next().asInstanceOf[A] + } + + def +=(elem: A): Unit = { val x = jset.add(elem); } + + def -=(elem: A): Unit = { val x = jset.remove(elem); } + + override def clear(): Unit = jset.clear() + + override def clone(): Set[A] = { + val res = new HashSet[A] + res ++= this + res + } +} diff --git a/src/library/scala/concurrent/ops.scala b/src/library/scala/concurrent/ops.scala new file mode 100644 index 0000000000..0d3c485300 --- /dev/null +++ b/src/library/scala/concurrent/ops.scala @@ -0,0 +1,78 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.concurrent + + +import java.lang.Thread + +/** The object ops ... + * + * @author Martin Odersky, Stepan Koltsov + * @version 1.0, 12/03/2003 + */ +object ops { + + /** + * @param p ... + */ + def spawn(p: => Unit) = { + val t = new Thread() { override def run() = p } + t.start() + } + + /** + * @param p ... + * @return ... + */ + def future[A](p: => A): () => A = { + val result = new SyncVar[A] + spawn { result setWithCatch p } + () => result.get + } + + /** + * @param xp ... + * @param yp ... + * @return ... + */ + def par[A, B](xp: => A, yp: => B): (A, B) = { + val y = new SyncVar[B] + spawn { y setWithCatch yp } + (xp, y.get) + } + + /** + * @param start ... + * @param end ... + * @param p ... + */ + def replicate(start: Int, end: Int)(p: Int => Unit) { + if (start == end) + () + else if (start + 1 == end) + p(start) + else { + val mid = (start + end) / 2 + spawn { replicate(start, mid)(p) } + replicate(mid, end)(p) + } + } + +/* + def parMap[a,b](f: a => b, xs: Array[a]): Array[b] = { + val results = new Array[b](xs.length); + replicate(0, xs.length) { i => results(i) = f(xs(i)) } + results + } +*/ + +} diff --git a/src/library/scala/io/BufferedSource.scala b/src/library/scala/io/BufferedSource.scala new file mode 100644 index 0000000000..99d8d036ae --- /dev/null +++ b/src/library/scala/io/BufferedSource.scala @@ -0,0 +1,98 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2008, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.io + +import java.io.InputStream +import java.nio.{ByteBuffer, CharBuffer} +import java.nio.channels.{ByteChannel, Channels, ReadableByteChannel} +import java.nio.charset.{Charset, CharsetDecoder} + +object BufferedSource { + + /** same as fromInputStream(inpStream, Charset.forName(enc), buffer_size, do_reset) */ + def fromInputStream(inpStream: InputStream, enc: String, buffer_size: Int, do_reset: () => Source): BufferedSource = + fromInputStream(inpStream, Charset.forName(enc), buffer_size, do_reset) + + /** same as fromInputStream(inpStream, charSet.newDecoder(), buffer_size, do_reset) */ + def fromInputStream(inpStream: InputStream, charSet: Charset, buffer_size: Int, do_reset: () => Source): BufferedSource = + fromInputStream(inpStream, charSet.newDecoder(), buffer_size, do_reset) + + /** constructs a BufferedSource instance from an input stream, using given decoder */ + def fromInputStream(inpStream: InputStream, decoder: CharsetDecoder, buffer_size: Int, do_reset: () => Source): BufferedSource = { + val byteChannel = Channels.newChannel(inpStream) + return new BufferedSource(byteChannel, decoder) { + val buf_size = buffer_size + override def reset = do_reset() + def close { inpStream.close } + } + } +} + +/** This object provides convenience methods to create an iterable + * representation of a source file. + * + * @author Burak Emir + * @version 1.0, 19/08/2004 + */ +abstract class BufferedSource(byteChannel: ReadableByteChannel, decoder: CharsetDecoder) extends Source { + + val buf_size: Int + + def close: Unit + + val byteBuffer = ByteBuffer.allocate(buf_size) + var charBuffer = CharBuffer.allocate(buf_size) + byteBuffer.position(byteBuffer.limit()) + charBuffer.position(charBuffer.limit()) + decoder.reset() + var endOfInput = false + + def fillBuffer() = { + byteBuffer.compact() + charBuffer.position(0) + var num_bytes = byteChannel.read(byteBuffer) + while (0 == num_bytes) { + Thread.sleep(1); // wait 1 ms for new data + num_bytes = byteChannel.read(byteBuffer) + } + num_bytes match { + case -1 => + endOfInput = true; + byteBuffer.position(0) + decoder.decode(byteBuffer, charBuffer, true) + decoder.flush(charBuffer) + case num_bytes => + endOfInput = false + byteBuffer.flip() + decoder.decode(byteBuffer, charBuffer, false) + charBuffer.flip() + } + } + override val iter = new Iterator[Char] { + var buf_char = { + fillBuffer() + if (endOfInput) ' ' else charBuffer.get() + } + def hasNext = { charBuffer.remaining() > 0 || !endOfInput} + def next = { + val c = buf_char + if (charBuffer.remaining() == 0) { + fillBuffer() + } + if (!endOfInput) { + buf_char = charBuffer.get() + } + c + } + } +} + diff --git a/src/library/scala/io/Source.scala b/src/library/scala/io/Source.scala new file mode 100644 index 0000000000..90bff94028 --- /dev/null +++ b/src/library/scala/io/Source.scala @@ -0,0 +1,400 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2008, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.io + + +import java.io.{BufferedInputStream, File, FileInputStream, InputStream, + PrintStream} +import java.nio.{ByteBuffer, CharBuffer} +import java.nio.charset.Charset +import java.net.{URI, URL} + +/** This object provides convenience methods to create an iterable + * representation of a source file. + * + * @author Burak Emir + * @version 1.0, 19/08/2004 + */ +object Source { + + val DefaultBufSize = 2048 + + val NoReset: () => Source = () => throw new UnsupportedOperationException() + + /** Creates a Source instance from the given array of bytes, + * with empty description. + * + * @param bytes ... + * @return the created Source instance. + */ + def fromBytes(bytes: Array[Byte]): Source = + fromString(new String(bytes)) + + /** Creates Source from array of bytes with given encoding, with + * empty description. + * + * @param bytes ... + * @param enc ... + * @return ... + */ + def fromBytes(bytes: Array[Byte], enc: String): Source = + fromString(new String(bytes, enc)) + + /** Creates a Source instance from a single character. + * + * @param c ... + * @return the create Source instance. + */ + def fromChar(c: Char): Source = { + val it = Iterator.single(c) + new Source { + def reset() = fromChar(c) + val iter = it + } + } + + /** creates Source from array of characters, with empty description. + * + * @param chars ... + * @return ... + */ + def fromChars(chars: Array[Char]): Source = { + val it = chars.elements + new Source { + def reset() = fromChars(chars) + val iter = it + } + } + + /** creates Source from string, with empty description. + * + * @param s ... + * @return ... + */ + def fromString(s: String): Source = { + val it = s.elements + new Source { + def reset() = fromString(s) + val iter = it + } + } + + /** creates Source from file with given name, setting its description to + * filename. + */ + def fromFile(name: String): Source = + fromFile(name, util.Properties.encodingString) + + /** creates Source from file with given name, using given encoding, setting + * its description to filename. + */ + def fromFile(name: String, enc: String): Source = + fromFile(new File(name), enc) + + /** creates Source from file with given file: URI + */ + def fromFile(uri: URI): Source = + fromFile(uri, util.Properties.encodingString) + + /** creates Source from file with given file: URI + */ + def fromFile(uri: URI, enc: String): Source = + fromFile(new File(uri), enc) + + /** creates Source from file, using default character encoding, setting its + * description to filename. + */ + def fromFile(file: File): Source = + fromFile(file, util.Properties.encodingString, Source.DefaultBufSize) + + /** same as fromFile(file, enc, Source.DefaultBufSize) + */ + def fromFile(file: File, enc: String): Source = + fromFile(file, enc, Source.DefaultBufSize) + + /** Creates Source from file, using given character encoding, + * setting its description to filename. Input is buffered in a buffer of + * size bufferSize. + */ + def fromFile(file: File, enc: String, bufferSize: Int): Source = { + val inpStream = new FileInputStream(file) + val size = if (bufferSize > 0) bufferSize else Source.DefaultBufSize + setFileDescriptor(file, + BufferedSource.fromInputStream(inpStream, enc, size, { () => fromFile(file, enc, size)})) + } + + /** This method sets the descr property of the given source to a string of the form "file:"+path + * @param file the file whose path we want to describe + * @param s the source whose property we set + * @return s + */ + private def setFileDescriptor(file: File, s: Source): Source = { + s.descr = new StringBuilder("file:").append(file.getAbsolutePath()).toString(); + s + } + + /** + * @param s ... + * @return ... + * @deprecated use fromURL(s, enc) + */ + def fromURL(s: String): Source = + fromURL(new URL(s)) + + /** same as fromURL(new URL(s), enc) + */ + def fromURL(s: String, enc:String): Source = + fromURL(new URL(s), enc) + + /** + * @param url ... + * @return ... + * @deprecated use fromURL(url, enc) + */ + def fromURL(url: URL): Source = { + val it = new Iterator[Char] { + var data: Int = _ + def hasNext = {data != -1} + def next = {val x = data.asInstanceOf[Char]; data = bufIn.read(); x} + val in = url.openStream() + val bufIn = new BufferedInputStream(in) + data = bufIn.read() + } + val s = new Source { + def reset() = fromURL(url) + val iter = it + } + s.descr = url.toString() + s + } + + /** same as fromInputStream(url.openStream(), enc) + */ + def fromURL(url: URL, enc:String): Source = + fromInputStream(url.openStream(), enc) + + /** reads data from istream into a byte array, and calls + * fromBytes with given encoding enc. + * If maxlen is given, reads not more bytes than maxlen; + * if maxlen was not given, or was <= 0, then + * whole istream is read and closed afterwards. + * + * @param istream the input stream from which to read + * @param enc the encoding to apply to the bytes + * @param maxlen optionally, a positive int specifying maximum number of bytes to read + */ + @deprecated def fromInputStream(istream: InputStream, enc: String, maxlen: Option[Int]): Source = { + val limit = maxlen match { case Some(i) => i; case None => 0 } + val bi = new BufferedInputStream(istream, Source.DefaultBufSize) + val bytes = new collection.mutable.ArrayBuffer[Byte]() + var b = 0 + var i = 0 + while( {b = bi.read; i += 1; b} != -1 && (limit <= 0 || i < limit)) { + bytes += b.toByte; + } + if(limit <= 0) bi.close + fromBytes(bytes.toArray, enc) + } + + /** same as BufferedSource.fromInputStream(is, enc, Source.DefaultBufSize) + */ + def fromInputStream(is: InputStream, enc: String): Source = + BufferedSource.fromInputStream(is, enc, Source.DefaultBufSize, { () => fromInputStream(is, enc) }) + + /** same as BufferedSource.fromInputStream(is, "utf-8", Source.DefaultBufSize) */ + def fromInputStream(is: InputStream): Source = + BufferedSource.fromInputStream(is, "utf-8", Source.DefaultBufSize, { () => fromInputStream(is) }) + +} + +/** The class Source implements an iterable representation + * of source files. Calling method reset returns an identical, + * resetted source. + * + * @author Burak Emir + * @version 1.0 + */ +abstract class Source extends Iterator[Char] { + + // ------ protected values + + /** the actual iterator */ + protected val iter: Iterator[Char] + + protected var cline = 1 + protected var ccol = 1 + + // ------ public values + + /** position of last character returned by next*/ + var pos = 0 + + /** the last character returned by next. + * the value before the first call to next is undefined. + */ + var ch: Char = _ + + /** description of this source, default empty */ + var descr: String = "" + + var nerrors = 0 + var nwarnings = 0 + + /** default col increment for tabs '\t', set to 4 initially + */ + var tabinc = 4 + + // + // -- methods + // + + /** convenience method, returns given line (not including newline) + * from Source. + * + * @param line the line index, first line is 1 + * @return the character string of the specified line. + * @throws scala.compat.Platform.IllegalArgumentException + * + */ + def getLine(line: Int): String = { // faster than getLines.drop(line).next + // todo: should @throws scala.compat.Platform.IndexOutOfBoundsException + if (line < 1) throw new IllegalArgumentException(line.toString); + val buf = new StringBuilder() + val it = reset + var i = 0 + + while (it.hasNext && i < (line-1)) + if ('\n' == it.next) + i += 1; + + if (!it.hasNext) // this should not happen + throw new IllegalArgumentException( + "line " + line + " does not exist" + ); + + var ch = it.next + while (it.hasNext && '\n' != ch) { + buf append ch + ch = it.next + } + + if ('\n' != ch) + buf append ch + + val res = buf.toString() + buf setLength 0 // hopefully help collector to deallocate StringBuilder + res + } + + /** returns an iterator who returns lines (including newline character). + * a line ends in \n. + */ + def getLines: Iterator[String] = new Iterator[String] { + val buf = new StringBuilder + def next = { + var ch = iter.next + while(ch != '\n' && iter.hasNext) { + buf append ch + ch = iter.next + } + buf.append(ch) + val res = buf.toString() + buf setLength 0 // clean things up for next call of "next" + res + } + def hasNext = iter.hasNext + } + /** Returns true if this source has more characters. + */ + def hasNext = iter.hasNext + + /** returns next character and has the following side-effects: updates + * position (ccol and cline) and assigns the character to ch + */ + def next = { + ch = iter.next + pos = Position.encode(cline,ccol) + ch match { + case '\n' => + ccol = 1 + cline += 1 + case '\t' => + ccol += tabinc + case _ => + ccol += 1 + } + ch + } + + /** Reports an error message to console. + * + * @param pos ... + * @param msg the error message to report + */ + def reportError(pos: Int, msg: String) { + reportError(pos, msg, java.lang.System.out) + } + + /** Reports an error message to the output stream out. + * + * @param pos ... + * @param msg the error message to report + * @param out ... + */ + def reportError(pos: Int, msg: String, out: PrintStream) { + nerrors = nerrors + 1 + report(pos, msg, out) + } + + /** + * @param pos ... + * @param msg the error message to report + * @param out ... + */ + def report(pos: Int, msg: String, out: PrintStream) { + val buf = new StringBuilder + val line = Position.line(pos) + val col = Position.column(pos) + buf.append(descr + ":" + line + ":" + col + ": " + msg) + buf.append(getLine(line)) + var i = 1 + while (i < col) { + buf.append(' ') + i += 1 + } + buf.append('^') + out.println(buf.toString) + } + + /** Reports a warning message to java.lang.System.out. + * + * @param pos ... + * @param msg the warning message to report + */ + def reportWarning(pos: Int, msg: String) { + reportWarning(pos, msg, java.lang.System.out) + } + + /** + * @param pos ... + * @param msg the warning message to report + * @param out ... + */ + def reportWarning(pos: Int, msg: String, out: PrintStream) { + nwarnings = nwarnings + 1 + report(pos, "warning! " + msg, out) + } + + /** the actual reset method */ + def reset(): Source + +} diff --git a/src/library/scala/reflect/BeanInfo.scala b/src/library/scala/reflect/BeanInfo.scala new file mode 100644 index 0000000000..a5ea0fb975 --- /dev/null +++ b/src/library/scala/reflect/BeanInfo.scala @@ -0,0 +1,22 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2008, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + +package scala.reflect + +/**

+ * This attribute indicates that a JavaBean-compliant BeanInfo + * class should be generated for this attributed Scala class. + * A val becomes a read-only property. A var becomes a read-write + * property. A def becomes a method. + *

+ * + * @author Ross Judson (rjudson@managedobjects.com) + */ +class BeanInfo extends Annotation diff --git a/src/library/scala/reflect/BeanProperty.scala b/src/library/scala/reflect/BeanProperty.scala new file mode 100644 index 0000000000..4a09578df9 --- /dev/null +++ b/src/library/scala/reflect/BeanProperty.scala @@ -0,0 +1,33 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.reflect + +/**

+ * This attribute adds a setter and a getter method, following the + * Java Bean convention (first letter of the property is capitalized) + * used by popular Java web frameworks. For example: + *

+ *    @BeanProperty
+ *    var status = ""
+ *

+ * adds the following methods to the generated code + *

+ *    def setStatus(s: String) { this.status = s }
+ *    def getStatus: String = this.status
+ *  
+ *

+ * However, you cannot call setStatus from + * Scala, + * you should use the normal Scala access and assignment. + *

+ */ +class BeanProperty extends Annotation diff --git a/src/library/scala/reflect/ScalaBeanInfo.scala b/src/library/scala/reflect/ScalaBeanInfo.scala new file mode 100644 index 0000000000..f8ea948818 --- /dev/null +++ b/src/library/scala/reflect/ScalaBeanInfo.scala @@ -0,0 +1,47 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2008, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + +package scala.reflect + +/** Provides some simple runtime processing necessary to create + * JavaBean descriptors for Scala entities. The compiler creates + * subclasses of this class automatically when the BeanInfo annotation is + * attached to a class. + * + * @author Ross Judson (rjudson@managedobjects.com) + */ +abstract class ScalaBeanInfo(clazz: java.lang.Class[_], + props: Array[String], + methods: Array[String]) extends java.beans.SimpleBeanInfo { + + import java.beans._ + + private val pd = new Array[PropertyDescriptor](props.length / 3) + private val md = + for (m <- clazz.getMethods if methods.exists(_ == m.getName)) + yield new MethodDescriptor(m) + + init + + override def getPropertyDescriptors() = pd + override def getMethodDescriptors() = md + + // override def getAdditionalBeanInfo() = Array(Introspector getBeanInfo clazz.getSuperclass) + + private def init { + var i = 0; + while (i < props.length) { + pd(i/3) = new PropertyDescriptor(props(i), clazz, props(i+1), props(i+2)) + i = i + 3; + } + } + +} + diff --git a/src/library/scala/runtime/BooleanRef.java b/src/library/scala/runtime/BooleanRef.java new file mode 100644 index 0000000000..e7c2467329 --- /dev/null +++ b/src/library/scala/runtime/BooleanRef.java @@ -0,0 +1,21 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2008, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.runtime; + + +public class BooleanRef implements java.io.Serializable { + private static final long serialVersionUID = -5730524563015615974L; + + public boolean elem; + public BooleanRef(boolean elem) { this.elem = elem; } + public String toString() { return "" + elem; } +} diff --git a/src/library/scala/runtime/BoxedUnit.java b/src/library/scala/runtime/BoxedUnit.java new file mode 100644 index 0000000000..fe6a4b9265 --- /dev/null +++ b/src/library/scala/runtime/BoxedUnit.java @@ -0,0 +1,33 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2008, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.runtime; + + +public final class BoxedUnit implements java.io.Serializable { + private static final long serialVersionUID = 8405543498931817370L; + + public final static BoxedUnit UNIT = new BoxedUnit(); + + private BoxedUnit() { } + + public boolean equals(java.lang.Object other) { + return this == other; + } + + public int hashCode() { + return 0; + } + + public String toString() { + return "()"; + } +} diff --git a/src/library/scala/runtime/BoxesRunTime.java b/src/library/scala/runtime/BoxesRunTime.java new file mode 100644 index 0000000000..a8e0549449 --- /dev/null +++ b/src/library/scala/runtime/BoxesRunTime.java @@ -0,0 +1,845 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.runtime; + +/** An object (static class) that defines methods used for creating, + * reverting, and calculating with, boxed values. There are four classes + * of methods in this object: + * - High-performance value boxing methods that feed from a pre- + * computed map of instances for the most common instanciations. + * - Convenience unboxing methods returning default value on null. + * - The generalised comparison method to be used when an object may + * be a boxed value. + * - Standard value operators for boxed number and quasi-number values. + * + * @author Gilles Dubochet + * @author Martin Odersky + * @contributor Stepan Koltsov + * @version 2.0 */ +public class BoxesRunTime { + + private static final int CHAR = 0, BYTE = 1, SHORT = 2, INT = 3, LONG = 4, FLOAT = 5, DOUBLE = 6, OTHER = 7; + + private static int typeCode(Object a) { + if (a instanceof Integer) return INT; + if (a instanceof Character) return CHAR; + if (a instanceof Long) return LONG; + if (a instanceof Double) return DOUBLE; + if (a instanceof Float) return FLOAT; + if (a instanceof Byte) return BYTE; + if (a instanceof Short) return SHORT; + return OTHER; + } + +/* BOXING ... BOXING ... BOXING ... BOXING ... BOXING ... BOXING ... BOXING ... BOXING */ + + private static int charLowBound = 0; + private static int charUpBound = 255; + private static Character[] charCache = new Character[charUpBound - charLowBound + 1]; + + private static int byteLowBound = -128; + private static int byteUpBound = 127; + private static Byte[] byteCache = new Byte[byteUpBound - byteLowBound + 1]; + + private static int shortLowBound = -128; + private static int shortUpBound = 127; + private static Short[] shortCache = new Short[shortUpBound - shortLowBound + 1]; + + private static int intLowBound = -128; + private static int intUpBound = 1024; + private static Integer[] intCache = new Integer[intUpBound - intLowBound + 1]; + + private static int longLowBound = -128; + private static int longUpBound = 1024; + private static Long[] longCache = new Long[longUpBound - longLowBound + 1]; + + static { + int idx = 0; + while (idx <= charUpBound - charLowBound) { + charCache[idx] = new Character((char)(idx + charLowBound)); + idx = idx + 1; + } + idx = 0; + while (idx <= byteUpBound - byteLowBound) { + byteCache[idx] = new Byte((byte)(idx + byteLowBound)); + idx = idx + 1; + } + idx = 0; + while (idx <= shortUpBound - shortLowBound) { + shortCache[idx] = new Short((short)(idx + shortLowBound)); + idx = idx + 1; + } + idx = 0; + while (idx <= intUpBound - intLowBound) { + intCache[idx] = new Integer((int)(idx + intLowBound)); + idx = idx + 1; + } + idx = 0; + while (idx <= longUpBound - longLowBound) { + longCache[idx] = new Long((long)(idx + longLowBound)); + idx = idx + 1; + } + } + + public static Boolean boxToBoolean(boolean b) { + return b ? Boolean.TRUE : Boolean.FALSE; + } + + public static Character boxToCharacter(char c) { + if (c >= charLowBound && c <= charUpBound) + return charCache[(int)c - charLowBound]; + return new Character(c); + } + + public static Byte boxToByte(byte b) { + if (b >= byteLowBound && b <= byteUpBound) + return byteCache[(int)b - byteLowBound]; + return new Byte(b); + } + + public static Short boxToShort(short s) { + if (s >= shortLowBound && s <= shortUpBound) + return shortCache[(int)s - shortLowBound]; + return new Short(s); + } + + public static Integer boxToInteger(int i) { + if (i >= intLowBound && i <= intUpBound) + return intCache[(int)i - intLowBound]; + return new Integer(i); + } + + public static Long boxToLong(long l) { + if (l >= longLowBound && l <= longUpBound) + return longCache[(int)l - longLowBound]; + return new Long(l); + } + + public static Float boxToFloat(float f) { + return new Float(f); + } + + public static Double boxToDouble(double d) { + return new Double(d); + } + +/* UNBOXING ... UNBOXING ... UNBOXING ... UNBOXING ... UNBOXING ... UNBOXING ... UNBOXING */ + + public static boolean unboxToBoolean(Object b) { + return b == null ? false : ((Boolean)b).booleanValue(); + } + + public static char unboxToChar(Object c) { + return c == null ? 0 : ((Character)c).charValue(); + } + + public static byte unboxToByte(Object b) { + return b == null ? 0 : ((Byte)b).byteValue(); + } + + public static short unboxToShort(Object s) { + return s == null ? 0 : ((Short)s).shortValue(); + } + + public static int unboxToInt(Object i) { + return i == null ? 0 : ((Integer)i).intValue(); + } + + public static long unboxToLong(Object l) { + return l == null ? 0 : ((Long)l).longValue(); + } + + public static float unboxToFloat(Object f) { + return f == null ? 0.0f : ((Float)f).floatValue(); + } + + public static double unboxToDouble(Object d) { + return d == null ? 0.0d : ((Double)d).doubleValue(); + } + + /* + public static boolean unboxToBoolean(Object b) { + if (b == null) + throw new ClassCastException("null is no Boolean value"); + return ((Boolean)b).booleanValue(); + } + + public static char unboxToChar(Object c) { + if (c == null) + throw new ClassCastException("null is no Char value"); + return ((Character)c).charValue(); + } + + public static byte unboxToByte(Object b) { + if (b == null) + throw new ClassCastException("null is no Byte value"); + return ((Byte)b).byteValue(); + } + + public static short unboxToShort(Object s) { + if (s == null) + throw new ClassCastException("null is no Short value"); + return ((Short)s).shortValue(); + } + + public static int unboxToInt(Object i) { + if (i == null) + throw new ClassCastException("null is no Int value"); + return ((Integer)i).intValue(); + } + + public static long unboxToLong(Object l) { + if (l == null) + throw new ClassCastException("null is no Long value"); + return ((Long)l).longValue(); + } + + public static float unboxToFloat(Object f) { + if (f == null) + throw new ClassCastException("null is no Float value"); + return ((Float)f).floatValue(); + } + + public static double unboxToDouble(Object d) { + if (d == null) + throw new ClassCastException("null is no Double value"); + return ((Double)d).doubleValue(); + } + */ + +/* COMPARISON ... COMPARISON ... COMPARISON ... COMPARISON ... COMPARISON ... COMPARISON */ + + /** A rich implementation of the equals method that overrides the + * default equals because Java's boxed primitives are utterly broken. This equals + * is inserted instead of a normal equals by the Scala compiler (in the + * ICode phase, method genEqEqPrimitive) only when either + * side of the comparison is a subclass of AnyVal, of + * java.lang.Number, of java.lang.Character or + * is exactly Any or AnyRef. */ + public static boolean equals(Object a, Object b) { + if (a == null || b == null) + return a == b; + if (a.equals(b)) + return true; + if (a instanceof Number || a instanceof Character || b instanceof Number || b instanceof Character) { + int acode = typeCode(a); + int bcode = typeCode(b); + int maxcode = (acode < bcode) ? bcode : acode; + if (maxcode <= INT) { + int aa = (acode == CHAR) ? ((Character) a).charValue() : ((Number) a).intValue(); + int bb = (bcode == CHAR) ? ((Character) b).charValue() : ((Number) b).intValue(); + return aa == bb; + } + if (maxcode <= LONG) { + long aa = (acode == CHAR) ? ((Character) a).charValue() : ((Number) a).longValue(); + long bb = (bcode == CHAR) ? ((Character) b).charValue() : ((Number) b).longValue(); + return aa == bb; + } + if (maxcode <= FLOAT) { + float aa = (acode == CHAR) ? ((Character) a).charValue() : ((Number) a).floatValue(); + float bb = (bcode == CHAR) ? ((Character) b).charValue() : ((Number) b).floatValue(); + return aa == bb; + } + if (maxcode <= DOUBLE) { + double aa = (acode == CHAR) ? ((Character) a).charValue() : ((Number) a).doubleValue(); + double bb = (bcode == CHAR) ? ((Character) b).charValue() : ((Number) b).doubleValue(); + return aa == bb; + } + return b.equals(a); + } + return false; + } + +/* OPERATORS ... OPERATORS ... OPERATORS ... OPERATORS ... OPERATORS ... OPERATORS ... OPERATORS ... OPERATORS */ + + /** arg1 + arg2 */ + public static Object add(Object arg1, Object arg2) throws NoSuchMethodException { + int code1 = typeCode(arg1); + int code2 = typeCode(arg2); + int maxcode = (code1 < code2) ? code2 : code1; + if (maxcode <= INT) { + int val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).intValue(); + int val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).intValue(); + return boxToInteger(val1 + val2); + } + if (maxcode <= LONG) { + long val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).longValue(); + long val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).longValue(); + return boxToLong(val1 + val2); + } + if (maxcode <= FLOAT) { + float val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).floatValue(); + float val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).floatValue(); + return boxToFloat(val1 + val2); + } + if (maxcode <= DOUBLE) { + double val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).doubleValue(); + double val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).doubleValue(); + return boxToDouble(val1 + val2); + } + throw new NoSuchMethodException(); + } + + /** arg1 - arg2 */ + public static Object subtract(Object arg1, Object arg2) throws NoSuchMethodException { + int code1 = typeCode(arg1); + int code2 = typeCode(arg2); + int maxcode = (code1 < code2) ? code2 : code1; + if (maxcode <= INT) { + int val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).intValue(); + int val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).intValue(); + return boxToInteger(val1 - val2); + } + if (maxcode <= LONG) { + long val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).longValue(); + long val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).longValue(); + return boxToLong(val1 - val2); + } + if (maxcode <= FLOAT) { + float val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).floatValue(); + float val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).floatValue(); + return boxToFloat(val1 - val2); + } + if (maxcode <= DOUBLE) { + double val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).doubleValue(); + double val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).doubleValue(); + return boxToDouble(val1 - val2); + } + throw new NoSuchMethodException(); + } + + /** arg1 * arg2 */ + public static Object multiply(Object arg1, Object arg2) throws NoSuchMethodException { + int code1 = typeCode(arg1); + int code2 = typeCode(arg2); + int maxcode = (code1 < code2) ? code2 : code1; + if (maxcode <= INT) { + int val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).intValue(); + int val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).intValue(); + return boxToInteger(val1 * val2); + } + if (maxcode <= LONG) { + long val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).longValue(); + long val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).longValue(); + return boxToLong(val1 * val2); + } + if (maxcode <= FLOAT) { + float val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).floatValue(); + float val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).floatValue(); + return boxToFloat(val1 * val2); + } + if (maxcode <= DOUBLE) { + double val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).doubleValue(); + double val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).doubleValue(); + return boxToDouble(val1 * val2); + } + throw new NoSuchMethodException(); + } + + /** arg1 / arg2 */ + public static Object divide(Object arg1, Object arg2) throws NoSuchMethodException { + int code1 = typeCode(arg1); + int code2 = typeCode(arg2); + int maxcode = (code1 < code2) ? code2 : code1; + if (maxcode <= INT) { + int val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).intValue(); + int val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).intValue(); + return boxToInteger(val1 / val2); + } + if (maxcode <= LONG) { + long val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).longValue(); + long val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).longValue(); + return boxToLong(val1 / val2); + } + if (maxcode <= FLOAT) { + float val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).floatValue(); + float val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).floatValue(); + return boxToFloat(val1 / val2); + } + if (maxcode <= DOUBLE) { + double val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).doubleValue(); + double val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).doubleValue(); + return boxToDouble(val1 / val2); + } + throw new NoSuchMethodException(); + } + + /** arg1 % arg2 */ + public static Object takeModulo(Object arg1, Object arg2) throws NoSuchMethodException { + int code1 = typeCode(arg1); + int code2 = typeCode(arg2); + int maxcode = (code1 < code2) ? code2 : code1; + if (maxcode <= INT) { + int val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).intValue(); + int val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).intValue(); + return boxToInteger(val1 % val2); + } + if (maxcode <= LONG) { + long val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).longValue(); + long val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).longValue(); + return boxToLong(val1 % val2); + } + if (maxcode <= FLOAT) { + float val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).floatValue(); + float val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).floatValue(); + return boxToFloat(val1 % val2); + } + if (maxcode <= DOUBLE) { + double val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).doubleValue(); + double val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).doubleValue(); + return boxToDouble(val1 % val2); + } + throw new NoSuchMethodException(); + } + + /** arg1 >> arg2 */ + public static Object shiftSignedRight(Object arg1, Object arg2) throws NoSuchMethodException { + int code1 = typeCode(arg1); + int code2 = typeCode(arg2); + if (code1 <= INT) { + int val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).intValue(); + if (code2 <= INT) { + int val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).intValue(); + return boxToInteger(val1 >> val2); + } + if (code2 <= LONG) { + long val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).longValue(); + return boxToInteger(val1 >> val2); + } + } + if (code1 <= LONG) { + long val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).longValue(); + if (code2 <= INT) { + int val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).intValue(); + return boxToLong(val1 >> val2); + } + if (code2 <= LONG) { + long val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).longValue(); + return boxToLong(val1 >> val2); + } + } + throw new NoSuchMethodException(); + } + + /** arg1 << arg2 */ + public static Object shiftSignedLeft(Object arg1, Object arg2) throws NoSuchMethodException { + int code1 = typeCode(arg1); + int code2 = typeCode(arg2); + if (code1 <= INT) { + int val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).intValue(); + if (code2 <= INT) { + int val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).intValue(); + return boxToInteger(val1 << val2); + } + if (code2 <= LONG) { + long val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).longValue(); + return boxToInteger(val1 << val2); + } + } + if (code1 <= LONG) { + long val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).longValue(); + if (code2 <= INT) { + int val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).intValue(); + return boxToLong(val1 << val2); + } + if (code2 <= LONG) { + long val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).longValue(); + return boxToLong(val1 << val2); + } + } + throw new NoSuchMethodException(); + } + + /** arg1 >>> arg2 */ + public static Object shiftLogicalRight(Object arg1, Object arg2) throws NoSuchMethodException { + int code1 = typeCode(arg1); + int code2 = typeCode(arg2); + if (code1 <= INT) { + int val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).intValue(); + if (code2 <= INT) { + int val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).intValue(); + return boxToInteger(val1 >>> val2); + } + if (code2 <= LONG) { + long val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).longValue(); + return boxToInteger(val1 >>> val2); + } + } + if (code1 <= LONG) { + long val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).longValue(); + if (code2 <= INT) { + int val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).intValue(); + return boxToLong(val1 >>> val2); + } + if (code2 <= LONG) { + long val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).longValue(); + return boxToLong(val1 >>> val2); + } + } + throw new NoSuchMethodException(); + } + + /** -arg */ + public static Object negate(Object arg) throws NoSuchMethodException { + int code = typeCode(arg); + if (code <= INT) { + int val = (code == CHAR) ? ((Character) arg).charValue() : ((Number) arg).intValue(); + return boxToInteger(-val); + } + if (code <= LONG) { + long val = (code == CHAR) ? ((Character) arg).charValue() : ((Number) arg).longValue(); + return boxToLong(-val); + } + if (code <= FLOAT) { + float val = (code == CHAR) ? ((Character) arg).charValue() : ((Number) arg).floatValue(); + return boxToFloat(-val); + } + if (code <= DOUBLE) { + double val = (code == CHAR) ? ((Character) arg).charValue() : ((Number) arg).doubleValue(); + return boxToDouble(-val); + } + throw new NoSuchMethodException(); + } + + /** +arg */ + public static Object positive(Object arg) throws NoSuchMethodException { + int code = typeCode(arg); + if (code <= INT) { + int val = (code == CHAR) ? ((Character) arg).charValue() : ((Number) arg).intValue(); + return boxToInteger(+val); + } + if (code <= LONG) { + long val = (code == CHAR) ? ((Character) arg).charValue() : ((Number) arg).longValue(); + return boxToLong(+val); + } + if (code <= FLOAT) { + float val = (code == CHAR) ? ((Character) arg).charValue() : ((Number) arg).floatValue(); + return boxToFloat(+val); + } + if (code <= DOUBLE) { + double val = (code == CHAR) ? ((Character) arg).charValue() : ((Number) arg).doubleValue(); + return boxToDouble(+val); + } + throw new NoSuchMethodException(); + } + + /** arg1 & arg2 */ + public static Object takeAnd(Object arg1, Object arg2) throws NoSuchMethodException { + if ((arg1 instanceof Boolean) || (arg2 instanceof Boolean)) { + if (!((arg1 instanceof Boolean) && (arg2 instanceof Boolean))) { + throw new NoSuchMethodException(); + } + return boxToBoolean(((Boolean) arg1).booleanValue() & ((Boolean) arg2).booleanValue()); + } + int code1 = typeCode(arg1); + int code2 = typeCode(arg2); + int maxcode = (code1 < code2) ? code2 : code1; + if (maxcode <= INT) { + int val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).intValue(); + int val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).intValue(); + return boxToInteger(val1 & val2); + } + if (maxcode <= LONG) { + long val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).longValue(); + long val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).longValue(); + return boxToLong(val1 & val2); + } + throw new NoSuchMethodException(); + } + + /** arg1 | arg2 */ + public static Object takeOr(Object arg1, Object arg2) throws NoSuchMethodException { + if ((arg1 instanceof Boolean) || (arg2 instanceof Boolean)) { + if (!((arg1 instanceof Boolean) && (arg2 instanceof Boolean))) { + throw new NoSuchMethodException(); + } + return boxToBoolean(((Boolean) arg1).booleanValue() | ((Boolean) arg2).booleanValue()); + } + int code1 = typeCode(arg1); + int code2 = typeCode(arg2); + int maxcode = (code1 < code2) ? code2 : code1; + if (maxcode <= INT) { + int val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).intValue(); + int val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).intValue(); + return boxToInteger(val1 | val2); + } + if (maxcode <= LONG) { + long val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).longValue(); + long val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).longValue(); + return boxToLong(val1 | val2); + } + throw new NoSuchMethodException(); + } + + /** arg1 ^ arg2 */ + public static Object takeXor(Object arg1, Object arg2) throws NoSuchMethodException { + if ((arg1 instanceof Boolean) || (arg2 instanceof Boolean)) { + if (!((arg1 instanceof Boolean) && (arg2 instanceof Boolean))) { + throw new NoSuchMethodException(); + } + return boxToBoolean(((Boolean) arg1).booleanValue() ^ ((Boolean) arg2).booleanValue()); + } + int code1 = typeCode(arg1); + int code2 = typeCode(arg2); + int maxcode = (code1 < code2) ? code2 : code1; + if (maxcode <= INT) { + int val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).intValue(); + int val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).intValue(); + return boxToInteger(val1 ^ val2); + } + if (maxcode <= LONG) { + long val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).longValue(); + long val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).longValue(); + return boxToLong(val1 ^ val2); + } + throw new NoSuchMethodException(); + } + + /** arg1 && arg2 */ + public static Object takeConditionalAnd(Object arg1, Object arg2) throws NoSuchMethodException { + if ((arg1 instanceof Boolean) && (arg2 instanceof Boolean)) { + return boxToBoolean(((Boolean) arg1).booleanValue() && ((Boolean) arg2).booleanValue()); + } + throw new NoSuchMethodException(); + } + + /** arg1 || arg2 */ + public static Object takeConditionalOr(Object arg1, Object arg2) throws NoSuchMethodException { + if ((arg1 instanceof Boolean) && (arg2 instanceof Boolean)) { + return boxToBoolean(((Boolean) arg1).booleanValue() || ((Boolean) arg2).booleanValue()); + } + throw new NoSuchMethodException(); + } + + /** ~arg */ + public static Object complement(Object arg) throws NoSuchMethodException { + int code = typeCode(arg); + if (code <= INT) { + int val = (code == CHAR) ? ((Character) arg).charValue() : ((Number) arg).intValue(); + return boxToInteger(~val); + } + if (code <= LONG) { + long val = (code == CHAR) ? ((Character) arg).charValue() : ((Number) arg).longValue(); + return boxToLong(~val); + } + throw new NoSuchMethodException(); + } + + /** !arg */ + public static Object takeNot(Object arg) throws NoSuchMethodException { + if (arg instanceof Boolean) { + return boxToBoolean(!((Boolean) arg).booleanValue()); + } + throw new NoSuchMethodException(); + } + + public static Object testEqual(Object arg1, Object arg2) throws NoSuchMethodException { + return boxToBoolean(arg1 == arg2); + } + + public static Object testNotEqual(Object arg1, Object arg2) throws NoSuchMethodException { + return boxToBoolean(arg1 != arg2); + } + + public static Object testLessThan(Object arg1, Object arg2) throws NoSuchMethodException { + int code1 = typeCode(arg1); + int code2 = typeCode(arg2); + int maxcode = (code1 < code2) ? code2 : code1; + if (maxcode <= INT) { + int val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).intValue(); + int val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).intValue(); + return boxToBoolean(val1 < val2); + } + if (maxcode <= LONG) { + long val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).longValue(); + long val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).longValue(); + return boxToBoolean(val1 < val2); + } + if (maxcode <= FLOAT) { + float val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).floatValue(); + float val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).floatValue(); + return boxToBoolean(val1 < val2); + } + if (maxcode <= DOUBLE) { + double val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).doubleValue(); + double val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).doubleValue(); + return boxToBoolean(val1 < val2); + } + throw new NoSuchMethodException(); + } + + public static Object testLessOrEqualThan(Object arg1, Object arg2) throws NoSuchMethodException { + int code1 = typeCode(arg1); + int code2 = typeCode(arg2); + int maxcode = (code1 < code2) ? code2 : code1; + if (maxcode <= INT) { + int val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).intValue(); + int val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).intValue(); + return boxToBoolean(val1 <= val2); + } + if (maxcode <= LONG) { + long val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).longValue(); + long val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).longValue(); + return boxToBoolean(val1 <= val2); + } + if (maxcode <= FLOAT) { + float val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).floatValue(); + float val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).floatValue(); + return boxToBoolean(val1 <= val2); + } + if (maxcode <= DOUBLE) { + double val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).doubleValue(); + double val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).doubleValue(); + return boxToBoolean(val1 <= val2); + } + throw new NoSuchMethodException(); + } + + public static Object testGreaterOrEqualThan(Object arg1, Object arg2) throws NoSuchMethodException { + int code1 = typeCode(arg1); + int code2 = typeCode(arg2); + int maxcode = (code1 < code2) ? code2 : code1; + if (maxcode <= INT) { + int val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).intValue(); + int val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).intValue(); + return boxToBoolean(val1 >= val2); + } + if (maxcode <= LONG) { + long val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).longValue(); + long val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).longValue(); + return boxToBoolean(val1 >= val2); + } + if (maxcode <= FLOAT) { + float val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).floatValue(); + float val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).floatValue(); + return boxToBoolean(val1 >= val2); + } + if (maxcode <= DOUBLE) { + double val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).doubleValue(); + double val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).doubleValue(); + return boxToBoolean(val1 >= val2); + } + throw new NoSuchMethodException(); + } + + public static Object testGreaterThan(Object arg1, Object arg2) throws NoSuchMethodException { + int code1 = typeCode(arg1); + int code2 = typeCode(arg2); + int maxcode = (code1 < code2) ? code2 : code1; + if (maxcode <= INT) { + int val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).intValue(); + int val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).intValue(); + return boxToBoolean(val1 > val2); + } + if (maxcode <= LONG) { + long val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).longValue(); + long val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).longValue(); + return boxToBoolean(val1 > val2); + } + if (maxcode <= FLOAT) { + float val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).floatValue(); + float val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).floatValue(); + return boxToBoolean(val1 > val2); + } + if (maxcode <= DOUBLE) { + double val1 = (code1 == CHAR) ? ((Character) arg1).charValue() : ((Number) arg1).doubleValue(); + double val2 = (code2 == CHAR) ? ((Character) arg2).charValue() : ((Number) arg2).doubleValue(); + return boxToBoolean(val1 > val2); + } + throw new NoSuchMethodException(); + } + + /** arg.toChar */ + public static Character toCharacter(Object arg) throws NoSuchMethodException { + if (arg instanceof Character) return (Character)arg; + if (arg instanceof Byte) return boxToCharacter((char)unboxToByte(arg)); + if (arg instanceof Short) return boxToCharacter((char)unboxToShort(arg)); + if (arg instanceof Integer) return boxToCharacter((char)unboxToInt(arg)); + if (arg instanceof Long) return boxToCharacter((char)unboxToLong(arg)); + if (arg instanceof Float) return boxToCharacter((char)unboxToFloat(arg)); + if (arg instanceof Double) return boxToCharacter((char)unboxToDouble(arg)); + throw new NoSuchMethodException(); + } + + /** arg.toByte */ + public static Byte toByte(Object arg) throws NoSuchMethodException { + if (arg instanceof Character) return boxToByte((byte)unboxToChar(arg)); + if (arg instanceof Byte) return (Byte)arg; + if (arg instanceof Short) return boxToByte((byte)unboxToShort(arg)); + if (arg instanceof Integer) return boxToByte((byte)unboxToInt(arg)); + if (arg instanceof Long) return boxToByte((byte)unboxToLong(arg)); + if (arg instanceof Float) return boxToByte((byte)unboxToFloat(arg)); + if (arg instanceof Double) return boxToByte((byte)unboxToDouble(arg)); + throw new NoSuchMethodException(); + } + + /** arg.toShort */ + public static Short toShort(Object arg) throws NoSuchMethodException { + if (arg instanceof Character) return boxToShort((short)unboxToChar(arg)); + if (arg instanceof Byte) return boxToShort((short)unboxToByte(arg)); + if (arg instanceof Short) return (Short)arg; + if (arg instanceof Integer) return boxToShort((short)unboxToInt(arg)); + if (arg instanceof Long) return boxToShort((short)unboxToLong(arg)); + if (arg instanceof Float) return boxToShort((short)unboxToFloat(arg)); + if (arg instanceof Double) return boxToShort((short)unboxToDouble(arg)); + throw new NoSuchMethodException(); + } + + /** arg.toInt */ + public static Integer toInteger(Object arg) throws NoSuchMethodException { + if (arg instanceof Character) return boxToInteger((int)unboxToChar(arg)); + if (arg instanceof Byte) return boxToInteger((int)unboxToByte(arg)); + if (arg instanceof Short) return boxToInteger((int)unboxToShort(arg)); + if (arg instanceof Integer) return (Integer)arg; + if (arg instanceof Long) return boxToInteger((int)unboxToLong(arg)); + if (arg instanceof Float) return boxToInteger((int)unboxToFloat(arg)); + if (arg instanceof Double) return boxToInteger((int)unboxToDouble(arg)); + throw new NoSuchMethodException(); + } + + /** arg.toLong */ + public static Long toLong(Object arg) throws NoSuchMethodException { + if (arg instanceof Character) return boxToLong((long)unboxToChar(arg)); + if (arg instanceof Byte) return boxToLong((long)unboxToByte(arg)); + if (arg instanceof Short) return boxToLong((long)unboxToShort(arg)); + if (arg instanceof Integer) return boxToLong((long)unboxToInt(arg)); + if (arg instanceof Long) return (Long)arg; + if (arg instanceof Float) return boxToLong((long)unboxToFloat(arg)); + if (arg instanceof Double) return boxToLong((long)unboxToDouble(arg)); + throw new NoSuchMethodException(); + } + + /** arg.toFloat */ + public static Float toFloat(Object arg) throws NoSuchMethodException { + if (arg instanceof Character) return boxToFloat((float)unboxToChar(arg)); + if (arg instanceof Byte) return boxToFloat((float)unboxToByte(arg)); + if (arg instanceof Short) return boxToFloat((float)unboxToShort(arg)); + if (arg instanceof Integer) return boxToFloat((float)unboxToInt(arg)); + if (arg instanceof Long) return boxToFloat((float)unboxToLong(arg)); + if (arg instanceof Float) return (Float)arg; + if (arg instanceof Double) return boxToFloat((float)unboxToDouble(arg)); + throw new NoSuchMethodException(); + } + + /** arg.toDouble */ + public static Double toDouble(Object arg) throws NoSuchMethodException { + if (arg instanceof Character) return boxToDouble((double)unboxToChar(arg)); + if (arg instanceof Byte) return boxToDouble((double)unboxToByte(arg)); + if (arg instanceof Short) return boxToDouble((double)unboxToShort(arg)); + if (arg instanceof Integer) return boxToDouble((double)unboxToInt(arg)); + if (arg instanceof Long) return boxToDouble((double)unboxToLong(arg)); + if (arg instanceof Float) return boxToDouble((double)unboxToFloat(arg)); + if (arg instanceof Double) return (Double)arg; + throw new NoSuchMethodException(); + } + +} diff --git a/src/library/scala/runtime/ByteRef.java b/src/library/scala/runtime/ByteRef.java new file mode 100644 index 0000000000..1e67f18a1f --- /dev/null +++ b/src/library/scala/runtime/ByteRef.java @@ -0,0 +1,21 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2008, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.runtime; + + +public class ByteRef implements java.io.Serializable { + private static final long serialVersionUID = -100666928446877072L; + + public byte elem; + public ByteRef(byte elem) { this.elem = elem; } + public String toString() { return Byte.toString(elem); } +} diff --git a/src/library/scala/runtime/CharRef.java b/src/library/scala/runtime/CharRef.java new file mode 100644 index 0000000000..a64b59dfd7 --- /dev/null +++ b/src/library/scala/runtime/CharRef.java @@ -0,0 +1,21 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2008, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.runtime; + + +public class CharRef implements java.io.Serializable { + private static final long serialVersionUID = 6537214938268005702L; + + public char elem; + public CharRef(char elem) { this.elem = elem; } + public String toString() { return Character.toString(elem); } +} diff --git a/src/library/scala/runtime/DoubleRef.java b/src/library/scala/runtime/DoubleRef.java new file mode 100644 index 0000000000..086429e03e --- /dev/null +++ b/src/library/scala/runtime/DoubleRef.java @@ -0,0 +1,21 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2008, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.runtime; + + +public class DoubleRef implements java.io.Serializable { + private static final long serialVersionUID = 8304402127373655534L; + + public double elem; + public DoubleRef(double elem) { this.elem = elem; } + public String toString() { return Double.toString(elem); } +} diff --git a/src/library/scala/runtime/ExceptionHandling.java b/src/library/scala/runtime/ExceptionHandling.java new file mode 100644 index 0000000000..0fcc1e2b1c --- /dev/null +++ b/src/library/scala/runtime/ExceptionHandling.java @@ -0,0 +1,26 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.runtime; + + +public abstract class ExceptionHandling { + + public static Throwable tryCatch(Runnable runnable) { + try { + runnable.run(); + return null; + } catch (Throwable exception) { + return exception; + } + } + +} diff --git a/src/library/scala/runtime/FloatRef.java b/src/library/scala/runtime/FloatRef.java new file mode 100644 index 0000000000..2160f54977 --- /dev/null +++ b/src/library/scala/runtime/FloatRef.java @@ -0,0 +1,21 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2008, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.runtime; + + +public class FloatRef implements java.io.Serializable { + private static final long serialVersionUID = -5793980990371366933L; + + public float elem; + public FloatRef(float elem) { this.elem = elem; } + public String toString() { return Float.toString(elem); } +} diff --git a/src/library/scala/runtime/IntRef.java b/src/library/scala/runtime/IntRef.java new file mode 100644 index 0000000000..3ad9ad69e5 --- /dev/null +++ b/src/library/scala/runtime/IntRef.java @@ -0,0 +1,21 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2008, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.runtime; + + +public class IntRef implements java.io.Serializable { + private static final long serialVersionUID = 1488197132022872888L; + + public int elem; + public IntRef(int elem) { this.elem = elem; } + public String toString() { return Integer.toString(elem); } +} diff --git a/src/library/scala/runtime/LongRef.java b/src/library/scala/runtime/LongRef.java new file mode 100644 index 0000000000..31b9cd3b55 --- /dev/null +++ b/src/library/scala/runtime/LongRef.java @@ -0,0 +1,21 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2008, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.runtime; + + +public class LongRef implements java.io.Serializable { + private static final long serialVersionUID = -3567869820105829499L; + + public long elem; + public LongRef(long elem) { this.elem = elem; } + public String toString() { return Long.toString(elem); } +} diff --git a/src/library/scala/runtime/ObjectRef.java b/src/library/scala/runtime/ObjectRef.java new file mode 100644 index 0000000000..1154c1dd26 --- /dev/null +++ b/src/library/scala/runtime/ObjectRef.java @@ -0,0 +1,21 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2008, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.runtime; + + +public class ObjectRef implements java.io.Serializable { + private static final long serialVersionUID = -9055728157600312291L; + + public Object elem; + public ObjectRef(Object elem) { this.elem = elem; } + public String toString() { return "" + elem; } +} diff --git a/src/library/scala/runtime/RichChar.scala b/src/library/scala/runtime/RichChar.scala new file mode 100644 index 0000000000..d06aa62a57 --- /dev/null +++ b/src/library/scala/runtime/RichChar.scala @@ -0,0 +1,71 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.runtime + + +import java.lang.Character +import Predef.NoSuchElementException + +/**

+ * For example, in the following code + *

+ *
+ *    object test extends Application {
+ *      Console.println('\40'.isWhitespace)
+ *      Console.println('\011'.isWhitespace)
+ *      Console.println('1'.asDigit == 1)
+ *      Console.println('A'.asDigit == 10)
+ *    }
+ *

+ * the implicit conversions are performed using the predefined view + * Predef.charWrapper. + *

+ */ +final class RichChar(x: Char) extends Proxy with Ordered[Char] { + + // Proxy.self + def self: Any = x + + // Ordered[Char].compare + def compare (y: Char): Int = if (x < y) -1 else if (x > y) 1 else 0 + + def asDigit: Int = Character.digit(x, Character.MAX_RADIX) + + def isControl: Boolean = Character.isISOControl(x) + def isDigit: Boolean = Character.isDigit(x) + def isLetter: Boolean = Character.isLetter(x) + def isLetterOrDigit: Boolean = Character.isLetterOrDigit(x) + def isLowerCase: Boolean = Character.isLowerCase(x) + def isUpperCase: Boolean = Character.isUpperCase(x) + def isWhitespace: Boolean = Character.isWhitespace(x) + + def toLowerCase: Char = Character.toLowerCase(x) + def toUpperCase: Char = Character.toUpperCase(x) + + /** Create an Iterator[Char] over the characters from 'x' to 'y' - 1 + */ + def until(limit: Char): Iterator[Char] = new Iterator[Char] { + private var ch = x + def hasNext: Boolean = ch < limit + def next: Char = + if (hasNext) { val j = ch; ch = (ch + 1).toChar; j } + else throw new NoSuchElementException("next on empty iterator") + } + + //def until(y: Char): Iterator[Char] = to(y) + + /** Create an Iterator[Char] over the characters from 'x' to 'y' + */ + def to(y: Char): Iterator[Char] = until((y + 1).toChar) + +} diff --git a/src/library/scala/runtime/RichDouble.scala b/src/library/scala/runtime/RichDouble.scala new file mode 100644 index 0000000000..64d9046980 --- /dev/null +++ b/src/library/scala/runtime/RichDouble.scala @@ -0,0 +1,54 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.runtime + + +final class RichDouble(x: Double) extends Proxy with Ordered[Double] { + + // Proxy.self + def self: Any = x + + // Ordered[Double].compare + //def compare(y: Double): Int = if (x < y) -1 else if (x > y) 1 else 0 + def compare(y: Double): Int = java.lang.Double.compare(x, y) + + def min(y: Double): Double = Math.min(x, y) + def max(y: Double): Double = Math.max(x, y) + def abs: Double = Math.abs(x) + + def round: Long = Math.round(x) + def ceil: Double = Math.ceil(x) + def floor: Double = Math.floor(x) + + /** Converts an angle measured in degrees to an approximately equivalent + * angle measured in radians. + * + * @param x an angle, in degrees + * @return the measurement of the angle x in radians. + */ + def toRadians: Double = Math.toRadians(x) + + /** Converts an angle measured in radians to an approximately equivalent + * angle measured in degrees. + * + * @param x angle, in radians + * @return the measurement of the angle x in degrees. + */ + def toDegrees: Double = Math.toDegrees(x) + + // isNaN is provided by the implicit conversion to java.lang.Double + // def isNaN: Boolean = java.lang.Double.isNaN(x) + def isInfinity: Boolean = java.lang.Double.isInfinite(x) + def isPosInfinity: Boolean = isInfinity && x > 0.0 + def isNegInfinity: Boolean = isInfinity && x < 0.0 + +} diff --git a/src/library/scala/runtime/RichFloat.scala b/src/library/scala/runtime/RichFloat.scala new file mode 100644 index 0000000000..482ec3fbc0 --- /dev/null +++ b/src/library/scala/runtime/RichFloat.scala @@ -0,0 +1,56 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.runtime + + +import Predef._ + +final class RichFloat(x: Float) extends Proxy with Ordered[Float] { + + // Proxy.self + def self: Any = x + + // Ordered[Float].compare + //def compare(y: Float): Int = if (x < y) -1 else if (x > y) 1 else 0 + def compare(y: Float): Int = java.lang.Float.compare(x, y) + + def min(y: Float) = Math.min(x, y) + def max(y: Float) = Math.max(x, y) + def abs: Float = Math.abs(x) + + def round: Int = Math.round(x) + def ceil: Float = Math.ceil(x).toFloat + def floor: Float = Math.floor(x).toFloat + + /** Converts an angle measured in degrees to an approximately equivalent + * angle measured in radians. + * + * @param x an angle, in degrees + * @return the measurement of the angle x in radians. + */ + def toRadians: Float = Math.toRadians(x).toFloat + + /** Converts an angle measured in radians to an approximately equivalent + * angle measured in degrees. + * + * @param x angle, in radians + * @return the measurement of the angle x in degrees. + */ + def toDegrees: Float = Math.toDegrees(x).toFloat + + // isNaN is provided by the implicit conversion to java.lang.Float + // def isNaN: Boolean = java.lang.Float.isNaN(x) + def isInfinity: Boolean = java.lang.Float.isInfinite(x) + def isPosInfinity: Boolean = isInfinity && x > 0.0f + def isNegInfinity: Boolean = isInfinity && x < 0.0f + +} diff --git a/src/library/scala/runtime/RichInt.scala b/src/library/scala/runtime/RichInt.scala new file mode 100644 index 0000000000..73b13afa28 --- /dev/null +++ b/src/library/scala/runtime/RichInt.scala @@ -0,0 +1,39 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2008, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.runtime + + +final class RichInt(start: Int) extends Proxy with Ordered[Int] { + + // Proxy + def self: Any = start + + // Ordered[Int] + def compare(that: Int): Int = if (start < that) -1 else if (start > that) 1 else 0 + + /** See Iterator.range. */ + def until(end: Int): Range = new Range(start, end, 1) + + /** See Iterator.range. */ + def until(end: Int, step: Int): Range = new Range(start, end, step) + + /** like until, but includes the last index */ + def to(end: Int) = new Range.Inclusive(start, end, 1) + + def min(that: Int): Int = if (start < that) start else that + def max(that: Int): Int = if (start > that) start else that + def abs: Int = if (start < 0) -start else start + + def toBinaryString: String = java.lang.Integer.toBinaryString(start) + def toHexString: String = java.lang.Integer.toHexString(start) + def toOctalString: String = java.lang.Integer.toOctalString(start) +} diff --git a/src/library/scala/runtime/RichLong.scala b/src/library/scala/runtime/RichLong.scala new file mode 100644 index 0000000000..7e835f10c3 --- /dev/null +++ b/src/library/scala/runtime/RichLong.scala @@ -0,0 +1,30 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2008, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.runtime + + +final class RichLong(x: Long) extends Proxy with Ordered[Long] { + + // Proxy.self + def self: Any = x + + // Ordered[Long].compare + def compare(y: Long): Int = if (x < y) -1 else if (x > y) 1 else 0 + + def min(y: Long): Long = if (x < y) x else y + def max(y: Long): Long = if (x > y) x else y + def abs: Long = if (x < 0) -x else x + + def toBinaryString: String = java.lang.Long.toBinaryString(x) + def toHexString: String = java.lang.Long.toHexString(x) + def toOctalString: String = java.lang.Long.toOctalString(x) +} diff --git a/src/library/scala/runtime/RichString.scala b/src/library/scala/runtime/RichString.scala new file mode 100644 index 0000000000..192cf62ebb --- /dev/null +++ b/src/library/scala/runtime/RichString.scala @@ -0,0 +1,245 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2008, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.runtime + +import Predef._ +import scala.util.matching.Regex + +final class RichString(val self: String) extends Proxy with CharSequence with RandomAccessSeq[Char] with Ordered[String] { + import RichString._ + override def apply(n: Int) = self charAt n + override def length = self.length + override def toString = self + override def mkString = self + + override def slice(from: Int, until: Int): RichString = { + val len = self.length + new RichString( + if (from >= until || from >= len) + "" + else { + val from0 = if (from < 0) 0 else from + val until0 = if (until > len) len else until + self.substring(from0, until0) + } + ) + } + + //override def ++ [B >: A](that: Iterable[B]): Seq[B] = { + override def ++[B >: Char](that: Iterable[B]): RandomAccessSeq[B] = that match { + case that: RichString => new RichString(self + that.self) + case that => super.++(that) + } + + override def take(until: Int): RichString = slice(0, until) + + override def drop(from: Int): RichString = slice(from, self.length) + + override def startsWith[B](that: Seq[B]) = that match { + case that: RichString => self startsWith that.self + case that => super.startsWith(that) + } + + override def endsWith[B](that: Seq[B]) = that match { + case that: RichString => self endsWith that.self + case that => super.endsWith(that) + } + + override def indexOf[B](that: Seq[B]) = that match { + case that: RichString => self indexOf that.self + case that => super.indexOf(that) + } + + override def containsSlice[B](that: Seq[B]) = that match { + case that: RichString => self contains that.self + case that => super.containsSlice(that) + } + + override def reverse: RichString = { + val buf = new StringBuilder + var i = self.length - 1 + while (i >= 0) { + buf append (self charAt i) + i -= 1 + } + new RichString(buf.toString) + } + + def charAt(index: Int) = self.charAt(index) + + def subSequence(start: Int, end: Int): CharSequence = + new RichString(self.substring(start, end)) + + /** return n times the current string + */ + def * (n: Int): String = { + val buf = new StringBuilder + for (i <- 0 until n) buf append self + buf.toString + } + + override def compare(other: String) = self compareTo other + + private def isLineBreak(c: Char) = c == LF || c == FF + + /**

+ * Strip trailing line end character from this string if it has one. + * A line end character is one of + *

+ * + *

+ * If a line feed character LF is preceded by a carriage return CR + * (0x0D hex), the CR character is also stripped (Windows convention). + *

+ */ + def stripLineEnd: String = { + val len = self.length + if (len == 0) self + else { + val last = apply(len - 1) + if (isLineBreak(last)) + self.substring(0, if (last == LF && len >= 2 && apply(len - 2) == CR) len - 2 else len - 1) + else + self + } + } + + /**

+ * Return all lines in this string in an iterator, including trailing + * line end characters. + *

+ *

+ * The number of strings returned is one greater than the number of line + * end characters in this string. For an empty string, a single empty + * line is returned. A line end character is one of + *

+ * + */ + def linesWithSeparators = new Iterator[String] { + val len = self.length + var index = 0 + def hasNext: Boolean = index < len + def next(): String = { + if (index >= len) throw new NoSuchElementException("next on empty iterator") + val start = index + while (index < len && !isLineBreak(apply(index))) index += 1 + index += 1 + self.substring(start, index min len) + } + } + + /** Return all lines in this string in an iterator, excluding trailing line + * end characters, i.e. apply .stripLineEnd to all lines + * returned by linesWithSeparators. + */ + def lines: Iterator[String] = + linesWithSeparators map (line => new RichString(line).stripLineEnd) + + /** Returns this string with first character converted to upper case */ + def capitalize: String = + if (self == null) null + else if (self.length == 0) "" + else { + val chars = self.toCharArray + chars(0) = chars(0).toUpperCase + new String(chars) + } + + /**

+ * For every line in this string: + *

+ *
+ * Strip a leading prefix consisting of blanks or control characters + * followed by marginChar from the line. + *
+ */ + def stripMargin(marginChar: Char): String = { + val buf = new StringBuilder + for (line <- linesWithSeparators) { + val len = line.length + var index = 0 + while (index < len && line.charAt(index) <= ' ') index += 1 + buf append + (if (index < len && line.charAt(index) == marginChar) line.substring(index + 1) else line) + } + buf.toString + } + + /**

+ * For every line in this string: + *

+ *
+ * Strip a leading prefix consisting of blanks or control characters + * followed by | from the line. + *
+ */ + def stripMargin: String = stripMargin('|') + + // NB. "\\Q" + '\\' + "\\E" works on Java 1.5 and newer, but not on Java 1.4 + private def escape(ch: Char): String = ch match { + case '\\' => "\\\\" + case _ => "\\Q"+ch+"\\E" + } + + @throws(classOf[java.util.regex.PatternSyntaxException]) + def split(separator: Char): Array[String] = self.split(escape(separator)) + + @throws(classOf[java.util.regex.PatternSyntaxException]) + def split(separators: Array[Char]): Array[String] = { + val re = separators.foldLeft("[")(_+escape(_)) + "]" + self.split(re) + } + + /** You can follow a string with `.r', turning + * it into a Regex. E.g. + * + * """A\w*""".r is the regular expression for identifiers starting with `A'. + */ + def r: Regex = new Regex(self) + + def toBoolean: Boolean = parseBoolean(self) + def toByte: Byte = java.lang.Byte.parseByte(self) + def toShort: Short = java.lang.Short.parseShort(self) + def toInt: Int = java.lang.Integer.parseInt(self) + def toLong: Long = java.lang.Long.parseLong(self) + def toFloat: Float = java.lang.Float.parseFloat(self) + def toDouble: Double = java.lang.Double.parseDouble(self) + + override def toArray: Array[Char] = { + val result = new Array[Char](length) + self.getChars(0, length, result, 0) + result + } +} + +object RichString { + // just statics for rich string. + private final val LF: Char = 0x0A + private final val FF: Char = 0x0C + private final val CR: Char = 0x0D + private final val SU: Char = 0x1A + + private def parseBoolean(s: String): Boolean = + if (s != null) s.toLowerCase match { + case "true" => true + case "false" => false + case _ => throw new NumberFormatException("For input string: \""+s+"\"") + } + else + throw new NumberFormatException("For input string: \"null\"") +} diff --git a/src/library/scala/runtime/ShortRef.java b/src/library/scala/runtime/ShortRef.java new file mode 100644 index 0000000000..b471056260 --- /dev/null +++ b/src/library/scala/runtime/ShortRef.java @@ -0,0 +1,20 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2008, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.runtime; + + +public class ShortRef implements java.io.Serializable { + private static final long serialVersionUID = 4218441291229072313L; + + public short elem; + public ShortRef(short elem) { this.elem = elem; } +} diff --git a/src/library/scala/runtime/StringAdd.scala b/src/library/scala/runtime/StringAdd.scala new file mode 100644 index 0000000000..272e2cbb08 --- /dev/null +++ b/src/library/scala/runtime/StringAdd.scala @@ -0,0 +1,41 @@ +/* *\ +** ________ ___ __ ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ |_| ** +** ** +\* */ + +// $Id$ + + +package scala.runtime + + +import Predef._ + +object StringAdd { + // Needed for the format hack. Can be removed once we drop 1.4 + lazy val formatMethod: java.lang.reflect.Method = { + val paramTypes = Array[Class[T] forSome { type T }](classOf[String], classOf[Array[Object]]) + classOf[String].getDeclaredMethod("format", paramTypes) + } +} +final class StringAdd(self: Any) { + + def +(other: String) = self.toString + other + + /** Returns string formatted according to given format string. + * Format strings are as for String.format + * (@see java.lang.String.format). + * Only works on Java 1.5 or higher! + */ + def formatted(format: String): String = { + // This should be: + // String.format(format, Array(self.asInstanceOf[Object])) + // However, the line above does not compile on Java 1.4 because String.format exists only in 1.5 + // Therefore, we do the following hack: + val args = Array(self.asInstanceOf[Object]) + StringAdd.formatMethod.invoke(null, Array[Object](format, args)).asInstanceOf[String] + } +} diff --git a/src/library/scala/util/DynamicVariable.scala b/src/library/scala/util/DynamicVariable.scala new file mode 100644 index 0000000000..552e946250 --- /dev/null +++ b/src/library/scala/util/DynamicVariable.scala @@ -0,0 +1,84 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2006-2008, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.util + + +import Predef._ +import java.lang.InheritableThreadLocal + +/**

+ * DynamicVariables provide a binding mechanism where the current + * value is found through dynamic scope, but where + * access to the variable itself is resolved through static + * scope. + *

+ *

+ * The current value can be retrieved with the + * value method. New values should be + * pushed using the withValue method. + * Values pushed via withValue only + * stay valid while the withValue's + * second argument, a parameterless closure, + * executes. When the second argument finishes, + * the variable reverts to the previous value. + *

+ *

+ * Usage of withValue looks like this: + *

+ *
+ *  someDynamicVariable.withValue(newValue) {
+ *    // ... code called in here that calls value ...
+ *    // ... will be given back the newValue ...
+ *  }
+ *  
+ *

+ * Each thread gets its own stack of bindings. When a + * new thread is created, the fluid gets a copy of + * the stack of bindings from the parent thread, and + * from then on the bindings for the new thread + * are independent of those for the original thread. + *

+ * + * @author Lex Spoon + * @version 1.1, 2007-5-21 + */ +class DynamicVariable[T](init: T) { + private val tl = new InheritableThreadLocal[T] { + override def initialValue = init.asInstanceOf[T with AnyRef] + } + + /** Retrieve the current value */ + def value: T = tl.get.asInstanceOf[T] + + + /** Set the value of the variable while executing the specified + * thunk. + * + * @param newval The value to which to set the fluid + * @param thunk The code to evaluate under the new setting + */ + def withValue[S](newval: T)(thunk: =>S): S = { + val oldval = value + tl.set(newval) + + try { thunk } finally { + tl.set(oldval) + } + } + + /** Change the currently bound value, discarding the old value. + * Usually withValue() gives better semantics. + */ + def value_=(newval: T) = { tl.set(newval) } + + override def toString: String = "DynamicVariable(" + value +")" +} diff --git a/src/library/scala/util/Properties.scala b/src/library/scala/util/Properties.scala new file mode 100644 index 0000000000..2fa885dc3a --- /dev/null +++ b/src/library/scala/util/Properties.scala @@ -0,0 +1,57 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2006-2008, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + +package scala.util + +/** A utility to load the library properties from a Java properties file + * included in the jar. + * + * @author Stephane Micheloud + */ +object Properties { + + /** The name of the properties file */ + private val propFilename = "/library.properties" + + /** The loaded properties */ + private val props = { + val props = new java.util.Properties + val stream = classOf[Application].getResourceAsStream(propFilename) + if (stream != null) + props.load(stream) + props + } + + /** The version number of the jar this was loaded from, or + * "(unknown)" if it cannot be determined. + */ + val versionString: String = { + val defaultString = "(unknown)" + "version " + props.getProperty("version.number") + } + + val copyrightString: String = { + val defaultString = "(c) 2002-2008 LAMP/EPFL" + props.getProperty("copyright.string", defaultString) + } + + val encodingString: String = { + val defaultString = "UTF8" //"ISO-8859-1" + props.getProperty("file.encoding", defaultString) + } + + private val writer = new java.io.PrintWriter(Console.err, true) + + val versionMsg = "Scala library " + versionString + " -- " + copyrightString + + def main(args: Array[String]) { + writer.println(versionMsg) + } +} diff --git a/src/library/scala/util/matching/Regex.scala b/src/library/scala/util/matching/Regex.scala new file mode 100644 index 0000000000..32fc300bf1 --- /dev/null +++ b/src/library/scala/util/matching/Regex.scala @@ -0,0 +1,274 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2007-2008, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.util.matching + +import java.util.regex.{Pattern, Matcher} + +/** This class provides methods for creating and using regular expressions. + * It is based on the regular expressions of the JDK since 1.4. + * + * @author Thibaud Hottelier + * @author Philipp Haller + * @author Martin Odersky + * @version 1.1, 29/01/2008 + * + * @param regex A string representing a regular expression + * @param groupNames A mapping from names to indices in capture groups + */ +class Regex(regex: String, groupNames: String*) { + + import Regex._ + + /** The compiled pattern */ + val pattern = Pattern.compile(regex) + + /** Tries to match target (whole match) and returns + * the matches. + * + * @param target The string to match + * @return The matches + */ + def unapplySeq(target: Any): Option[List[String]] = target match { + case s: java.lang.CharSequence => + val m = pattern.matcher(s) + if (m.matches) Some((1 to m.groupCount).toList map m.group) + else None + case Match(s) => + unapplySeq(s) + case _ => + None + } + + /** Return all matches of this regexp in given character sequence as an iterator + */ + def findAllIn(source: CharSequence) = new Regex.MatchIterator(source, this, groupNames) + + /** Return optionally first matching string of this regexp in given character sequence, + * None if it does not exist. + */ + def findFirstIn(source: CharSequence): Option[String] = { + val m = pattern.matcher(source) + if (m.find) Some(m.group) else None + } + + /** Return optionally first match of this regexp in given character sequence, + * None if it does not exist. + */ + def findFirstMatchIn(source: CharSequence): Option[Match] = { + val m = pattern.matcher(source) + if (m.find) Some(new Match(source, m, groupNames)) else None + } + + /** Return optionally match of this regexp at the beginning of the + * given character sequence, or None if regexp matches no prefix + * of the character sequence. + */ + def findPrefixOf(source: CharSequence): Option[String] = { + val m = pattern.matcher(source) + if (m.lookingAt) Some(m.group) else None + } + + /** Return optionally match of this regexp at the beginning of the + * given character sequence, or None if regexp matches no prefix + * of the character sequence. + */ + def findPrefixMatchOf(source: CharSequence): Option[Match] = { + val m = pattern.matcher(source) + if (m.lookingAt) Some(new Match(source, m, groupNames)) else None + } + + /** Replaces all matches by a string. + * + * @param target The string to match + * @param replacement The string that will replace each match + * @return The resulting string + */ + def replaceAllIn(target: CharSequence, replacement: String): String = { + val m = pattern.matcher(target) + m.replaceAll(replacement) + } + + /** Replaces the first match by a string. + * + * @param target The string to match + * @param replacement The string that will replace the match + * @return The resulting string + */ + def replaceFirstIn(target: CharSequence, replacement: String): String = { + val m = pattern.matcher(target) + m.replaceFirst(replacement) + } + + /** The string defining the regular expression */ + override def toString = regex +} + +/** This object defines inner classes that describe + * regex matches. The class hirrachy is as follows. + * + * MatchData + * | \ + * MatchIterator Match + */ +object Regex { + + /** This class provides methods to access + * the details of a match. + */ + trait MatchData { + + /** The source from where the match originated */ + val source: CharSequence + + /** The names of the groups, or some empty sequence if one defined */ + val groupNames: Seq[String] + + /** The index of the first matched character */ + def start: Int + + /** The index of the first matched character in group i */ + def start(i: Int): Int + + /** The index of the last matched character */ + def end: Int + + /** The number of subgroups */ + def groupCount: Int + + /** The index following the last matched character in group i */ + def end(i: Int): Int + + /** The matched string */ + def matched: String = source.subSequence(start, end).toString + + /** The matched string in group i */ + def group(i: Int): String = source.subSequence(start(i), end(i)).toString + + /** All matched subgroups, i.e. not including group(0) */ + def subgroups: List[String] = (1 to groupCount).toList map group + + /** The char sequence before first character of match */ + def before: CharSequence = source.subSequence(0, start) + + /** The char sequence before first character of match in group i */ + def before(i: Int): CharSequence = source.subSequence(0, start(i)) + + /** Returns char sequence after last character of match */ + def after: CharSequence = source.subSequence(end) + + /** The char sequence after last character of match in group i */ + def after(i: Int): CharSequence = source.subSequence(end(i)) + + private lazy val nameToIndex: Map[String, Int] = Map() ++ ("" :: groupNames.toList).zipWithIndex + + /** Returns the group with given name + * + * @param id The group name + * @return The requested group + * @throws NoSuchElementException if the requested + * group name is not defined + */ + def group(id: String): String = nameToIndex.get(id) match { + case None => throw new NoSuchElementException("group name "+id+" not defined") + case Some(index) => group(index) + } + + /** The matched string; equivalent to matched.toString */ + override def toString = matched + + } + + /** A case class for a succesful match. + */ + class Match(val source: CharSequence, + matcher: Matcher, + val groupNames: Seq[String]) extends MatchData { + + /** The index of the first matched character */ + val start = matcher.start + + /** The index following the last matched character */ + val end = matcher.end + + /** The number of subgroups */ + def groupCount = matcher.groupCount + + private lazy val starts: Array[Int] = + ((1 to groupCount) map matcher.start).toArray + private lazy val ends: Array[Int] = + ((1 to groupCount) map matcher.end).toArray + + /** The index of the first matched character in group i */ + def start(i: Int) = starts(i) + + /** The index following the last matched character in group i */ + def end(i: Int) = ends(i) + + /** The match itself with matcher-dependent lazy vals forced, + * so that match is valid even once matcher is advanced + */ + def force: this.type = { starts; ends; this } + } + + /** An extractor object for Matches, yielding the matched string */ + object Match { + def unapply(m: Match): Some[String] = Some(m.matched) + } + + /** A class to step through a sequence of regex matches + */ + class MatchIterator(val source: CharSequence, val regex: Regex, val groupNames: Seq[String]) + extends Iterator[String] with MatchData { self => + + private val matcher = regex.pattern.matcher(source) + private var nextSeen = false + + /** Is there another match? */ + def hasNext: Boolean = { + if (!nextSeen) nextSeen = matcher.find() + nextSeen + } + + /** The next matched substring of `source' */ + def next: String = { + if (!hasNext) throw new NoSuchElementException + nextSeen = false + matcher.group + } + + override def toString = super[Iterator].toString + + /** The index of the first matched character */ + def start: Int = matcher.start + + /** The index of the first matched character in group i */ + def start(i: Int): Int = matcher.start(i) + + /** The index of the last matched character */ + def end: Int = matcher.end + + /** The index following the last matched character in group i */ + def end(i: Int): Int = matcher.end(i) + + /** The number of subgroups */ + def groupCount = matcher.groupCount + + /** Convert to an iterator that yields MatchData elements instead of Strings */ + def matchData = new Iterator[Match] { + def hasNext = self.hasNext + def next = { self.next; new Match(source, matcher, groupNames).force } + } + } +} + + + diff --git a/src/library/scala/util/parsing/CharInputStreamIterator.scala b/src/library/scala/util/parsing/CharInputStreamIterator.scala new file mode 100644 index 0000000000..b58650e025 --- /dev/null +++ b/src/library/scala/util/parsing/CharInputStreamIterator.scala @@ -0,0 +1,52 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.util.parsing + + +import java.io.InputStream +import java.io.{IOException, EOFException} + +/** This class ... + * + * @author Burak Emir + * @version 1.0 + * + * @deprecated use classes from + * scala.util.parsing.input instead. + */ +@deprecated +class CharInputStreamIterator(in: InputStream) extends Iterator[Char] { + + private var ch: Int = _ + private var chSet = false + private var error: IOException = null + + private def lookahead() { + try { + ch = in.read(); chSet = ch >= 0 + } catch { + case ex: EOFException => ch = -1 + case ex: IOException => ch = 1; error = ex + } + } + + def hasNext: Boolean = { + if (!chSet) lookahead() + chSet + } + + def next(): Char = { + if (!chSet) lookahead() + chSet = false + ch.asInstanceOf[Char] + } +} diff --git a/src/library/scala/util/parsing/combinator/RegexParsers.scala b/src/library/scala/util/parsing/combinator/RegexParsers.scala new file mode 100644 index 0000000000..37b5f1d10c --- /dev/null +++ b/src/library/scala/util/parsing/combinator/RegexParsers.scala @@ -0,0 +1,84 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + +package scala.util.parsing.combinator + +import java.util.regex.Pattern +import scala.util.matching.Regex +import scala.util.parsing.input._ + +trait RegexParsers extends Parsers { + + type Elem = Char + + protected val whiteSpace = """\s+""".r + + def skipWhitespace = whiteSpace.toString.length > 0 + + protected def handleWhiteSpace(source: CharSequence, offset: Int): Int = + if (skipWhitespace) + (whiteSpace findPrefixMatchOf (source subSequence offset)) match { + case Some(matched) => offset + matched.end + case None => offset + } + else + offset + + /** A parser that matches a literal string */ + implicit def literal(s: String): Parser[String] = new Parser[String] { + def apply(in: Input) = { + val source = in.source + val offset = in.offset + val start = handleWhiteSpace(source, offset) + var i = 0 + var j = start + while (i < s.length && source.isDefinedAt(j) && s.charAt(i) == source.charAt(j)) { + i += 1 + j += 1 + } + if (i == s.length) + Success(source.subSequence(start, j).toString, in.drop(j - offset)) + else + Failure("`"+s+"' expected but `"+in.first+"' found", in.drop(start - offset)) + } + } + + /** A parser that matches a regex string */ + implicit def regex(r: Regex): Parser[String] = new Parser[String] { + def apply(in: Input) = { + val source = in.source + val offset = in.offset + val start = handleWhiteSpace(source, offset) + (r findPrefixMatchOf (source subSequence start)) match { + case Some(matched) => + Success(source.subSequence(start, start + matched.end).toString, + in.drop(start + matched.end - offset)) + case None => + Failure("string matching regex `+r+' expected but `"+in.first+"' found", in.drop(start - offset)) + } + } + } + + /** Parse some prefix of character sequence `in' with parser `p' */ + def parse[T](p: Parser[T], in: CharSequence): ParseResult[T] = + p(new CharSequenceReader(in)) + + /** Parse some prefix of reader `in' with parser `p' */ + def parse[T](p: Parser[T], in: Reader[Char]): ParseResult[T] = + p(in) + + /** Parse all of character sequence `in' with parser `p' */ + def parseAll[T](p: Parser[T], in: CharSequence): ParseResult[T] = + parse(phrase(p), in) + + /** Parse all of reader `in' with parser `p' */ + def parseAll[T](p: Parser[T], in: Reader[Char]): ParseResult[T] = + parse(phrase(p), in) +} diff --git a/src/library/scala/util/parsing/input/StreamReader.scala b/src/library/scala/util/parsing/input/StreamReader.scala new file mode 100644 index 0000000000..f997590f18 --- /dev/null +++ b/src/library/scala/util/parsing/input/StreamReader.scala @@ -0,0 +1,74 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2006-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + +package scala.util.parsing.input + +import java.io.BufferedReader + +/** An object to create a StreamReader from a java.io.Reader. + * + * @param in the java.io.Reader that provides the underlying + * stream of characters for this Reader. + * + * @author Miles Sabin + */ +object StreamReader { + final val EofCh = '\032' + + def apply(in: java.io.Reader): StreamReader = { + new StreamReader(new LazyCharSequence(in), 0, 1) + } +} + +/** A character array reader reads a stream of characters (keeping track of + * their positions) from an array. + * + * NOTE: + * StreamReaders do not really fulfill the new contract for readers, which + * requires a `source' CharSequence representing the full input. + * Instead source is treated line by line. + * As a consequence, regex matching cannot extend beyond a single lines + * when a StreamReader are used for input. + * + * @param bin the underlying java.io.BufferedReader + * @param sourceLine the line at column `col' in the stream + * @param line the 1-based line number of the character returned by `first' + * @param column the 1-based column number of the character returned by `first' + * + * @author Miles Sabin + */ +sealed class StreamReader(source: CharSequence, offset: Int, lnum: Int) extends CharSequenceReader(source, offset) { + import StreamReader._ + + override def rest: CharSequenceReader = + if (offset == source.length) this + else if (source(offset) == '\n') new StreamReader(source.subSequence(offset + 1), 0, lnum + 1) + else new StreamReader(source, offset + 1, lnum) + + private def nextEol = { + var i = offset + while (i < source.length && source(i) != '\n' && source(i) != EofCh) i += 1 + i + } + + override def drop(n: Int): StreamReader = { + val eolPos = nextEol + if (eolPos < offset + n && eolPos < source.length) + new StreamReader(source.subSequence(eolPos + 1), 0, lnum + 1).drop(offset + n - (eolPos + 1)) + else + new StreamReader(source, offset + n, lnum) + } + + override def pos: Position = new Position { + def line = lnum + def column = offset + 1 + def lineContents = source.subSequence(0, nextEol).toString + } +} diff --git a/src/library/scala/xml/Parsing.scala b/src/library/scala/xml/Parsing.scala new file mode 100644 index 0000000000..9f2934a7b5 --- /dev/null +++ b/src/library/scala/xml/Parsing.scala @@ -0,0 +1,105 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.xml + + +/** The object Parsing ... + * + * @author Burak Emir + * @version 1.0 + * + * @deprecated use either parsing.TokenTests or + * Utilty (helper functions for parsing XML fragments). + */ +object Parsing { + + /**
(#x20 | #x9 | #xD | #xA)
*/ + final def isSpace(ch: Char): Boolean = ch match { + case '\u0009' | '\u000A' | '\u000D' | '\u0020' => true + case _ => false + } + + /**
(#x20 | #x9 | #xD | #xA)+
*/ + final def isSpace(cs: Seq[Char]): Boolean = { + val it = cs.elements + it.hasNext && it.forall { isSpace } + } + + /**
NameChar ::= Letter | Digit | '.' | '-' | '_' | ':'
+   *             | CombiningChar | Extender
+ * + * see [4] and Appendix B of XML 1.0 specification + */ + def isNameChar(ch: Char) = isNameStart(ch) || (ch match { + case '.' | '-' | ':' => true + case _ => java.lang.Character.getType(ch).asInstanceOf[Byte] match { + case java.lang.Character.COMBINING_SPACING_MARK => true // Mc + case java.lang.Character.ENCLOSING_MARK => true // Me + case java.lang.Character.NON_SPACING_MARK => true // Mn + case java.lang.Character.MODIFIER_LETTER => true // Lm + case java.lang.Character.DECIMAL_DIGIT_NUMBER => true // Nd + case _ => false + } + }); + + /**
NameStart ::= ( Letter | '_' )
+ * where Letter means in one of the Unicode general + * categories { Ll, Lu, Lo, Lt, Nl } + * + * We do not allow a name to start with ':'. + * see [3] and Appendix B of XML 1.0 specification + */ + def isNameStart(ch: Char) = + java.lang.Character.getType(ch).asInstanceOf[Byte] match { + case java.lang.Character.LOWERCASE_LETTER => true + case java.lang.Character.UPPERCASE_LETTER => true + case java.lang.Character.OTHER_LETTER => true + case java.lang.Character.TITLECASE_LETTER => true + case java.lang.Character.LETTER_NUMBER => true + case _ => ch == '_' + } + + /**
Name ::= ( Letter | '_' ) (NameChar)*
+ * + * see [5] of XML 1.0 specification + */ + def isName(s: String): Boolean = + if (s.length() > 0) { + val z: Seq[Char] = s + val y = z.elements + if (isNameStart(y.next)) { + while (y.hasNext && isNameChar(y.next)) {} + !y.hasNext + } else false + } else false + + def isPubIDChar(c: Char) = c match { + case '\u0020' | '\u000D' | '\u000A' => true + case _ if + ('0' < c && c < '9')||('a' < c && c < 'z')||('A' < c && c < 'Z') => true + case '-' | '\''| '(' | ')' | '+' | ',' | '.' | '/' | ':' | '=' | + '?' | ';' | '!' | '*' | '#' | '@' | '$' | '_' | '%' => true + case _ => false + } + + def checkSysID(s: String): Boolean = + s.indexOf('"') == -1 || s.indexOf('\'') == -1 + + def checkPubID(s: String): Boolean = + if (s.length() > 0) { + val z:Seq[Char] = s + val y = z.elements + while (y.hasNext && isPubIDChar(y.next)) {} + !y.hasNext + } else true + +} diff --git a/src/library/scala/xml/PrettyPrinter.scala b/src/library/scala/xml/PrettyPrinter.scala new file mode 100644 index 0000000000..05c612ce81 --- /dev/null +++ b/src/library/scala/xml/PrettyPrinter.scala @@ -0,0 +1,308 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.xml + +import scala.collection.Map + +/** Class for pretty printing. After instantiating, you can use the + * toPrettyXML methods to convert XML to a formatted string. The class + * can be reused to pretty print any number of XML nodes. + * + * @author Burak Emir + * @version 1.0 + * + * @param width the width to fit the output into + * @step indentation + */ +class PrettyPrinter( width:Int, step:Int ) { + + class BrokenException() extends java.lang.Exception + + class Item + case object Break extends Item { + override def toString() = "\\" + } + case class Box(col: Int, s: String) extends Item + case class Para(s: String) extends Item + + protected var items: List[Item] = Nil + + protected var cur = 0 + //protected var pmap:Map[String,String] = _ + + protected def reset() = { + cur = 0 + items = Nil + } + + /** Try to cut at whitespace. + * + * @param s ... + * @param ind ... + * @return ... + */ + protected def cut(s: String, ind: Int): List[Item] = { + val tmp = width - cur + if (s.length < tmp) + return List(Box(ind, s)) + val sb = new StringBuilder() + var i = s.indexOf(' ') + if (i > tmp || i == -1) throw new BrokenException() // cannot break + + var last: List[Int] = Nil + while (i != -1 && i < tmp) { + last = i::last + i = s.indexOf(' ', i+1) + } + var res: List[Item] = Nil + while (Nil != last) try { + val b = Box(ind, s.substring(0, last.head)) + cur = ind + res = b :: Break :: cut(s.substring(last.head, s.length), ind) + // backtrack + last = last.tail + } catch { + case _:BrokenException => last = last.tail + } + throw new BrokenException() + } + + /** Try to make indented box, if possible, else para. + * + * @param ind ... + * @param s ... + * @return ... + */ + protected def makeBox(ind: Int, s: String) = { + if (cur < ind) + cur == ind + if (cur + s.length > width) { // fits in this line + items = Box(ind, s) :: items + cur += s.length + } else try { + for (b <- cut(s, ind).elements) // break it up + items = b :: items + } catch { + case _:BrokenException => makePara(ind, s) // give up, para + } + } + + // dont respect indent in para, but afterwards + protected def makePara(ind: Int, s: String) = { + items = Break::Para(s)::Break::items + cur = ind + } + + // respect indent + protected def makeBreak() = { // using wrapping here... + items = Break :: items + cur = 0 + } + + /** + * @param n ... + * @return ... + */ + protected def leafTag(n: Node) = { + val sb = new StringBuilder("<") + n.nameToString(sb) + //Utility.appendPrefixedName( n.prefix, n.label, pmap, sb ); + n.attributes.toString(sb) + //Utility.attr2xml( n.scope, n.attributes, pmap, sb ); + sb.append("/>") + sb.toString() + } + + protected def startTag(n: Node, pscope: NamespaceBinding): (String, Int) = { + val sb = new StringBuilder("<") + n.nameToString(sb) //Utility.appendPrefixedName( n.prefix, n.label, pmap, sb ); + val i = sb.length + 1 + n.attributes.toString(sb) + n.scope.toString(sb, pscope) + sb.append('>') + (sb.toString(), i) + } + + protected def endTag(n: Node) = { + val sb = new StringBuilder("') + sb.toString() + } + + protected def childrenAreLeaves(n: Node): Boolean = { + val it = n.child.elements + while (it.hasNext) + it.next match { + case _:Atom[_] | _:Comment | _:EntityRef | _:ProcInstr => + case _:Node => + return false + } + true + } + + protected def fits(test: String) = + test.length < width - cur + + /** @param tail: what we'd like to sqeeze in */ + protected def traverse(node: Node, pscope: NamespaceBinding, ind: Int): Unit = node match { + + case Text(s) if s.trim() == "" => + ; + case _:Atom[_] | _:Comment | _:EntityRef | _:ProcInstr => + makeBox( ind, node.toString().trim() ) + case g @ Group(xs) => + traverse(xs.elements, pscope, ind) + case _ => + val test = { + val sb = new StringBuilder() + Utility.toXML(node, pscope, sb, false) + if (node.attribute("http://www.w3.org/XML/1998/namespace", "space") == "preserve") + sb.toString() + else + TextBuffer.fromString(sb.toString()).toText(0)._data + } + if (childrenAreLeaves(node) && fits(test)) { + makeBox(ind, test) + } else { + val (stg, len2) = startTag(node, pscope) + val etg = endTag(node) + if (stg.length < width - cur) { // start tag fits + makeBox(ind, stg) + makeBreak() + traverse(node.child.elements, node.scope, ind + step) + makeBox(ind, etg) + } else if (len2 < width - cur) { + // + if (!lastwasbreak) sb.append('\n') // on windows: \r\n ? + lastwasbreak = true + cur = 0 +// while( cur < last ) { +// sb.append(' '); +// cur = cur + 1; +// } + + case Box(i, s) => + lastwasbreak = false + while (cur < i) { + sb.append(' ') + cur += 1 + } + sb.append(s) + case Para( s ) => + lastwasbreak = false + sb.append(s) + } + } + + // public convenience methods + + /** returns a formatted string containing well-formed XML with + * default namespace prefix mapping + * + * @param n the node to be serialized + * @return ... + */ + def format(n: Node): String = format(n, null) //Utility.defaultPrefixes(n)) + + /** Returns a formatted string containing well-formed XML with + * given namespace to prefix mapping. + * + * @param n the node to be serialized + * @param pmap the namespace to prefix mapping + * @return ... + */ + def format(n: Node, pscope: NamespaceBinding): String = { + val sb = new StringBuilder() + format(n, pscope, sb) + sb.toString() + } + + /** Returns a formatted string containing well-formed XML nodes with + * default namespace prefix mapping. + * + * @param nodes ... + * @return ... + */ + def formatNodes(nodes: Seq[Node]): String = + formatNodes(nodes, null) + + /** Returns a formatted string containing well-formed XML. + * + * @param nodes the sequence of nodes to be serialized + * @param pmap the namespace to prefix mapping + */ + def formatNodes(nodes: Seq[Node], pscope: NamespaceBinding): String = { + var sb = new StringBuilder() + formatNodes(nodes, pscope, sb) + sb.toString() + } + + /** Appends a formatted string containing well-formed XML with + * the given namespace to prefix mapping to the given stringbuffer. + * + * @param n the node to be serialized + * @param pmap the namespace to prefix mapping + * @param sb the string buffer to which to append to + */ + def formatNodes(nodes: Seq[Node], pscope: NamespaceBinding, sb: StringBuilder): Unit = + for (n <- nodes.elements) { + sb.append(format(n, pscope)) + } + +} diff --git a/src/library/scala/xml/Text.scala b/src/library/scala/xml/Text.scala new file mode 100644 index 0000000000..c766e34999 --- /dev/null +++ b/src/library/scala/xml/Text.scala @@ -0,0 +1,42 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.xml + + +/** The class Text implements an XML node for text (PCDATA). + * It is used in both non-bound and bound XML representations. + * + * @author Burak Emir + * + * @param text the text contained in this node, may not be null. + */ +case class Text(_data: String) extends Atom[String](_data) { + + if (null == data) + throw new java.lang.NullPointerException("tried to construct Text with null") + + final override def equals(x: Any) = x match { + case s:String => s.equals(data) + case s:Text => data == s.data + case _ => false + } + + /** Returns text, with some characters escaped according to the XML + * specification. + * + * @param sb ... + * @return ... + */ + override def toString(sb: StringBuilder) = + Utility.escape(data, sb) + +} diff --git a/src/library/scala/xml/Unparsed.scala b/src/library/scala/xml/Unparsed.scala new file mode 100644 index 0000000000..6bda932b89 --- /dev/null +++ b/src/library/scala/xml/Unparsed.scala @@ -0,0 +1,35 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.xml + +/** An XML node for unparsed content. It will be output verbatim, all bets + * are off regarding wellformedness etc. + * + * @author Burak Emir + * @param _data content in this node, may not be null. + */ +case class Unparsed(_data: String) extends Atom[String](_data) { + + if (null == data) + throw new java.lang.NullPointerException("tried to construct Unparsed with null") + + final override def equals(x: Any) = x match { + case s:String => s.equals(data) + case s:Text => data == s.data + case s:Unparsed => data == s.data + case _ => false + } + + /** returns text, with some characters escaped according to XML spec */ + override def toString(sb: StringBuilder) = sb append data + +} diff --git a/src/library/scala/xml/XML.scala b/src/library/scala/xml/XML.scala new file mode 100644 index 0000000000..675d4dcbb7 --- /dev/null +++ b/src/library/scala/xml/XML.scala @@ -0,0 +1,158 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.xml + + +import Predef._ +import scala.xml.parsing.NoBindingFactoryAdapter +import org.xml.sax.InputSource +import java.io.{File, FileDescriptor, FileInputStream, FileOutputStream} +import java.io.{InputStream, Reader, StringReader, Writer} + +/** The object XML provides constants, and functions to load + * and save XML elements. Use this when data binding is not desired, i.e. + * when XML is handled using Symbol nodes. + * + * @author Burak Emir + * @version 1.0, 25/04/2005 + */ +object XML { + + val xml = "xml" + val xmlns = "xmlns" + val namespace = "http://www.w3.org/XML/1998/namespace" + val preserve = "preserve" + val space = "space" + val lang = "lang" + val encoding = "ISO-8859-1" + + // functions for generic xml loading, saving + + /** loads XML from given file, using XML parser in JDK. */ + final def loadFile(file: File): Elem = + new NoBindingFactoryAdapter().loadXML(new InputSource( + new FileInputStream(file) + )) + + /** loads XML from given file descriptor, using XML parser in JDK. + * + * @param fileDesc ... + * @return ... + */ + final def loadFile(fileDesc: FileDescriptor): Elem = + new NoBindingFactoryAdapter().loadXML(new InputSource( + new FileInputStream(fileDesc) + )) + + /** loads XML from given file, using XML parser in JDK. */ + final def loadFile(fileName: String): Elem = + new NoBindingFactoryAdapter().loadXML(new InputSource( + new FileInputStream(fileName) + )); + + /** loads XML from given InputStream, using XML parser in JDK. */ + final def load( is:InputStream ): Elem = + new NoBindingFactoryAdapter().loadXML(new InputSource(is)) + + /** loads XML from given Reader, using XML parser in JDK. */ + final def load(reader: Reader): Elem = + new NoBindingFactoryAdapter().loadXML(new InputSource(reader)) + + /** loads XML from given sysID, using XML parser in JDK. */ + final def load(sysID: String): Elem = + new NoBindingFactoryAdapter().loadXML(new InputSource(sysID)) + + /** loads XML from a given input source, using XML parser in JDK. + * + * @param source ... + * @return ... + */ + final def load(source: InputSource): Elem = + new NoBindingFactoryAdapter().loadXML(source) + + /** loads XML from a string, using XML parser in JDK. */ + final def loadString(string: String): Elem = + load(new StringReader(string)) + + /** Saves XML to filename with encoding ISO-8859-1 without xml-decl without + * doctype. + * + * @param filename ... + * @param node ... + */ + final def save(filename: String, node: Node): Unit = + save(filename, node, encoding) + + /** saves XML to filename with given encoding, without xml-decl without + * doctype. + * + * @param filename ... + * @param node ... + * @param enc ... + */ + final def save(filename: String, node: Node, enc: String): Unit = + saveFull(filename, node, enc, false, null); + + /** saves a node to a file with given filename using encoding iso-8859-1 + * optionally with xmldecl and doctype declaration. + * + * @param filename the filename + * @param node the xml node we want to write + * @param xmlDecl if true, write xml declaration + * @param doctype if not null, write doctype declaration + */ + final def saveFull(filename: String, node: Node, xmlDecl: Boolean, doctype: dtd.DocType): Unit = + saveFull(filename, node, encoding, xmlDecl, doctype) + + /** Saves a node to a file with given filename using given encoding + * optionally with xmldecl and doctype declaration. + * + * @param filename the filename + * @param node the xml node we want to write + * @param enc encoding to use + * @param xmlDecl if true, write xml declaration + * @param doctype if not null, write doctype declaration + */ + + final def saveFull(filename: String, node: Node, enc: String, xmlDecl: Boolean, doctype: dtd.DocType) { + var fos: FileOutputStream = null + var w: Writer = null + try { + // using NIO classes of JDK 1.4 + import java.io.{FileOutputStream, Writer} + import java.nio.channels.{Channels, FileChannel} + + fos = new FileOutputStream(filename) + w = Channels.newWriter(fos.getChannel(), enc) + write(w, node, enc, xmlDecl, doctype) + } finally { + w.close() + fos.close() + } + } + + /** Writes the given node using writer, optionally with xml decl and doctype. + * It's the caller's responsibility to close the writer. + * + * @param w the writer + * @param node the xml node we want to write + * @param enc the string to be used in xmlDecl + * @param xmlDecl if true, write xml declaration + * @param doctype if not null, write doctype declaration + */ + final def write(w: java.io.Writer, node: Node, enc: String, xmlDecl: Boolean, doctype: dtd.DocType) { + /* TODO: optimize by giving writer parameter to toXML*/ + if (xmlDecl) w.write("\n") + if (doctype ne null) w.write( doctype.toString() + "\n") + w.write(Utility.toXML(node)) + } +} diff --git a/src/library/scala/xml/include/XIncludeException.scala b/src/library/scala/xml/include/XIncludeException.scala new file mode 100644 index 0000000000..5563d68c38 --- /dev/null +++ b/src/library/scala/xml/include/XIncludeException.scala @@ -0,0 +1,64 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + +package scala.xml.include + +/** + *

+ * XIncludeException is the generic superclass + * for all checked exceptions that may be thrown as a result + * of a violation of XInclude's rules. + *

+ *

+ * Constructs an XIncludeException with the specified detail + * message. The error message string message can later be + * retrieved by the {@link java.lang.Throwable#getMessage} + * method of class java.lang.Throwable. + *

+ * + * @param message the detail message. + */ +class XIncludeException(message: String) extends Exception(message) { + + /** + * uses null as its error detail message. + */ + def this() = this(null) + + private var rootCause: Throwable = null + + /** + * When an IOException, MalformedURLException + * or other generic exception is thrown while processing an XML document + * for XIncludes, it is customarily replaced + * by some form of XIncludeException. + * This method allows you to store the original exception. + * + * @param nestedException the underlying exception which + caused the XIncludeException to be thrown + */ + def setRootCause(nestedException: Throwable ) { + this.rootCause = nestedException + } + + /** + * When an IOException, MalformedURLException + * or other generic exception is thrown while processing an XML document + * for XIncludes, it is customarily replaced + * by some form of XIncludeException. + * This method allows you to retrieve the original exception. + * It returns null if no such exception caused this XIncludeException. + * + * @return Throwable the underlying exception which caused the + * XIncludeException to be thrown + */ + def getRootCause(): Throwable = this.rootCause + +} diff --git a/src/library/scala/xml/include/parsing/ConstructingParser.scala b/src/library/scala/xml/include/parsing/ConstructingParser.scala new file mode 100644 index 0000000000..b7c88c79ec --- /dev/null +++ b/src/library/scala/xml/include/parsing/ConstructingParser.scala @@ -0,0 +1,67 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.xml.parsing + +import java.io.File + +import scala.io.Source + +object ConstructingParser { + + def fromFile(inp: File, preserveWS: Boolean) = { + val p = new ConstructingParser(Source.fromFile(inp), preserveWS) + p.nextch + p + } + + def fromSource(inp: Source, preserveWS: Boolean) = { + val p = new ConstructingParser(inp, preserveWS) + p.nextch + p + } +} + +/** An xml parser. parses XML and invokes callback methods of a MarkupHandler. + * Don't forget to call next.ch on a freshly instantiated parser in order to + * initialize it. If you get the parser from the object method, initialization + * is already done for you. + * + *
+object parseFromURL {
+  def main(args:Array[String]): Unit = {
+    val url = args(0);
+    val src = scala.io.Source.fromURL(url);
+    val cpa = scala.xml.parsing.ConstructingParser.fromSource(src, false); // fromSource initializes automatically
+    val doc = cpa.document();
+
+    // let's see what it is
+    val ppr = new scala.xml.PrettyPrinter(80,5);
+    val ele = doc.docElem;
+    Console.println("finished parsing");
+    val out = ppr.format(ele);
+    Console.println(out);
+  }
+}
+
+ */ +class ConstructingParser(inp: Source, presWS:Boolean) +extends ConstructingHandler +with ExternalSources +with MarkupParser { + + // default impl. of Logged + override def log(msg: String): Unit = {} + + val preserveWS = presWS + val input = inp +} + diff --git a/src/library/scala/xml/include/parsing/ExternalSources.scala b/src/library/scala/xml/include/parsing/ExternalSources.scala new file mode 100644 index 0000000000..cbfee413e6 --- /dev/null +++ b/src/library/scala/xml/include/parsing/ExternalSources.scala @@ -0,0 +1,82 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.xml.parsing + +import java.net.URL + +import scala.io.Source + +/** + * @author Burak Emir + * @version 1.0 + */ +trait ExternalSources { self: ExternalSources with MarkupParser with MarkupHandler => + + private def externalSourceFromURL(url: URL): Source = { + import java.io.{BufferedReader, InputStreamReader} + val in = + new BufferedReader( + new InputStreamReader( + url.openStream())) + + //@todo: replace this hack with proper Source implementation + + val str = new StringBuilder() + var inputLine: String = null + + //while (inputLine = in.readLine()) != null) { + while ({inputLine = in.readLine(); inputLine} ne null) { + // Console.println(inputLine) // DEBUG + str.append(inputLine) + str.append('\n') // readable output + } + in.close() + + class MyClass extends Source { + + def newIter = new Iterator[Char] { + var i = -1 + private val len = str.length-1 + def hasNext = i < len + def next = { i += 1; str.charAt(i) } + } + + val iter = newIter + + def reset: Source = new MyClass + + /*override var*/ descr = url.toExternalForm() + } + + new MyClass + } + + /** ... + * + * @param systemId ... + * @return ... + */ + def externalSource(systemId: String): Source = { + if (systemId startsWith "http:") + return externalSourceFromURL(new URL(systemId)) + + var fileStr = input.descr + + if (input.descr startsWith "file:") { + fileStr = input.descr.substring(5, input.descr.length) + } else + fileStr = fileStr.substring(0, + fileStr.lastIndexOf(java.io.File.separator)+1) + Source.fromFile(fileStr + systemId) + } + +} diff --git a/src/library/scala/xml/include/parsing/FactoryAdapter.scala b/src/library/scala/xml/include/parsing/FactoryAdapter.scala new file mode 100644 index 0000000000..32c58c3ff6 --- /dev/null +++ b/src/library/scala/xml/include/parsing/FactoryAdapter.scala @@ -0,0 +1,321 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.xml.parsing + +import java.io.{InputStream, Reader, File, FileDescriptor, FileInputStream} +import scala.collection.mutable.{HashMap,Stack} + +import org.xml.sax.{Attributes, InputSource} + +import org.xml.sax.SAXException +import org.xml.sax.SAXNotRecognizedException +import org.xml.sax.SAXNotSupportedException +import org.xml.sax.SAXParseException +import org.xml.sax.helpers.DefaultHandler + +import javax.xml.parsers.SAXParserFactory +import javax.xml.parsers.ParserConfigurationException +import javax.xml.parsers.SAXParser + + +/** SAX adapter class, for use with Java SAX parser. Keeps track of + * namespace bindings, without relying on namespace handling of the + * underlying SAX parser. + */ +abstract class FactoryAdapter extends DefaultHandler() { + + val buffer = new StringBuilder() + val attribStack = new Stack[MetaData] + val hStack = new Stack[Node] // [ element ] contains siblings + val tagStack = new Stack[String] + var scopeStack = new Stack[NamespaceBinding] + + var curTag : String = null + var capture: Boolean = false + + // abstract methods + + /** Tests if an XML element contains text. + * @return true if element named localName contains text. + */ + def nodeContainsText(localName: String): Boolean // abstract + + /** creates an new non-text(tree) node. + * @param elemName + * @param attribs + * @param chIter + * @return a new XML element. + */ + def createNode(pre: String, elemName: String, attribs: MetaData, + scope: NamespaceBinding, chIter: List[Node]): Node //abstract + + /** creates a Text node. + * @param text + * @return a new Text node. + */ + def createText(text: String): Text // abstract + + /** creates a new processing instruction node. + */ + def createProcInstr(target: String, data: String): Seq[ProcInstr] + + // + // ContentHandler methods + // + + val normalizeWhitespace = false + + /** Characters. + * @param ch + * @param offset + * @param length + */ + override def characters(ch: Array[Char], offset: Int, length: Int): Unit = { + if (capture) { + if (normalizeWhitespace) { + // normalizing whitespace is not compliant, but useful */ + var i: Int = offset + var ws = false + while (i < offset + length) { + if (ch(i).isWhitespace) { + if (!ws) { + buffer.append(' ') + ws = true + } + } else { + buffer.append(ch(i)) + ws = false + } + i += 1 + } + } else { // compliant:report every character + buffer.append(ch, offset, length) + } + } + } + + //var elemCount = 0; //STATISTICS + + /* ContentHandler methods */ + + /* Start prefix mapping - use default impl. + def startPrefixMapping( prefix:String , uri:String ):Unit = {} + */ + + /* Start element. */ + override def startElement(uri: String, _localName: String, + qname: String, attributes: Attributes): Unit = { + /*elemCount = elemCount + 1; STATISTICS */ + captureText() + //Console.println("FactoryAdapter::startElement("+uri+","+_localName+","+qname+","+attributes+")"); + tagStack.push(curTag) + curTag = qname; //localName ; + + val colon = qname.indexOf(':'.asInstanceOf[Int]) + val localName = if(-1 == colon) qname else qname.substring(colon+1,qname.length()) + + //Console.println("FactoryAdapter::startElement - localName ="+localName); + + capture = nodeContainsText(localName) + + hStack.push(null) + var m: MetaData = Null + + var scpe = scopeStack.top + for (i <- List.range(0, attributes.getLength())) { + //val attrType = attributes.getType(i); // unused for now + val qname = attributes.getQName(i) + val value = attributes.getValue(i) + val colon = qname.indexOf(':'.asInstanceOf[Int]) + if (-1 != colon) { // prefixed attribute + val pre = qname.substring(0, colon) + val key = qname.substring(colon+1, qname.length()) + if ("xmlns" /*XML.xmlns*/ == pre) + scpe = value.length() match { + case 0 => new NamespaceBinding(key, null, scpe) + case _ => new NamespaceBinding(key, value, scpe) + } + else + m = new PrefixedAttribute(pre, key, Text(value), m) + } else if ("xmlns" /*XML.xmlns*/ == qname) + scpe = value.length() match { + case 0 => new NamespaceBinding(null, null, scpe) + case _ => new NamespaceBinding(null, value, scpe) + } + else + m = new UnprefixedAttribute(qname, Text(value), m) + } + scopeStack.push(scpe) + attribStack.push(m) + () + } // startElement(String,String,String,Attributes) + + + /** captures text, possibly normalizing whitespace + */ + def captureText(): Unit = { + if (capture) { + val text = buffer.toString() + if (text.length() > 0 && !text.equals(" ")) { + hStack.push(createText(text)) + } + } + buffer.setLength(0) + } + + /** End element. + * @param uri + * @param localName + * @param qname + * @throws org.xml.sax.SAXException if .. + */ + override def endElement(uri: String , _localName: String , qname: String): Unit = { + captureText() + + val metaData = attribStack.pop + + // reverse order to get it right + var v: List[Node] = Nil + var child: Node = hStack.pop + while (child ne null) { + v = child::v + child = hStack.pop + } + + val colon = qname.indexOf(':'.asInstanceOf[Int]) + val localName = + if (-1 == colon) qname + else qname.substring(colon+1, qname.length()) + + val scp = scopeStack.pop + // create element + val pre = if (-1 == colon) null else qname.substring(0, colon) + rootElem = createNode(pre, localName, metaData, scp, v) + + hStack.push(rootElem) + + // set + curTag = tagStack.pop + + capture = + if (curTag ne null) nodeContainsText(curTag) // root level + else false + } // endElement(String,String,String) + + /** Processing instruction. + */ + override def processingInstruction(target: String, data: String) { + for (pi <- createProcInstr(target, data)) + hStack.push(pi) + } + + // + // ErrorHandler methods + // + + /** Warning.*/ + override def warning(ex: SAXParseException): Unit = { + // ignore warning, crimson warns even for entity resolution! + //printError("Warning", ex); + } + + /** Error. */ + override def error(ex: SAXParseException): Unit = + printError("Error", ex) + + /** Fatal error.*/ + override def fatalError(ex: SAXParseException): Unit = + printError("Fatal Error", ex) + + // + // Protected methods + // + + /** Prints the error message */ + protected def printError(errtype: String, ex: SAXParseException): Unit = + Console.withOut(Console.err) { + Console.print("[") + Console.print(errtype) + Console.print("] ") + + var systemId = ex.getSystemId() + if (systemId ne null) { + val index = systemId.lastIndexOf('/'.asInstanceOf[Int]) + if (index != -1) + systemId = systemId.substring(index + 1) + //Console.print(systemId) + } + + Console.print(':') + Console.print(ex.getLineNumber()) + Console.print(':') + Console.print(ex.getColumnNumber()) + Console.print(": ") + Console.print(ex.getMessage()) + Console.println + Console.flush + } + + var rootElem: Node = null:Node + + //FactoryAdapter + // MAIN + // + + /** load XML document + * @param source + * @return a new XML document object + */ + def loadXML(source: InputSource): Node = { + // create parser + val parser: SAXParser = try { + val f = SAXParserFactory.newInstance() + f.setNamespaceAware(false) + f.newSAXParser() + } catch { + case e: Exception => + Console.err.println("error: Unable to instantiate parser") + throw e + } + + // parse file + scopeStack.push(TopScope) + parser.parse(source, this) + scopeStack.pop + return rootElem + } // loadXML + + /** loads XML from given file */ + def loadFile(file: File): Node = + loadXML(new InputSource(new FileInputStream(file))) + + /** loads XML from given file descriptor */ + def loadFile(fileDesc: FileDescriptor): Node = + loadXML(new InputSource(new FileInputStream(fileDesc))) + + /** loads XML from given file */ + def loadFile(fileName: String): Node = + loadXML(new InputSource(new FileInputStream(fileName))) + + /** loads XML from given InputStream */ + def load(is: InputStream): Node = + loadXML(new InputSource(is)) + + /** loads XML from given Reader */ + def load(reader: Reader): Node = + loadXML(new InputSource(reader)) + + /** loads XML from given sysID */ + def load(sysID: String): Node = + loadXML(new InputSource(sysID)) + +} diff --git a/src/library/scala/xml/include/parsing/FatalError.scala b/src/library/scala/xml/include/parsing/FatalError.scala new file mode 100644 index 0000000000..2768becb8b --- /dev/null +++ b/src/library/scala/xml/include/parsing/FatalError.scala @@ -0,0 +1,15 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.xml.parsing; + + +case class FatalError(msg:String) extends java.lang.RuntimeException(msg); diff --git a/src/library/scala/xml/include/parsing/MarkupParser.scala b/src/library/scala/xml/include/parsing/MarkupParser.scala new file mode 100644 index 0000000000..541cc65ac2 --- /dev/null +++ b/src/library/scala/xml/include/parsing/MarkupParser.scala @@ -0,0 +1,1215 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.xml.parsing + +import scala.io.Source +import scala.xml.dtd._ + +/** + * An XML parser. + * + * Parses XML 1.0, invokes callback methods of a MarkupHandler + * and returns whatever the markup handler returns. Use + * ConstructingParser if you just want to parse XML to + * construct instances of scala.xml.Node. + * + * While XML elements are returned, DTD declarations - if handled - are + * collected using side-effects. + * + * @author Burak Emir + * @version 1.0 + */ +trait MarkupParser extends AnyRef with TokenTests { self: MarkupParser with MarkupHandler => + + val input: Source + + /** if true, does not remove surplus whitespace */ + val preserveWS: Boolean + + def externalSource(systemLiteral: String): Source + + // + // variables, values + // + + var curInput: Source = input + + /** the handler of the markup, returns this */ + private val handle: MarkupHandler = this + + /** stack of inputs */ + var inpStack: List[Source] = Nil + + /** holds the position in the source file */ + var pos: Int = _ + + + /* used when reading external subset */ + var extIndex = -1 + + /** holds temporary values of pos */ + var tmppos: Int = _ + + /** holds the next character */ + var ch: Char = _ + + /** character buffer, for names */ + protected val cbuf = new StringBuilder() + + var dtd: DTD = null + + protected var doc: Document = null + + var eof: Boolean = false + + // + // methods + // + + /** <? prolog ::= xml S ... ?> + */ + def xmlProcInstr(): MetaData = { + xToken("xml") + xSpace + val (md,scp) = xAttributes(TopScope) + if (scp != TopScope) + reportSyntaxError("no xmlns definitions here, please."); + xToken('?') + xToken('>') + md + } + + /** <? prolog ::= xml S? + * // this is a bit more lenient than necessary... + */ + def prolog(): Tuple3[Option[String], Option[String], Option[Boolean]] = { + + //Console.println("(DEBUG) prolog") + var n = 0 + var info_ver: Option[String] = None + var info_enc: Option[String] = None + var info_stdl: Option[Boolean] = None + + var m = xmlProcInstr() + + xSpaceOpt + + m("version") match { + case null => ; + case Text("1.0") => info_ver = Some("1.0"); n += 1 + case _ => reportSyntaxError("cannot deal with versions != 1.0") + } + + m("encoding") match { + case null => ; + case Text(enc) => + if (!isValidIANAEncoding(enc)) + reportSyntaxError("\"" + enc + "\" is not a valid encoding") + else { + info_enc = Some(enc) + n += 1 + } + } + m("standalone") match { + case null => ; + case Text("yes") => info_stdl = Some(true); n += 1 + case Text("no") => info_stdl = Some(false); n += 1 + case _ => reportSyntaxError("either 'yes' or 'no' expected") + } + + if (m.length - n != 0) { + reportSyntaxError("VersionInfo EncodingDecl? SDDecl? or '?>' expected!"); + } + //Console.println("[MarkupParser::prolog] finished parsing prolog!"); + Tuple3(info_ver,info_enc,info_stdl) + } + + /** prolog, but without standalone */ + def textDecl(): Tuple2[Option[String],Option[String]] = { + + var info_ver: Option[String] = None + var info_enc: Option[String] = None + + var m = xmlProcInstr() + var n = 0 + + m("version") match { + case null => ; + case Text("1.0") => info_ver = Some("1.0"); n += 1 + case _ => reportSyntaxError("cannot deal with versions != 1.0") + } + + m("encoding") match { + case null => ; + case Text(enc) => + if (!isValidIANAEncoding(enc)) + reportSyntaxError("\"" + enc + "\" is not a valid encoding") + else { + info_enc = Some(enc) + n += 1 + } + } + + if (m.length - n != 0) { + reportSyntaxError("VersionInfo EncodingDecl? or '?>' expected!"); + } + //Console.println("[MarkupParser::textDecl] finished parsing textdecl"); + Tuple2(info_ver, info_enc); + } + + /** + *[22] prolog ::= XMLDecl? Misc* (doctypedecl Misc*)? + *[23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>' + *[24] VersionInfo ::= S 'version' Eq ("'" VersionNum "'" | '"' VersionNum '"') + *[25] Eq ::= S? '=' S? + *[26] VersionNum ::= '1.0' + *[27] Misc ::= Comment | PI | S + */ + + def document(): Document = { + + //Console.println("(DEBUG) document") + doc = new Document() + + this.dtd = null + var info_prolog: Tuple3[Option[String], Option[String], Option[Boolean]] = Tuple3(None, None, None); + if ('<' != ch) { + reportSyntaxError("< expected") + return null + } + + nextch // is prolog ? + var children: NodeSeq = null + if ('?' == ch) { + //Console.println("[MarkupParser::document] starts with xml declaration"); + nextch; + info_prolog = prolog() + doc.version = info_prolog._1 + doc.encoding = info_prolog._2 + doc.standAlone = info_prolog._3 + + children = content(TopScope) // DTD handled as side effect + } else { + //Console.println("[MarkupParser::document] does not start with xml declaration"); + // + + val ts = new NodeBuffer(); + content1(TopScope, ts); // DTD handled as side effect + ts &+ content(TopScope); + children = NodeSeq.fromSeq(ts); + } + //Console.println("[MarkupParser::document] children now: "+children.toList); + var elemCount = 0; + var theNode: Node = null; + for (c <- children) c match { + case _:ProcInstr => ; + case _:Comment => ; + case _:EntityRef => // todo: fix entities, shouldn't be "special" + reportSyntaxError("no entity references alllowed here"); + case s:SpecialNode => + if (s.toString().trim().length > 0) //non-empty text nodes not allowed + elemCount = elemCount + 2; + case m:Node => + elemCount = elemCount + 1; + theNode = m; + } + if (1 != elemCount) { + reportSyntaxError("document must contain exactly one element") + Console.println(children.toList) + } + + doc.children = children + doc.docElem = theNode + doc + } + + /** append Unicode character to name buffer*/ + protected def putChar(c: Char) = cbuf.append(c) + + //var xEmbeddedBlock = false; + + /** this method assign the next character to ch and advances in input */ + def nextch { + if (curInput.hasNext) { + ch = curInput.next + pos = curInput.pos + } else { + val ilen = inpStack.length; + //Console.println(" ilen = "+ilen+ " extIndex = "+extIndex); + if ((ilen != extIndex) && (ilen > 0)) { + /** for external source, inpStack == Nil ! need notify of eof! */ + pop() + } else { + eof = true + ch = 0.asInstanceOf[Char] + } + } + } + + //final val enableEmbeddedExpressions: Boolean = false; + + /** munch expected XML token, report syntax error for unexpected + */ + def xToken(that: Char) { + if (ch == that) + nextch + else { + reportSyntaxError("'" + that + "' expected instead of '" + ch + "'") + error("FATAL") + } + } + + def xToken(that: Seq[Char]): Unit = { + val it = that.elements; + while (it.hasNext) + xToken(it.next); + } + + /** parse attribute and create namespace scope, metadata + * [41] Attributes ::= { S Name Eq AttValue } + */ + def xAttributes(pscope:NamespaceBinding): (MetaData,NamespaceBinding) = { + var scope: NamespaceBinding = pscope + var aMap: MetaData = Null + while (isNameStart(ch)) { + val pos = this.pos + + val qname = xName + val _ = xEQ + val value = xAttributeValue() + + Utility.prefix(qname) match { + case Some("xmlns") => + val prefix = qname.substring(6 /*xmlns:*/ , qname.length); + scope = new NamespaceBinding(prefix, value, scope); + + case Some(prefix) => + val key = qname.substring(prefix.length+1, qname.length); + aMap = new PrefixedAttribute(prefix, key, Text(value), aMap); + + case _ => + if( qname == "xmlns" ) + scope = new NamespaceBinding(null, value, scope); + else + aMap = new UnprefixedAttribute(qname, Text(value), aMap); + } + + if ((ch != '/') && (ch != '>') && ('?' != ch)) + xSpace; + } + + if(!aMap.wellformed(scope)) + reportSyntaxError( "double attribute"); + + (aMap,scope) + } + + /** attribute value, terminated by either ' or ". value may not contain <. + * AttValue ::= `'` { _ } `'` + * | `"` { _ } `"` + */ + def xAttributeValue(): String = { + val endch = ch + nextch + while (ch != endch) { + if ('<' == ch) + reportSyntaxError( "'<' not allowed in attrib value" ); + putChar(ch) + nextch + } + nextch + val str = cbuf.toString() + cbuf.length = 0 + + // well-formedness constraint + normalizeAttributeValue(str) + } + + /** entity value, terminated by either ' or ". value may not contain <. + * AttValue ::= `'` { _ } `'` + * | `"` { _ } `"` + */ + def xEntityValue(): String = { + val endch = ch + nextch + while (ch != endch) { + putChar(ch) + nextch + } + nextch + val str = cbuf.toString() + cbuf.length = 0 + str + } + + + /** parse a start or empty tag. + * [40] STag ::= '<' Name { S Attribute } [S] + * [44] EmptyElemTag ::= '<' Name { S Attribute } [S] + */ + protected def xTag(pscope:NamespaceBinding): Tuple3[String, MetaData, NamespaceBinding] = { + val qname = xName + + xSpaceOpt + val (aMap: MetaData, scope: NamespaceBinding) = { + if (isNameStart(ch)) + xAttributes(pscope) + else + (Null, pscope) + } + (qname, aMap, scope) + } + + /** [42] '<' xmlEndTag ::= '<' '/' Name S? '>' + */ + def xEndTag(n: String) = { + xToken('/') + val m = xName + if (n != m) + reportSyntaxError("expected closing tag of " + n/* +", not "+m*/); + xSpaceOpt + xToken('>') + } + + /** '<! CharData ::= [CDATA[ ( {char} - {char}"]]>"{char} ) ']]>' + * + * see [15] + */ + def xCharData: NodeSeq = { + xToken("[CDATA[") + val pos1 = pos + val sb: StringBuilder = new StringBuilder() + while (true) { + if (ch==']' && + { sb.append(ch); nextch; ch == ']' } && + { sb.append(ch); nextch; ch == '>' } ) { + sb.length = sb.length - 2 + nextch; + return handle.text( pos1, sb.toString() ); + } else sb.append( ch ); + nextch; + } + throw FatalError("this cannot happen"); + }; + + /** CharRef ::= "&#" '0'..'9' {'0'..'9'} ";" + * | "&#x" '0'..'9'|'A'..'F'|'a'..'f' { hexdigit } ";" + * + * see [66] + */ + def xCharRef(ch: () => Char, nextch: () => Unit): String = { + Utility.parseCharRef(ch, nextch, reportSyntaxError _) + /* + val hex = (ch() == 'x') && { nextch(); true }; + val base = if (hex) 16 else 10; + var i = 0; + while (ch() != ';') { + ch() match { + case '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' => + i = i * base + Character.digit( ch(), base ); + case 'a' | 'b' | 'c' | 'd' | 'e' | 'f' + | 'A' | 'B' | 'C' | 'D' | 'E' | 'F' => + if (! hex) + reportSyntaxError("hex char not allowed in decimal char ref\n" + +"Did you mean to write &#x ?"); + else + i = i * base + Character.digit(ch(), base); + case _ => + reportSyntaxError("character '" + ch() + " not allowed in char ref\n"); + } + nextch(); + } + new String(Array(i.asInstanceOf[char])) + */ + } + + + /** Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->' + * + * see [15] + */ + def xComment: NodeSeq = { + val sb: StringBuilder = new StringBuilder() + xToken('-') + xToken('-') + while (true) { + if (ch == '-' && { sb.append(ch); nextch; ch == '-' }) { + sb.length = sb.length - 1 + nextch + xToken('>') + return handle.comment(pos, sb.toString()) + } else sb.append(ch) + nextch + } + throw FatalError("this cannot happen") + } + + /* todo: move this into the NodeBuilder class */ + def appendText(pos: Int, ts: NodeBuffer, txt: String): Unit = { + if (preserveWS) + ts &+ handle.text(pos, txt); + else + for (t <- TextBuffer.fromString(txt).toText) { + ts &+ handle.text(pos, t.text); + } + } + + /** '<' content1 ::= ... */ + def content1(pscope: NamespaceBinding, ts: NodeBuffer): Unit = + ch match { + case '!' => + nextch + if ('[' == ch) // CDATA + ts &+ xCharData + else if ('D' == ch) // doctypedecl, parse DTD // @todo REMOVE HACK + parseDTD() + else // comment + ts &+ xComment + case '?' => // PI + nextch + ts &+ xProcInstr + case _ => + ts &+ element1(pscope) // child + } + + /** content1 ::= '<' content1 | '&' charref ... */ + def content(pscope: NamespaceBinding): NodeSeq = { + var ts = new NodeBuffer + var exit = eof + while (! exit) { + //Console.println("in content, ch = '"+ch+"' line="+scala.io.Position.line(pos)); + /* if( xEmbeddedBlock ) { + ts.append( xEmbeddedExpr ); + } else {*/ + tmppos = pos; + exit = eof; + if(!eof) + ch match { + case '<' => // another tag + //Console.println("before ch = '"+ch+"' line="+scala.io.Position.line(pos)+" pos="+pos); + nextch; + //Console.println("after ch = '"+ch+"' line="+scala.io.Position.line(pos)+" pos="+pos); + + if('/' ==ch) + exit = true; // end tag + else + content1(pscope, ts) + //case '{' => +/* if( xCheckEmbeddedBlock ) { + ts.appendAll(xEmbeddedExpr); + } else {*/ + // val str = new StringBuilder("{"); + // str.append(xText); + // appendText(tmppos, ts, str.toString()); + /*}*/ + // postcond: xEmbeddedBlock == false! + case '&' => // EntityRef or CharRef + nextch; + ch match { + case '#' => // CharacterRef + nextch; + val theChar = handle.text( tmppos, + xCharRef ({ ()=> ch },{ () => nextch }) ); + xToken(';'); + ts &+ theChar ; + case _ => // EntityRef + val n = xName + xToken(';') + n match { + case "lt" => ts &+ '<' + case "gt" => ts &+ '>' + case "amp" => ts &+ '&' + case "quot" => ts &+ '"' + case _ => + /* + ts + handle.entityRef( tmppos, n ) ; + */ + push(n) + } + } + case _ => // text content + //Console.println("text content?? pos = "+pos); + appendText(tmppos, ts, xText); + // here xEmbeddedBlock might be true + } + /*}*/ + } + val list = ts.toList + // 2do: optimize seq repr. + new NodeSeq { + val theSeq = list + } + } // content(NamespaceBinding) + + /** externalID ::= SYSTEM S syslit + * PUBLIC S pubid S syslit + */ + + def externalID(): ExternalID = ch match { + case 'S' => + nextch + xToken("YSTEM") + xSpace + val sysID = systemLiteral() + new SystemID(sysID) + case 'P' => + nextch; xToken("UBLIC") + xSpace + val pubID = pubidLiteral() + xSpace + val sysID = systemLiteral() + new PublicID(pubID, sysID) + } + + + /** parses document type declaration and assigns it to instance variable + * dtd. + * + * <! parseDTD ::= DOCTYPE name ... > + */ + def parseDTD(): Unit = { // dirty but fast + //Console.println("(DEBUG) parseDTD"); + var extID: ExternalID = null + if (this.dtd ne null) + reportSyntaxError("unexpected character (DOCTYPE already defined"); + xToken("DOCTYPE") + xSpace + val n = xName + xSpace + //external ID + if ('S' == ch || 'P' == ch) { + extID = externalID() + xSpaceOpt + } + + /* parse external subset of DTD + */ + + if ((null != extID) && isValidating) { + + pushExternal(extID.systemId) + //val extSubsetSrc = externalSource( extID.systemId ); + + extIndex = inpStack.length + /* + .indexOf(':') != -1) { // assume URI + Source.fromFile(new java.net.URI(extID.systemLiteral)); + } else { + Source.fromFile(extID.systemLiteral); + } + */ + //Console.println("I'll print it now"); + //val old = curInput; + //tmppos = curInput.pos; + //val oldch = ch; + //curInput = extSubsetSrc; + //pos = 0; + //nextch; + + extSubset() + + pop() + + extIndex = -1 + + //curInput = old; + //pos = curInput.pos; + //ch = curInput.ch; + //eof = false; + //while(extSubsetSrc.hasNext) + //Console.print(extSubsetSrc.next); + + //Console.println("returned from external, current ch = "+ch ) + } + + if ('[' == ch) { // internal subset + nextch + /* TODO */ + //Console.println("hello"); + intSubset() + //while(']' != ch) + // nextch; + // TODO: do the DTD parsing?? ?!?!?!?!! + xToken(']') + xSpaceOpt + } + xToken('>') + this.dtd = new DTD { + /*override var*/ externalID = extID + /*override val */decls = handle.decls.reverse + } + //this.dtd.initializeEntities(); + if (doc ne null) + doc.dtd = this.dtd + + handle.endDTD(n) + } + + def element(pscope: NamespaceBinding): NodeSeq = { + xToken('<') + element1(pscope) + } + + /** '<' element ::= xmlTag1 '>' { xmlExpr | '{' simpleExpr '}' } ETag + * | xmlTag1 '/' '>' + */ + def element1(pscope: NamespaceBinding): NodeSeq = { + val pos = this.pos + val Tuple3(qname, aMap, scope) = xTag(pscope) + val Tuple2(pre, local) = Utility.prefix(qname) match { + case Some(p) => (p,qname.substring(p.length+1, qname.length)) + case _ => (null,qname) + } + val ts = { + if (ch == '/') { // empty element + xToken('/') + xToken('>') + handle.elemStart(pos, pre, local, aMap, scope) + NodeSeq.Empty + } + else { // element with content + xToken('>') + handle.elemStart(pos, pre, local, aMap, scope) + val tmp = content(scope) + xEndTag(qname) + tmp + } + } + val res = handle.elem(pos, pre, local, aMap, scope, ts) + handle.elemEnd(pos, pre, local) + res + } + + //def xEmbeddedExpr: MarkupType; + + /** Name ::= (Letter | '_' | ':') (NameChar)* + * + * see [5] of XML 1.0 specification + */ + def xName: String = { + if (isNameStart(ch)) { + while (isNameChar(ch)) { + putChar(ch) + nextch + } + val n = cbuf.toString().intern() + cbuf.length = 0 + n + } else { + reportSyntaxError("name expected") + "" + } + } + + /** scan [S] '=' [S]*/ + def xEQ = { xSpaceOpt; xToken('='); xSpaceOpt } + + /** skip optional space S? */ + def xSpaceOpt = while (isSpace(ch) && !eof) { nextch; } + + /** scan [3] S ::= (#x20 | #x9 | #xD | #xA)+ */ + def xSpace = + if (isSpace(ch)) { nextch; xSpaceOpt } + else reportSyntaxError("whitespace expected") + + /** '<?' ProcInstr ::= Name [S ({Char} - ({Char}'>?' {Char})]'?>' + * + * see [15] + */ + def xProcInstr: NodeSeq = { + val sb:StringBuilder = new StringBuilder() + val n = xName + if (isSpace(ch)) { + xSpace + while (true) { + if (ch == '?' && { sb.append( ch ); nextch; ch == '>' }) { + sb.length = sb.length - 1; + nextch; + return handle.procInstr(tmppos, n, sb.toString); + } else + sb.append(ch); + nextch + } + }; + xToken('?') + xToken('>') + handle.procInstr(tmppos, n, sb.toString) + } + + /** parse character data. + * precondition: xEmbeddedBlock == false (we are not in a scala block) + */ + def xText: String = { + //if( xEmbeddedBlock ) throw FatalError("internal error: encountered embedded block"); // assert + + /*if( xCheckEmbeddedBlock ) + return "" + else {*/ + //Console.println("in xText! ch = '"+ch+"'"); + var exit = false; + while (! exit) { + //Console.println("LOOP in xText! ch = '"+ch+"' + pos="+pos); + putChar(ch); + val opos = pos; + nextch; + + //Console.println("STILL LOOP in xText! ch = '"+ch+"' + pos="+pos+" opos="+opos); + + + exit = eof || /*{ nextch; xCheckEmbeddedBlock }||*/( ch == '<' ) || ( ch == '&' ); + } + val str = cbuf.toString(); + cbuf.length = 0; + str + /*}*/ + } + + /** attribute value, terminated by either ' or ". value may not contain <. + * AttValue ::= `'` { _ } `'` + * | `"` { _ } `"` + */ + def systemLiteral(): String = { + val endch = ch + if (ch != '\'' && ch != '"') + reportSyntaxError("quote ' or \" expected"); + nextch + while (ch != endch) { + putChar(ch) + nextch + } + nextch + val str = cbuf.toString() + cbuf.length = 0 + str + } + + + /* [12] PubidLiteral ::= '"' PubidChar* '"' | "'" (PubidChar - "'")* "'" */ + def pubidLiteral(): String = { + val endch = ch + if (ch!='\'' && ch != '"') + reportSyntaxError("quote ' or \" expected"); + nextch + while (ch != endch) { + putChar(ch) + //Console.println("hello '"+ch+"'"+isPubIDChar(ch)); + if (!isPubIDChar(ch)) + reportSyntaxError("char '"+ch+"' is not allowed in public id"); + nextch + } + nextch + val str = cbuf.toString() + cbuf.length = 0 + str + } + + // + // dtd parsing + // + + def extSubset(): Unit = { + var textdecl:Tuple2[Option[String],Option[String]] = null; + if (ch=='<') { + nextch + if (ch=='?') { + nextch + textdecl = textDecl() + } else + markupDecl1() + } + while (!eof) + markupDecl() + } + + def markupDecl1() = { + def doInclude() = { + xToken('['); while(']' != ch) markupDecl(); nextch // ']' + } + def doIgnore() = { + xToken('['); while(']' != ch) nextch; nextch; // ']' + } + if ('?' == ch) { + nextch + xProcInstr // simply ignore processing instructions! + } else { + xToken('!') + ch match { + case '-' => + xComment // ignore comments + + case 'E' => + nextch + if ('L' == ch) { + nextch + elementDecl() + } else + entityDecl() + + case 'A' => + nextch + attrDecl() + + case 'N' => + nextch + notationDecl() + + case '[' if inpStack.length >= extIndex => + nextch + xSpaceOpt + ch match { + case '%' => + nextch + val ent = xName + xToken(';') + xSpaceOpt + /* + Console.println("hello, pushing!"); + { + val test = replacementText(ent); + while(test.hasNext) + Console.print(test.next); + } */ + push(ent) + xSpaceOpt + //Console.println("hello, getting name"); + val stmt = xName + //Console.println("hello, got name"); + xSpaceOpt + //Console.println("how can we be eof = "+eof); + + // eof = true because not external?! + //if(!eof) + // error("expected only INCLUDE or IGNORE"); + + //pop(); + + //Console.println("hello, popped"); + stmt match { + // parameter entity + case "INCLUDE" => + doInclude() + case "IGNORE" => + doIgnore() + } + case 'I' => + nextch + ch match { + case 'G' => + nextch + xToken("NORE") + xSpaceOpt + doIgnore() + case 'N' => + nextch + xToken("NCLUDE") + doInclude() + } + } + xToken(']') + xToken('>') + + case _ => + curInput.reportError(pos, "unexpected character '"+ch+"', expected some markupdecl") + while (ch!='>') + nextch + } + } + } + + def markupDecl(): Unit = ch match { + case '%' => // parameter entity reference + nextch + val ent = xName + xToken(';') + if (!isValidating) + handle.peReference(ent) // n-v: just create PE-reference + else + push(ent) // v: parse replacementText + + //peReference + case '<' => + nextch + markupDecl1() + case _ if isSpace(ch) => + xSpace + case _ => + reportSyntaxError("markupdecl: unexpected character '"+ch+"' #" + ch.asInstanceOf[Int]) + nextch + } + + /** "rec-xml/#ExtSubset" pe references may not occur within markup + declarations + */ + def intSubset() { + //Console.println("(DEBUG) intSubset()") + xSpace + while (']' != ch) + markupDecl() + } + + /** <! element := ELEMENT + */ + def elementDecl() { + xToken("EMENT") + xSpace + val n = xName + xSpace + while ('>' != ch) { + //Console.println("["+ch+"]") + putChar(ch) + nextch + } + //Console.println("END["+ch+"]") + nextch + val cmstr = cbuf.toString() + cbuf.length = 0 + handle.elemDecl(n, cmstr) + } + + /** <! attlist := ATTLIST + */ + def attrDecl() = { + xToken("TTLIST") + xSpace + val n = xName + xSpace + var attList: List[AttrDecl] = Nil + // later: find the elemDecl for n + while ('>' != ch) { + val aname = xName + //Console.println("attribute name: "+aname); + var defdecl: DefaultDecl = null + xSpace + // could be enumeration (foo,bar) parse this later :-/ + while ('"' != ch && '\'' != ch && '#' != ch && '<' != ch) { + if (!isSpace(ch)) + cbuf.append(ch); + nextch; + } + val atpe = cbuf.toString() + cbuf.length = 0 + //Console.println("attr type: "+atpe); + ch match { + case '\'' | '"' => + val defValue = xAttributeValue() // default value + defdecl = DEFAULT(false, defValue) + + case '#' => + nextch + xName match { + case "FIXED" => + xSpace + val defValue = xAttributeValue() // default value + defdecl = DEFAULT(true, defValue) + case "IMPLIED" => + defdecl = IMPLIED + case "REQUIRED" => + defdecl = REQUIRED + } + case _ => + } + xSpaceOpt + + attList = AttrDecl(aname, atpe, defdecl) :: attList + cbuf.length = 0 + } + nextch + handle.attListDecl(n, attList.reverse) + } + + /** <! element := ELEMENT + */ + def entityDecl() = { + //Console.println("entityDecl()") + var isParameterEntity = false + var entdef: EntityDef = null + xToken("NTITY") + xSpace + if ('%' == ch) { + nextch + isParameterEntity = true + xSpace + } + val n = xName + xSpace + ch match { + case 'S' | 'P' => //sy + val extID = externalID() + if (isParameterEntity) { + xSpaceOpt + xToken('>') + handle.parameterEntityDecl(n, ExtDef(extID)) + } else { // notation? + xSpace + if ('>' != ch) { + xToken("NDATA") + xSpace + val notat = xName + xSpaceOpt + xToken('>') + handle.unparsedEntityDecl(n, extID, notat) + } else { + nextch + handle.parsedEntityDecl(n, ExtDef(extID)) + } + } + + case '"' | '\'' => + val av = xEntityValue() + xSpaceOpt + xToken('>') + if (isParameterEntity) + handle.parameterEntityDecl(n, IntDef(av)) + else + handle.parsedEntityDecl(n, IntDef(av)) + } + {} + } // entityDecl + + /** 'N' notationDecl ::= "OTATION" + */ + def notationDecl() { + xToken("OTATION") + xSpace + val notat = xName + xSpace + val extID = if (ch == 'S') { + externalID(); + } + else if (ch == 'P') { + /** PublicID (without system, only used in NOTATION) */ + nextch + xToken("UBLIC") + xSpace + val pubID = pubidLiteral() + xSpaceOpt + val sysID = if (ch != '>') + systemLiteral() + else + null; + new PublicID(pubID, sysID); + } else { + reportSyntaxError("PUBLIC or SYSTEM expected"); + error("died parsing notationdecl") + } + xSpaceOpt + xToken('>') + handle.notationDecl(notat, extID) + } + + /** + * report a syntax error + */ + def reportSyntaxError(pos: Int, str: String) { + curInput.reportError(pos, str) + //error("MarkupParser::synerr") // DEBUG + } + + def reportSyntaxError(str: String): Unit = reportSyntaxError(pos, str) + + /** + * report a syntax error + */ + def reportValidationError(pos: Int, str: String) { + curInput.reportError(pos, str) + } + + def push(entityName: String) { + //Console.println("BEFORE PUSHING "+ch) + //Console.println("BEFORE PUSHING "+pos) + //Console.print("[PUSHING "+entityName+"]") + if (!eof) + inpStack = curInput :: inpStack + + curInput = replacementText(entityName) + nextch + } + + /* + def push(src:Source) = { + curInput = src + nextch + } + */ + + def pushExternal(systemId: String) { + //Console.print("BEFORE PUSH, curInput = $"+curInput.descr) + //Console.println(" stack = "+inpStack.map { x => "$"+x.descr }) + + //Console.print("[PUSHING EXTERNAL "+systemId+"]") + if (!eof) + inpStack = curInput :: inpStack + + curInput = externalSource(systemId) + + //Console.print("AFTER PUSH, curInput = $"+curInput.descr) + //Console.println(" stack = "+inpStack.map { x => "$"+x.descr }) + + nextch + } + + def pop() { + curInput = inpStack.head + inpStack = inpStack.tail + ch = curInput.ch + pos = curInput.pos + eof = false // must be false, because of places where entity refs occur + //Console.println("\n AFTER POP, curInput = $"+curInput.descr); + //Console.println(inpStack.map { x => x.descr }); + } + + /** for the moment, replace only character references + * see spec 3.3.3 + * precond: cbuf empty + */ + def normalizeAttributeValue(attval: String): String = { + val s: Seq[Char] = attval + val it = s.elements + while (it.hasNext) { + it.next match { + case ' '|'\t'|'\n'|'\r' => + cbuf.append(' '); + case '&' => it.next match { + case '#' => + var c = it.next + val s = xCharRef ({ () => c }, { () => c = it.next }) + cbuf.append(s) + case nchar => + val nbuf = new StringBuilder() + var d = nchar + do { + nbuf.append(d) + d = it.next + } while(d != ';'); + nbuf.toString() match { + case "lt" => cbuf.append('<') + case "gt" => cbuf.append('>') + case "amp" => cbuf.append('&') + case "apos" => cbuf.append('\'') + case "quot" => cbuf.append('"') + case "quote" => cbuf.append('"') + case name => + cbuf.append('&') + cbuf.append(name) + cbuf.append(';') + } + } + case c => + cbuf.append(c) + } + } + val name = cbuf.toString() + cbuf.length = 0 + name + } + +} diff --git a/src/library/scala/xml/include/parsing/NoBindingFactoryAdapter.scala b/src/library/scala/xml/include/parsing/NoBindingFactoryAdapter.scala new file mode 100644 index 0000000000..be71e55fef --- /dev/null +++ b/src/library/scala/xml/include/parsing/NoBindingFactoryAdapter.scala @@ -0,0 +1,62 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.xml.parsing; + + +import scala.xml.factory.NodeFactory; +import org.xml.sax.InputSource; + +/** nobinding adaptor providing callbacks to parser to create elements. +* implements hash-consing +*/ +class NoBindingFactoryAdapter extends FactoryAdapter with NodeFactory[Elem] { + + // -- FactoryAdapter methods + + /** returns true. Every XML node may contain text that the application needs + **/ + def nodeContainsText( label:java.lang.String ): Boolean = true; + + + // methods for NodeFactory[Elem] + + /** constructs an instance of scala.xml.Elem */ + protected def create(pre: String, label: String, attrs: MetaData, scpe: NamespaceBinding, children:Seq[Node]): Elem = { + Elem( pre, label, attrs, scpe, children:_* ); + } + + // -- methods for FactoryAdapter + + /** creates a node. never creates the same node twice, using hash-consing + */ + def createNode(pre:String, label: String, attrs: MetaData, scpe: NamespaceBinding, children: List[Node] ): Elem = { + //Console.println("NoBindingFactoryAdapter::createNode("+pre+","+label+","+attrs+","+scpe+","+children+")"); + Elem( pre, label, attrs, scpe, children:_* ); + //makeNode(pre, label, attrs, scpe, children); + } + + /** creates a text node + */ + def createText( text:String ) = + Text( text ); + + /** create a processing instruction + */ + def createProcInstr(target: String, data: String) = + makeProcInstr(target, data) + + /** loads an XML document, returning a Symbol node. + */ + override def loadXML( source:InputSource ):Elem = + super.loadXML( source ).asInstanceOf[ Elem ]; + +} diff --git a/src/library/scala/xml/include/parsing/TokenTests.scala b/src/library/scala/xml/include/parsing/TokenTests.scala new file mode 100644 index 0000000000..d56b9bb7d7 --- /dev/null +++ b/src/library/scala/xml/include/parsing/TokenTests.scala @@ -0,0 +1,146 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2006, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.xml.parsing; + + +/** + * Helper functions for parsing XML fragments + */ +trait TokenTests { + + /** (#x20 | #x9 | #xD | #xA) */ + final def isSpace( ch:Char ): Boolean = ch match { + case '\u0009' | '\u000A' | '\u000D' | '\u0020' => true + case _ => false; + } + + /** (#x20 | #x9 | #xD | #xA)+ */ + final def isSpace(cs: Seq[Char]): Boolean = { + val it = cs.elements; + it.hasNext && it.forall { isSpace }; + } + + /** NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' + * | CombiningChar | Extender + * + * see [4] and Appendix B of XML 1.0 specification + */ + def isNameChar(ch: Char) = isNameStart(ch) || (ch match { + case '.' | '-' | ':' => true; + case _ => java.lang.Character.getType( ch ).asInstanceOf[Byte] match { + case java.lang.Character.COMBINING_SPACING_MARK => true; // Mc + case java.lang.Character.ENCLOSING_MARK => true; // Me + case java.lang.Character.NON_SPACING_MARK => true; // Mn + case java.lang.Character.MODIFIER_LETTER => true; // Lm + case java.lang.Character.DECIMAL_DIGIT_NUMBER => true; // Nd + case _ => false; + } + }); + + /** NameStart ::= ( Letter | '_' ) + * where Letter means in one of the Unicode general + * categories { Ll, Lu, Lo, Lt, Nl } + * + * We do not allow a name to start with ':'. + * see [3] and Appendix B of XML 1.0 specification + */ + def isNameStart(ch: Char) = + java.lang.Character.getType(ch).asInstanceOf[Byte] match { + case java.lang.Character.LOWERCASE_LETTER => true; + case java.lang.Character.UPPERCASE_LETTER => true; + case java.lang.Character.OTHER_LETTER => true; + case java.lang.Character.TITLECASE_LETTER => true; + case java.lang.Character.LETTER_NUMBER => true; + case _ => ch match { + case '_' => true + case _ => false; + } + } + + /** Name ::= ( Letter | '_' ) (NameChar)* + * + * see [5] of XML 1.0 specification + */ + def isName(s: String): Boolean = { + if( s.length() > 0 ) { + val y = s.elements; + if (isNameStart(y.next)) { + while (y.hasNext && isNameChar(y.next)) {}; + !y.hasNext + } else false; + } else false; + } + + def isPubIDChar(ch: Char): Boolean = { + //Console.println("char: '" + ch + "'"); + ch match { + case '\u0020' | '\u000D' | '\u000A' => true; + case _ if + (('0' <= ch && ch <= '9') || ('a' <= ch && ch <= 'z') || + ('A' <= ch && ch <= 'Z')) => true; + case '-' | '\''| '(' | ')' | '+' | ',' | '.' | + '/' | ':' | '=' | '?' | ';' | '!' | '*' | + '#' | '@' | '$' | '_' | '%' => true + case _ => + //Console.println("false: '" + ch + "'"); + false; + } + } + + /** + * Returns true if the encoding name is a valid IANA encoding. + * This method does not verify that there is a decoder available + * for this encoding, only that the characters are valid for an + * IANA encoding name. + * + * @param ianaEncoding The IANA encoding name. + */ + def isValidIANAEncoding(ianaEncoding: Seq[Char]): Boolean = { + val it = ianaEncoding.elements; + if (!it.hasNext) + return false; + + var c = it.next; + if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) { + while (it.hasNext) { + c = it.next; + if ((c < 'A' || c > 'Z') && (c < 'a' || c > 'z') && + (c < '0' || c > '9') && c != '.' && c != '_' && + c != '-') { + return false; + } + } + return true; + } else + return false; + } // isValidIANAEncoding(String): Boolean + + def checkSysID( s:String ): Boolean = { + s.indexOf('"'.asInstanceOf[Int]) == -1 || s.indexOf('\''.asInstanceOf[Int]) == -1 + } + + def checkPubID(s: String): Boolean = { + //Console.println("checkPubID of \""+s+"\""); + if (s.length() > 0) { + val y = s.elements; + var c = ' '; + while (y.hasNext && isPubIDChar(c)) { + //Console.println(c); + c = y.next + }; + !y.hasNext + } + else + true + } + +} diff --git a/src/library/scala/xml/include/persistent/CachedFileStorage.scala b/src/library/scala/xml/include/persistent/CachedFileStorage.scala new file mode 100644 index 0000000000..137286492a --- /dev/null +++ b/src/library/scala/xml/include/persistent/CachedFileStorage.scala @@ -0,0 +1,123 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + +package scala.xml.persistent + +import java.io.{File, FileOutputStream} +import java.nio.ByteBuffer +import java.nio.channels.Channels + +/**

+ * Mutable storage of immutable xml trees. Everything is kept in memory, + * with a thread periodically checking for changes and writing to file. + * To ensure atomicity, two files are used, filename1 and '$'+filename1. + * The implementation switches between the two, deleting the older one + * after a complete dump of the database has been written. + *

+ * + * @author Burak Emir + */ +abstract class CachedFileStorage(private val file1: File) +extends java.lang.Thread with scala.util.logging.Logged { + + private val file2 = new File(file1.getParent, file1.getName+"$") + + /** either equals file1 or file2, references the next file in which updates will be stored + */ + private var theFile: File = null + + private def switch = { theFile = if (theFile == file1) file2 else file1; } + + /** this storage modified since last modification check */ + protected var dirty = false + + /** period between modification checks, in milliseconds */ + protected val interval = 1000 + + /** finds and loads the storage file. subclasses should call this method + * prior to any other, but only once, to obtain the initial sequence of nodes. + */ + protected def initialNodes: Iterator[Node] = (file1.exists, file2.exists) match { + case (false,false) => + theFile = file1 + Iterator.empty + case (true, true ) if (file1.lastModified < file2.lastModified) => + theFile = file2 + load + case (true, _ ) => + theFile = file1 + load + case _ => + theFile = file2 + load + } + + /** returns an iterator over the nodes in this storage */ + def nodes: Iterator[Node] + + /** adds a node, setting this.dirty to true as a side effect */ + def += (e: Node): Unit + + /** removes a tree, setting this.dirty to true as a side effect */ + def -= (e: Node): Unit + + /* loads and parses XML from file */ + private def load: Iterator[Node] = { + import scala.io.Source + import scala.xml.parsing.ConstructingParser + log("[load]\nloading "+theFile) + val src = Source.fromFile( theFile ) + log("parsing "+theFile) + val res = ConstructingParser.fromSource(src,false).document.docElem(0) + switch + log("[load done]") + res.child.elements + } + + /** saves the XML to file */ + private def save = if (this.dirty) { + log("[save]\ndeleting "+theFile); + theFile.delete(); + log("creating new "+theFile); + theFile.createNewFile(); + val fos = new FileOutputStream(theFile) + val c = fos.getChannel() + + // @todo: optimize + val storageNode = { nodes.toList } + val w = Channels.newWriter(c, "utf-8") + XML.write(w, storageNode, "utf-8", true, null) + + log("writing to "+theFile); + + w.close + c.close + fos.close + dirty = false + switch + log("[save done]") + } + + /** run method of the thread. remember to use start() to start a thread, not run. */ + override def run = { + log("[run]\nstarting storage thread, checking every "+interval+" ms"); + while(true) { + Thread.sleep( this.interval ); + save + } + } + + /** forces writing of contents to the file, even if there has not been any update. */ + def flush = { + this.dirty = true; + save + } +} + diff --git a/src/library/scala/xml/include/persistent/IndexedStorage.scala b/src/library/scala/xml/include/persistent/IndexedStorage.scala new file mode 100644 index 0000000000..c14c88e5b1 --- /dev/null +++ b/src/library/scala/xml/include/persistent/IndexedStorage.scala @@ -0,0 +1,48 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.xml.persistent + +import scala.collection.mutable +import java.io.File + +/** indexed multiset of xml trees. The index may be an arbitrary totally + * type, especially one can construct indices by selecting parts of + * xml nodes. + */ +class IndexedStorage[A](file: File, index: Index[A]) //@todo +extends CachedFileStorage(file) { + + private var theMap: mutable.Map[A,Node] = new mutable.HashMap[A,Node]() + + super.initialNodes.foreach { x:Node => this += x } + + this.dirty = false + + def += (e: Node): Unit = synchronized { + log("added element at index '"+index(e)+"'") + dirty = true + theMap(index(e)) = e + } + + def -= (e: Node): Unit = synchronized { + log("removed element at index '"+index(e)+"'") + dirty = true + theMap -= index( e ) + } + + def nodes: Iterator[Node] = synchronized { + theMap.values + } + + def lookup(n: A): Option[Node] = theMap.get(n) + +} diff --git a/src/library/scala/xml/include/persistent/SetStorage.scala b/src/library/scala/xml/include/persistent/SetStorage.scala new file mode 100644 index 0000000000..1391f1f76e --- /dev/null +++ b/src/library/scala/xml/include/persistent/SetStorage.scala @@ -0,0 +1,43 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + +package scala.xml.persistent + +import scala.collection.mutable +import java.io.File + +/** A persistent store with set semantics. This class allows to add and remove + * trees, but never contains two structurally equal trees. + * + * @author Burak Emir + */ +class SetStorage(file: File) extends CachedFileStorage(file) { + + private var theSet: mutable.HashSet[Node] = new mutable.HashSet[Node] + + // initialize + + { + val it = super.initialNodes + dirty = it.hasNext + for(val x <- it) { + theSet += x; + } + } + + /* forwarding methods to hashset*/ + + def += (e: Node): Unit = synchronized { this.dirty = true; theSet += e } + + def -= (e: Node): Unit = synchronized { this.dirty = true; theSet -= e } + + def nodes = synchronized { theSet.elements } + +} diff --git a/src/library/scala/xml/include/pull/XMLEventReader.scala b/src/library/scala/xml/include/pull/XMLEventReader.scala new file mode 100644 index 0000000000..bcc48af1e7 --- /dev/null +++ b/src/library/scala/xml/include/pull/XMLEventReader.scala @@ -0,0 +1,133 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + + +package scala.xml.pull + + +import java.lang.{Runnable, Thread} + +import scala.io.Source +import scala.xml.parsing.{ExternalSources, MarkupHandler, MarkupParser} + +/**

+ * A pull parser that offers to view an XML document as a series of events. + * Please note that this API might change. Here's how to use this class + *

+ *  import scala.xml._
+ *  import scala.xml.pull._
+ *  import scala.io.Source
+ *
+ *  object reader {
+ *    val src = Source.fromString("")
+ *    val er = new XMLEventReader().initialize(src)
+ *
+ *    def main(args: Array[String]) {
+ *      Console.println(er.next)
+ *      Console.println(er.next)
+ *    }
+ *  }
+ *  
+ * + * @author Burak Emir + */ +class XMLEventReader extends Iterator[XMLEvent] { + + var src:Source = null + def getSource = this.src + def initialize(src: Source): this.type = { + this.src = src + this.parserThread = new Thread(new Parser()) + this.parserThread.start() + this + } + + // -- this part of the class is for communication with the thread + var xmlEvent: XMLEvent = null + var continue: Boolean = true + + def myresume = synchronized { + while (continue) { + wait() + } + continue = true + notifyAll + } + def getAndClearEvent: XMLEvent = synchronized { + while (xmlEvent eq null) { + wait() + } + val r = xmlEvent + xmlEvent = null + r + } + def setEvent(e: XMLEvent) { + xmlEvent = e + } + + def doNotify() = synchronized { + XMLEventReader.this.continue = false + notifyAll() + while (!XMLEventReader.this.continue) wait(); + NodeSeq.Empty + } + + // iterator methods + + def next: XMLEvent = { + myresume + val r = getAndClearEvent + r + } + + def hasNext = true + + var parserThread: Thread = null + + class Parser extends MarkupHandler with MarkupParser with ExternalSources with Runnable { + + val preserveWS = true + val input = XMLEventReader.this.getSource + + override def elemStart(pos: Int, pre: String, label: String, attrs: MetaData, scope: NamespaceBinding) { + setEvent(ElemStart(pre, label, attrs, scope)); doNotify + } + + override def elemEnd(pos: Int, pre: String, label: String) { + setEvent(ElemEnd(pre, label)); doNotify + } + + final def elem(pos: Int, pre: String, label: String, attrs: MetaData, pscope: NamespaceBinding, nodes: NodeSeq): NodeSeq = + NodeSeq.Empty + + def procInstr(pos: Int, target: String, txt: String): NodeSeq = { + setEvent(ElemStart(null, "comm", null, null)); doNotify + } + + def comment(pos: Int, txt: String): NodeSeq = { + setEvent(ElemStart(null, "comm", null, null)); doNotify + } + + def entityRef(pos: Int, n: String): NodeSeq = { + setEvent(ElemStart(null, "eref", null, null)); doNotify + } + + def text(pos: Int, txt:String): NodeSeq = { + setEvent(ElemStart(null, "tex", null, null)); doNotify + } + + override def run() { + curInput = input + this.nextch + doNotify() + this.document() + } + } +} diff --git a/src/library/scala/xml/include/sax/EncodingHeuristics.scala b/src/library/scala/xml/include/sax/EncodingHeuristics.scala new file mode 100644 index 0000000000..adab470106 --- /dev/null +++ b/src/library/scala/xml/include/sax/EncodingHeuristics.scala @@ -0,0 +1,177 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + +package scala.xml.include.sax + +import java.io.{IOException, InputStreamReader, InputStream} + +/** + *

+ * EncodingHeuristics reads from a stream + * (which should be buffered) and attempts to guess + * what the encoding of the text in the stream is. + * Byte order marks are stripped from the stream. + * If it fails to determine the type of the encoding, + * it returns the default UTF-8. + *

+ *

+ * Translated from Elliotte Rusty Harold's Java source + *

+ * + * @author Burak Emir + */ +object EncodingHeuristics { + + /** + *

+ * This utility method ????. + *

+ * + * @param in InputStream to read from. + * @return String The name of the encoding. + * @throws IOException if the stream cannot be reset back to where it was when + * the method was invoked. + */ + def readEncodingFromStream(in: InputStream): String = { + //System.err.println("EncodingHeuristics::readEncodingFromStream"); + // This may fail if there are a lot of space characters before the end + // of the encoding declaration + in.mark(1024) + var ret: String = null + try { + // lots of things can go wrong here. If any do, I just return null + // so that we'll fall back on the encoding declaration or the + // UTF-8 default + val byte1 = in.read() + val byte2 = in.read() + if (byte1 == 0xFE && byte2 == 0xFF) { + // don't reset because the byte order mark should not be included???? + ret = "UnicodeBig"; // name for big-endian???? + } + else if (byte1 == 0xFF && byte2 == 0xFE) { + // don't reset because the byte order mark should not be included???? + // will the reader throw away the byte order mark or will it return it???? + ret = "UnicodeLittle" + } + + /* In accordance with the Character Model [Character Model], + when the text format is a Unicode encoding, the XInclude + processor must fail the inclusion when the text in the + selected range is non-normalized. When transcoding characters + to a Unicode encoding from a legacy encoding, a normalizing transcoder must be used. */ + + val byte3 = in.read() + // check for UTF-8 byte order mark + if (byte1 == 0xEF && byte2 == 0xBB && byte3 == 0xBF) { + // don't reset because the byte order mark should not be included???? + // in general what happens if text document includes non-XML legal chars???? + ret = "UTF-8"; + } + + val byte4 = in.read(); + if (byte1 == 0x00 && byte2 == 0x00 && byte3 == 0xFE && byte4 == 0xFF) { + // don't reset because the byte order mark should not be included???? + ret = "UCS-4"; // right name for big-endian UCS-4 in Java 1.4???? + } + else if (byte1 == 0x00 && byte2 == 0x00 && byte3 == 0xFF && byte4 == 0xFE) { + // don't reset because the byte order mark should not be included???? + ret = "UCS-4"; // right name for little-endian UCS-4 in Java 1.4???? + } + + // no byte order mark present; first character must be + // less than sign or white space + // Let's look for less-than signs first + if (byte1 == 0x00 && byte2 == 0x00 && byte3 == 0x00 && byte4 == '<') { + in.reset() + ret = "UCS-4" // right name for big-endian UCS-4 in Java 1.4???? + } + else if (byte1 == '<' && byte2 == 0x00 && byte3 == 0x00 && byte4 == 0x00) { + in.reset() + ret = "UCS-4" // right name for little-endian UCS-4 in Java 1.4???? + } + else if (byte1 == 0x00 && byte2 == '<' && byte3 == 0x00 && byte4 == '?') { + in.reset() + ret = "UnicodeBigUnmarked" + } + else if (byte1 == '<' && byte2 == 0x00 && byte3 == '?' && byte4 == 0x00) { + in.reset() + ret = "UnicodeLittleUnmarked" + } + else if (byte1 == '<' && byte2 == '?' && byte3 == 'x' && byte4 == 'm') { + // ASCII compatible, must read encoding declaration + // 1024 bytes will be far enough to read most XML declarations + val data = new Array[Byte](1024) + data(0) = byte1.asInstanceOf[Byte] + data(1) = byte2.asInstanceOf[Byte] + data(2) = byte3.asInstanceOf[Byte] + data(3) = byte4.asInstanceOf[Byte] + val length = in.read(data, 4, 1020) + 4; + // Use Latin-1 (ISO-8859-1) because it's ASCII compatible and + // all byte sequences are legal Latin-1 sequences so I don't have + // to worry about encoding errors if I slip past the + // end of the XML/text declaration + val declaration = new String(data, 0, length, "8859_1"); + // if any of these throw a StringIndexOutOfBoundsException + // we just fall into the catch bloclk and return null + // since this can't be well-formed XML + var position = declaration.indexOf("encoding") + 8; + var c: Char = '\0' // bogus init value + // get rid of white space before equals sign + do { + c = declaration.charAt(position) + position += 1 + } while (c == ' ' || c == '\t' || c == '\r' || c == '\n') ; + if (c != '=') { // malformed + in.reset() + ret = "UTF-8" + } + // get rid of white space after equals sign + do { + c = declaration.charAt(position) + position += 1 + } while (c == ' ' || c == '\t' || c == '\r' || c == '\n') ; + var delimiter: Char = c + if (delimiter != '\'' && delimiter != '"') { // malformed + in.reset() + ret = "UTF-8" + } + // now positioned to read encoding name + val encodingName = new StringBuffer() + do { + c = declaration.charAt(position) + position += 1 + encodingName.append(c) + } while(c != delimiter) + encodingName.setLength(encodingName.length() - 1) // rm delim + in.reset() + ret = encodingName.toString() + } + else if (byte1 == 0x4C && byte2 == 0x6F && byte3 == 0xA7 && byte4 == 0x94) { + // EBCDIC compatible, must read encoding declaration + // ???? + } + + } catch { + case e: Exception => + in.reset() + ret = "UTF-8" + } + + // no XML or text declaration present + //System.err.println("exit EncodingHeuristics::readEncodingFromStream"); + + if (ret != null) + ret + else { + in.reset() + "UTF-8" + } + } +} diff --git a/src/library/scala/xml/include/sax/XIncludeFilter.scala b/src/library/scala/xml/include/sax/XIncludeFilter.scala new file mode 100644 index 0000000000..19dc5ecead --- /dev/null +++ b/src/library/scala/xml/include/sax/XIncludeFilter.scala @@ -0,0 +1,422 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + +package scala.xml.include.sax + +import org.xml.sax.Attributes +import org.xml.sax.SAXException +import org.xml.sax.XMLReader +import org.xml.sax.EntityResolver +import org.xml.sax.Locator +import org.xml.sax.helpers.XMLReaderFactory +import org.xml.sax.helpers.XMLFilterImpl +import org.xml.sax.helpers.NamespaceSupport +import org.xml.sax.helpers.AttributesImpl + +import java.net.URL +import java.net.URLConnection +import java.net.MalformedURLException +import java.io.UnsupportedEncodingException +import java.io.IOException +import java.io.InputStream +import java.io.BufferedInputStream +import java.io.InputStreamReader +import java.util.Stack + +/** + *

+ * This is a SAX filter which resolves all XInclude include elements + * before passing them on to the client application. Currently this + * class has the following known deviation from the XInclude specification: + *

+ *
    + *
  1. XPointer is not supported.
  2. + *
+ * + *

+ * Furthermore, I would definitely use a new instance of this class + * for each document you want to process. I doubt it can be used + * successfully on multiple documents. Furthermore, I can virtually + * guarantee that this class is not thread safe. You have been + * warned. + *

+ * + *

+ * Since this class is not designed to be subclassed, and since + * I have not yet considered how that might affect the methods + * herein or what other protected methods might be needed to support + * subclasses, I have declared this class final. I may remove this + * restriction later, though the use-case for subclassing is weak. + * This class is designed to have its functionality extended via a + * a horizontal chain of filters, not a + * vertical hierarchy of sub and superclasses. + *

+ * + *

+ * To use this class: + *

+ *
    + *
  1. Construct an XIncludeFilter object with a known base URL
  2. + *
  3. Pass the XMLReader object from which the raw document will + * be read to the setParent() method of this object.
  4. + *
  5. Pass your own ContentHandler object to the + * setContentHandler() method of this object. This is the + * object which will receive events from the parsed and included + * document. + *
  6. + *
  7. Optional: if you wish to receive comments, set your own + * LexicalHandler object as the value of this object's + * http://xml.org/sax/properties/lexical-handler property. + * Also make sure your LexicalHandler asks this object + * for the status of each comment using insideIncludeElement + * before doing anything with the comment. + *
  8. + *
  9. Pass the URL of the document to read to this object's + * parse() method
  10. + *
+ * + *

e.g.

+ *
XIncludeFilter includer = new XIncludeFilter(base);
+ *  includer.setParent(parser);
+ *  includer.setContentHandler(new SAXXIncluder(System.out));
+ *  includer.parse(args[i]);
+ *  
+ *

+ * translated from Elliotte Rusty Harold's Java source + * @author Burak Emir + */ +class XIncludeFilter extends XMLFilterImpl { + + final val XINCLUDE_NAMESPACE = "http://www.w3.org/2001/XInclude"; + + private val bases = new Stack[URL](); + private val locators = new Stack[Locator](); + +/* private EntityResolver resolver; + + public XIncludeFilter() { + this(null); + } + + public XIncludeFilter(EntityResolver resolver) { + this.resolver = resolver; + } */ + + + // what if this isn't called???? + // do I need to check this in startDocument() and push something + // there???? + override def setDocumentLocator(locator: Locator) { + locators.push(locator) + val base = locator.getSystemId() + try { + bases.push(new URL(base)) + } + catch { + case e:MalformedURLException => + throw new UnsupportedOperationException("Unrecognized SYSTEM ID: " + base) + } + super.setDocumentLocator(locator) + } + + + // necessary to throw away contents of non-empty XInclude elements + private var level = 0 + + /** + *

+ * This utility method returns true if and only if this reader is + * currently inside a non-empty include element. (This is + * not the same as being inside the node set which replaces + * the include element.) This is primarily needed for comments + * inside include elements. It must be checked by the actual + * LexicalHandler to see whether a comment is passed or not. + *

+ * + * @return boolean + */ + def insideIncludeElement(): Boolean = level != 0 + + override def startElement(uri: String, localName: String, qName: String, atts1: Attributes) { + var atts = atts1 + if (level == 0) { // We're not inside an xi:include element + + // Adjust bases stack by pushing either the new + // value of xml:base or the base of the parent + val base = atts.getValue(NamespaceSupport.XMLNS, "base") + val parentBase = bases.peek().asInstanceOf[URL] + var currentBase = parentBase + if (base != null) { + try { + currentBase = new URL(parentBase, base) + } + catch { + case e: MalformedURLException => + throw new SAXException("Malformed base URL: " + + currentBase, e) + } + } + bases.push(currentBase); + + if (uri.equals(XINCLUDE_NAMESPACE) && localName.equals("include")) { + // include external document + val href = atts.getValue("href") + // Verify that there is an href attribute + if (href==null) { + throw new SAXException("Missing href attribute") + } + + var parse = atts.getValue("parse") + if (parse == null) parse = "xml" + + if (parse.equals("text")) { + val encoding = atts.getValue("encoding"); + includeTextDocument(href, encoding); + } + else if (parse.equals("xml")) { + includeXMLDocument(href); + } + // Need to check this also in DOM and JDOM???? + else { + throw new SAXException( + "Illegal value for parse attribute: " + parse); + } + level += 1 + } + else { + if (atRoot) { + // add xml:base attribute if necessary + val attsImpl = new AttributesImpl(atts) + attsImpl.addAttribute(NamespaceSupport.XMLNS, "base", + "xml:base", "CDATA", currentBase.toExternalForm()) + atts = attsImpl + atRoot = false + } + super.startElement(uri, localName, qName, atts) + } + } + } + + override def endElement(uri: String, localName: String, qName: String) { + if (uri.equals(XINCLUDE_NAMESPACE) + && localName.equals("include")) { + level -= 1; + } + else if (level == 0) { + bases.pop() + super.endElement(uri, localName, qName) + } + } + + private var depth = 0; + + override def startDocument() { + level = 0 + if (depth == 0) super.startDocument() + depth += 1 + } + + override def endDocument() { + locators.pop() + bases.pop(); // pop the URL for the document itself + depth -= 1 + if (depth == 0) super.endDocument() + } + + // how do prefix mappings move across documents???? + override def startPrefixMapping(prefix: String , uri: String) { + if (level == 0) super.startPrefixMapping(prefix, uri) + } + + override def endPrefixMapping(prefix: String) { + if (level == 0) super.endPrefixMapping(prefix) + } + + override def characters(ch: Array[Char], start: Int, length: Int) { + if (level == 0) super.characters(ch, start, length) + } + + override def ignorableWhitespace(ch: Array[Char], start: Int, length: Int) { + if (level == 0) super.ignorableWhitespace(ch, start, length) + } + + override def processingInstruction(target: String, data: String) { + if (level == 0) super.processingInstruction(target, data) + } + + override def skippedEntity(name: String) { + if (level == 0) super.skippedEntity(name) + } + + // convenience method for error messages + private def getLocation(): String = { + var locationString = "" + val locator = locators.peek().asInstanceOf[Locator] + var publicID = "" + var systemID = "" + var column = -1 + var line = -1 + if (locator != null) { + publicID = locator.getPublicId() + systemID = locator.getSystemId() + line = locator.getLineNumber() + column = locator.getColumnNumber() + } + locationString = (" in document included from " + publicID + + " at " + systemID + + " at line " + line + ", column " + column); + + locationString + } + + /** + *

+ * This utility method reads a document at a specified URL + * and fires off calls to characters(). + * It's used to include files with parse="text" + *

+ * + * @param url URL of the document that will be read + * @param encoding Encoding of the document; e.g. UTF-8, + * ISO-8859-1, etc. + * @return void + * @throws SAXException if the requested document cannot + be downloaded from the specified URL + or if the encoding is not recognized + */ + private def includeTextDocument(url: String, encoding1: String) { + var encoding = encoding1 + if (encoding == null || encoding.trim().equals("")) encoding = "UTF-8"; + var source: URL = null + try { + val base = bases.peek().asInstanceOf[URL] + source = new URL(base, url) + } + catch { + case e: MalformedURLException => + val ex = new UnavailableResourceException("Unresolvable URL " + url + + getLocation()); + ex.setRootCause(e); + throw new SAXException("Unresolvable URL " + url + getLocation(), ex); + } + + try { + val uc = source.openConnection() + val in = new BufferedInputStream(uc.getInputStream()) + var encodingFromHeader = uc.getContentEncoding() + var contentType = uc.getContentType() + if (encodingFromHeader != null) + encoding = encodingFromHeader + else { + // What if file does not have a MIME type but name ends in .xml???? + // MIME types are case-insensitive + // Java may be picking this up from file URL + if (contentType != null) { + contentType = contentType.toLowerCase(); + if (contentType.equals("text/xml") + || contentType.equals("application/xml") + || (contentType.startsWith("text/") && contentType.endsWith("+xml") ) + || (contentType.startsWith("application/") && contentType.endsWith("+xml"))) { + encoding = EncodingHeuristics.readEncodingFromStream(in); + } + } + } + val reader = new InputStreamReader(in, encoding) + val c = new Array[Char](1024) + var charsRead: Int = 0 // bogus init value + do { + charsRead = reader.read(c, 0, 1024); + if (charsRead > 0) this.characters(c, 0, charsRead); + } while (charsRead != -1) ; + } + catch { + case e: UnsupportedEncodingException => + throw new SAXException("Unsupported encoding: " + + encoding + getLocation(), e); + case e: IOException => + throw new SAXException("Document not found: " + + source.toExternalForm() + getLocation(), e); + } + + } + + private var atRoot = false + + /** + *

+ * This utility method reads a document at a specified URL + * and fires off calls to various ContentHandler methods. + * It's used to include files with parse="xml" + *

+ * + * @param url URL of the document that will be read + * @return void + * @throws SAXException if the requested document cannot + be downloaded from the specified URL. + */ + private def includeXMLDocument(url: String) { + var source: URL = null + try { + val base = bases.peek().asInstanceOf[URL] + source = new URL(base, url) + } + catch { + case e:MalformedURLException => + val ex = new UnavailableResourceException("Unresolvable URL " + url + + getLocation()); + ex.setRootCause(e) + throw new SAXException("Unresolvable URL " + url + getLocation(), ex) + } + + try { + // make this more robust + var parser: XMLReader = null + try { + parser = XMLReaderFactory.createXMLReader() + } catch { + case e:SAXException => + try { + parser = XMLReaderFactory.createXMLReader( + "org.apache.xerces.parsers.SAXParser" + ); + } catch { + case e2: SAXException => + System.err.println("Could not find an XML parser") + } + } + if(parser != null) { + parser.setContentHandler(this) + val resolver = this.getEntityResolver() + if (resolver != null) parser.setEntityResolver(resolver); + // save old level and base + val previousLevel = level + this.level = 0 + if (bases.contains(source)) { + val e = new CircularIncludeException( + "Circular XInclude Reference to " + source + getLocation() + ); + throw new SAXException("Circular XInclude Reference", e) + } + bases.push(source) + atRoot = true + parser.parse(source.toExternalForm()) + // restore old level and base + this.level = previousLevel + bases.pop() + } + } + catch { + case e:IOException => + throw new SAXException("Document not found: " + + source.toExternalForm() + getLocation(), e) + } + + } +} diff --git a/src/library/scala/xml/include/sax/XIncluder.scala b/src/library/scala/xml/include/sax/XIncluder.scala new file mode 100644 index 0000000000..bac9c9d82e --- /dev/null +++ b/src/library/scala/xml/include/sax/XIncluder.scala @@ -0,0 +1,201 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2007, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id$ + +package scala.xml.include.sax + +import org.xml.sax.SAXException +import org.xml.sax.SAXParseException +import org.xml.sax.ContentHandler +import org.xml.sax.EntityResolver +import org.xml.sax.helpers.XMLReaderFactory +import org.xml.sax.XMLReader +import org.xml.sax.Locator +import org.xml.sax.Attributes +import org.xml.sax.ext.LexicalHandler + +import java.io.{File, IOException, OutputStream, OutputStreamWriter, + UnsupportedEncodingException, Writer} +import java.net.{MalformedURLException, URL} +import java.util.Stack + +/** XIncluder is a SAX ContentHandler + * that writes its XML document onto an output stream after resolving + * all xinclude:include elements. + * + *

+ * based on Eliotte Rusty Harold's SAXXIncluder + *

+ */ +class XIncluder(outs:OutputStream, encoding:String) extends Object +with ContentHandler with LexicalHandler { + + var out = new OutputStreamWriter(outs, encoding) + + def setDocumentLocator(locator: Locator) {} + + def startDocument() { + try { + out.write("\r\n"); + } + catch { + case e:IOException => + throw new SAXException("Write failed", e) + } + } + + def endDocument() { + try { + out.flush() + } + catch { + case e:IOException => + throw new SAXException("Flush failed", e) + } + } + + def startPrefixMapping(prefix: String , uri: String) {} + + def endPrefixMapping(prefix: String) {} + + def startElement(namespaceURI: String, localName: String, qualifiedName: String, atts: Attributes) = { + try { + out.write("<" + qualifiedName); + var i = 0; while (i < atts.getLength()) { + out.write(" "); + out.write(atts.getQName(i)); + out.write("='"); + val value = atts.getValue(i); + // @todo Need to use character references if the encoding + // can't support the character + out.write(xml.Utility.escape(value)) + out.write("'"); + i += 1 + } + out.write(">") + } + catch { + case e:IOException => + throw new SAXException("Write failed", e) + } + } + + def endElement(namespaceURI: String, localName:String, qualifiedName: String) { + try { + out.write("") + } + catch { + case e: IOException => + throw new SAXException("Write failed", e) + } + } + + // need to escape characters that are not in the given + // encoding using character references???? + def characters(ch: Array[Char], start: Int, length: Int) { + try { + var i = 0; while (i < length) { + val c = ch(start+i); + if (c == '&') out.write("&"); + else if (c == '<') out.write("<"); + // This next fix is normally not necessary. + // However, it is required if text contains ]]> + // (The end CDATA section delimiter) + else if (c == '>') out.write(">"); + else out.write(c); + i = i+1; + } + } + catch { + case e: IOException => + throw new SAXException("Write failed", e); + } + } + + def ignorableWhitespace(ch: Array[Char], start: Int , length: Int) { + this.characters(ch, start, length) + } + + // do I need to escape text in PI???? + def processingInstruction(target: String, data: String) { + try { + out.write("") + } + catch { + case e:IOException => + throw new SAXException("Write failed", e) + } + } + + def skippedEntity(name: String) { + try { + out.write("&" + name + ";") + } + catch { + case e:IOException => + throw new SAXException("Write failed", e) + } + } + + // LexicalHandler methods + private var inDTD: Boolean = false + private val entities = new Stack[String]() + + def startDTD(name: String, publicID: String, systemID: String) { + inDTD = true + // if this is the source document, output a DOCTYPE declaration + if (entities.size() == 0) { + var id = "" + if (publicID != null) id = " PUBLIC \"" + publicID + "\" \"" + systemID + '"'; + else if (systemID != null) id = " SYSTEM \"" + systemID + '"'; + try { + out.write("\r\n") + } + catch { + case e:IOException => + throw new SAXException("Error while writing DOCTYPE", e) + } + } + } + def endDTD() {} + + def startEntity(name: String) { + entities.push(name) + } + + def endEntity(name: String) { + entities.pop() + } + + def startCDATA() {} + def endCDATA() {} + + // Just need this reference so we can ask if a comment is + // inside an include element or not + private var filter: XIncludeFilter = null + + def setFilter(filter: XIncludeFilter) { + this.filter = filter + } + + def comment(ch: Array[Char], start: Int, length: Int) { + if (!inDTD && !filter.insideIncludeElement()) { + try { + out.write("") + } + catch { + case e: IOException => + throw new SAXException("Write failed", e) + } + } + } +} -- cgit v1.2.3