You can subscribe to this list here.
| 2006 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(97) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2007 |
Jan
(127) |
Feb
(34) |
Mar
(16) |
Apr
(26) |
May
(55) |
Jun
(107) |
Jul
(36) |
Aug
(72) |
Sep
(90) |
Oct
(41) |
Nov
(27) |
Dec
(13) |
| 2008 |
Jan
(37) |
Feb
(39) |
Mar
(98) |
Apr
(115) |
May
(134) |
Jun
(120) |
Jul
(86) |
Aug
(149) |
Sep
(68) |
Oct
(66) |
Nov
(104) |
Dec
(49) |
| 2009 |
Jan
(131) |
Feb
(132) |
Mar
(125) |
Apr
(172) |
May
(161) |
Jun
(43) |
Jul
(47) |
Aug
(38) |
Sep
(18) |
Oct
(6) |
Nov
(1) |
Dec
(15) |
| 2010 |
Jan
(21) |
Feb
(8) |
Mar
(10) |
Apr
(4) |
May
(9) |
Jun
|
Jul
(1) |
Aug
|
Sep
|
Oct
(2) |
Nov
|
Dec
(4) |
| 2011 |
Jan
(23) |
Feb
(10) |
Mar
(13) |
Apr
(3) |
May
|
Jun
(19) |
Jul
(11) |
Aug
(22) |
Sep
|
Oct
(4) |
Nov
(2) |
Dec
(12) |
| 2012 |
Jan
(3) |
Feb
(4) |
Mar
(7) |
Apr
(3) |
May
|
Jun
(1) |
Jul
(1) |
Aug
(30) |
Sep
(3) |
Oct
(2) |
Nov
|
Dec
(8) |
| 2013 |
Jan
(3) |
Feb
(40) |
Mar
|
Apr
|
May
|
Jun
(1) |
Jul
|
Aug
|
Sep
|
Oct
|
Nov
(12) |
Dec
|
| 2021 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
(2) |
Oct
|
Nov
|
Dec
|
|
From: <ls...@us...> - 2007-05-17 20:37:51
|
Revision: 3219
http://jnode.svn.sourceforge.net/jnode/?rev=3219&view=rev
Author: lsantha
Date: 2007-05-17 13:37:49 -0700 (Thu, 17 May 2007)
Log Message:
-----------
Openjdk patches.
Removed Paths:
-------------
trunk/core/src/classpath/vm/sun/reflect/Reflection.java
Deleted: trunk/core/src/classpath/vm/sun/reflect/Reflection.java
===================================================================
--- trunk/core/src/classpath/vm/sun/reflect/Reflection.java 2007-05-17 20:37:34 UTC (rev 3218)
+++ trunk/core/src/classpath/vm/sun/reflect/Reflection.java 2007-05-17 20:37:49 UTC (rev 3219)
@@ -1,51 +0,0 @@
-/* Reflection.java - JSR 166 reflection hooks
- Copyright (C) 2006 Free Software Foundation
-
-This file is part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; see the file COPYING. If not, write to the
-Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301 USA.
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-package sun.reflect;
-
-import gnu.classpath.VMStackWalker;
-
-public class Reflection
-{
- /**
- * A stack-walking wrapper method used by the JSR 166 RI.
- */
- public static Class getCallerClass(int depth)
- {
- return VMStackWalker.getClassContext()[depth];
- }
-}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ls...@us...> - 2007-05-17 20:37:39
|
Revision: 3218
http://jnode.svn.sourceforge.net/jnode/?rev=3218&view=rev
Author: lsantha
Date: 2007-05-17 13:37:34 -0700 (Thu, 17 May 2007)
Log Message:
-----------
Openjdk patches.
Removed Paths:
-------------
trunk/core/src/classpath/sun/sun/misc/Service.java
trunk/core/src/classpath/sun/sun/misc/ServiceConfigurationError.java
Deleted: trunk/core/src/classpath/sun/sun/misc/Service.java
===================================================================
--- trunk/core/src/classpath/sun/sun/misc/Service.java 2007-05-17 19:15:01 UTC (rev 3217)
+++ trunk/core/src/classpath/sun/sun/misc/Service.java 2007-05-17 20:37:34 UTC (rev 3218)
@@ -1,66 +0,0 @@
-/* Service.java -- A wrapper around GNU service provision.
- Copyright (C) 2006 Free Software Foundation
-
-This file is part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; see the file COPYING. If not, write to the
-Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301 USA.
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-
-package sun.misc;
-
-import gnu.classpath.ServiceFactory;
-
-import java.util.Iterator;
-
-public class Service
-{
-
- /**
- * Returns an {@link Iterator} over the service providers which
- * provide a service of the given class, and are available from
- * the specified classloader.
- *
- * @param c the service provider interface which must be
- * implemented by any loaded service providers.
- * @param cl the class loader that will be used to load the
- * service providers, or <code>null</code> for the system class
- * loader.
- * @return an iterator over the service providers.
- */
- public static <P> Iterator<P> providers(Class<P> c, ClassLoader cl)
- {
- return (Iterator<P>) ServiceFactory.lookupProviders(c, cl);
- }
-
-}
-
Deleted: trunk/core/src/classpath/sun/sun/misc/ServiceConfigurationError.java
===================================================================
--- trunk/core/src/classpath/sun/sun/misc/ServiceConfigurationError.java 2007-05-17 19:15:01 UTC (rev 3217)
+++ trunk/core/src/classpath/sun/sun/misc/ServiceConfigurationError.java 2007-05-17 20:37:34 UTC (rev 3218)
@@ -1,64 +0,0 @@
-/* ServiceConfigurationError.java -- An error from service configuration.
- Copyright (C) 2006 Free Software Foundation
-
-This file is part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; see the file COPYING. If not, write to the
-Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301 USA.
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-
-package sun.misc;
-
-public class ServiceConfigurationError
- extends Error
-{
-
- /**
- * Constructs a new {@link ServiceConfigurationError}
- */
- public ServiceConfigurationError()
- {
- super();
- }
-
- /**
- * Constructs a new {@link ServiceConfigurationError}
- * with the specified message.
- */
- public ServiceConfigurationError(String message)
- {
- super(message);
- }
-
-
-}
-
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <fd...@us...> - 2007-05-17 19:15:06
|
Revision: 3217
http://jnode.svn.sourceforge.net/jnode/?rev=3217&view=rev
Author: fduminy
Date: 2007-05-17 12:15:01 -0700 (Thu, 17 May 2007)
Log Message:
-----------
fixed some classpath issues for eclipse
Modified Paths:
--------------
trunk/core/.classpath
trunk/net/.classpath
Modified: trunk/core/.classpath
===================================================================
--- trunk/core/.classpath 2007-05-17 19:04:55 UTC (rev 3216)
+++ trunk/core/.classpath 2007-05-17 19:15:01 UTC (rev 3217)
@@ -1,6 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
+ <classpathentry kind="src" path="src/openjdk/vm"/>
+ <classpathentry kind="src" path="src/openjdk/java"/>
+ <classpathentry kind="src" path="src/openjdk/javax"/>
+ <classpathentry kind="src" path="src/openjdk/sun"/>
<classpathentry kind="src" path="src/classpath/gnu"/>
+ <classpathentry kind="src" path="src/classpath/sun"/>
+ <classpathentry kind="src" path="src/classpath/tools"/>
<classpathentry kind="src" path="src/classpath/java"/>
<classpathentry kind="src" path="src/classpath/javax"/>
<classpathentry kind="src" path="src/classpath/org"/>
@@ -16,7 +22,7 @@
<classpathentry kind="lib" path="lib/log4j-1.2.8.jar"/>
<classpathentry kind="lib" path="lib/junit.jar"/>
<classpathentry kind="lib" path="lib/mx4j.jar"/>
- <classpathentry sourcepath="D:/epr/cvswork/MMTk/src" kind="lib" path="lib/mmtk/mmtk.jar"/>
+ <classpathentry kind="lib" path="lib/mmtk/mmtk.jar" sourcepath="D:/epr/cvswork/MMTk/src"/>
<classpathentry kind="src" path="src/nanoxml"/>
<classpathentry kind="lib" path="lib/mauve.jar"/>
<classpathentry kind="output" path="build/classes"/>
Modified: trunk/net/.classpath
===================================================================
--- trunk/net/.classpath 2007-05-17 19:04:55 UTC (rev 3216)
+++ trunk/net/.classpath 2007-05-17 19:15:01 UTC (rev 3217)
@@ -8,7 +8,7 @@
<classpathentry kind="src" path="/JNode-Shell"/>
<classpathentry kind="lib" path="/JNode-Core/lib/gnu-crypto.jar"/>
<classpathentry kind="lib" path="/JNode-Core/lib/javax-crypto.jar"/>
- <classpathentry kind="lib" path="lib/dnsjava-2.0.1a.jar"/>
+ <classpathentry kind="lib" path="lib/dnsjava-2.0.3.jar"/>
<classpathentry kind="lib" path="lib/jsch-0.1.24.jar"/>
<classpathentry kind="lib" path="/JNode-Core/lib/commons-net-1.1.0.jar"/>
<classpathentry kind="lib" path="/JNode-Core/lib/junit.jar"/>
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kon...@us...> - 2007-05-17 19:04:56
|
Revision: 3216
http://jnode.svn.sourceforge.net/jnode/?rev=3216&view=rev
Author: konkubinaten
Date: 2007-05-17 12:04:55 -0700 (Thu, 17 May 2007)
Log Message:
-----------
+ added cusomized mauve runner to jnode so we can run a complete testsuite without crashing jnode
Modified Paths:
--------------
trunk/core/descriptors/gnu.mauve.core.xml
Added Paths:
-----------
trunk/core/src/test/org/jnode/test/mauve/CheckResult.java
trunk/core/src/test/org/jnode/test/mauve/ClassResult.java
trunk/core/src/test/org/jnode/test/mauve/HTMLGenerator.java
trunk/core/src/test/org/jnode/test/mauve/MauveTestCommand.java
trunk/core/src/test/org/jnode/test/mauve/PackageResult.java
trunk/core/src/test/org/jnode/test/mauve/RunResult.java
trunk/core/src/test/org/jnode/test/mauve/TestResult.java
Modified: trunk/core/descriptors/gnu.mauve.core.xml
===================================================================
--- trunk/core/descriptors/gnu.mauve.core.xml 2007-05-17 18:34:44 UTC (rev 3215)
+++ trunk/core/descriptors/gnu.mauve.core.xml 2007-05-17 19:04:55 UTC (rev 3216)
@@ -11,7 +11,8 @@
<runtime>
<library name="mauve.jar">
- <export name="gnu/testlet/*"/>
+ <!-- export name="gnu/testlet/*"/ -->
+ <export name="*"/>
</library>
<library name="jnode-core.jar">
<export name="org/jnode/test/mauve/*"/>
@@ -21,6 +22,7 @@
<extension point="org.jnode.shell.aliases">
<alias name="mauve-plugin" class="org.jnode.test.mauve.PluginTestHarness"/>
<alias name="mauve-simple" class="org.jnode.test.mauve.SingleTestHarness"/>
+ <alias name="testCommand" class="org.jnode.test.mauve.MauveTestCommand"/>
</extension>
<extension point="org.jnode.security.permissions">
Added: trunk/core/src/test/org/jnode/test/mauve/CheckResult.java
===================================================================
--- trunk/core/src/test/org/jnode/test/mauve/CheckResult.java (rev 0)
+++ trunk/core/src/test/org/jnode/test/mauve/CheckResult.java 2007-05-17 19:04:55 UTC (rev 3216)
@@ -0,0 +1,172 @@
+// Tags: not-a-test
+// Copyright (C) 2004 by Object Refinery Limited
+// Written by David Gilbert (dav...@ob...)
+
+// This file is part of Mauve Reporter.
+
+// Mauve Reporter is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+
+// Mauve Reporter is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Mauve Reporter; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+package org.jnode.test.mauve;
+
+/**
+ * Records the details of a check that is performed by Mauve.
+ */
+public class CheckResult {
+
+ /** The check number. */
+ private int number;
+
+ /** The check point string. */
+ private String checkPoint;
+
+ /** A flag that indicates whether or not the check passed. */
+ private boolean passed;
+
+ /** The expected result (converted to a string). */
+ private String expected;
+
+ /** The actual result (converted to a string). */
+ private String actual;
+
+ /** The log output for the check. */
+ private StringBuffer log;
+
+ /**
+ * Creates a new check.
+ *
+ * @param number the check number.
+ * @param passed a flag that indicates whether or not the check passed.
+ */
+ CheckResult(int number, boolean passed) {
+ this.number = number;
+ this.passed = passed;
+ }
+
+ /**
+ * Returns the check number.
+ *
+ * @return The check number.
+ */
+ public int getNumber() {
+ return this.number;
+ }
+
+ /**
+ * Sets the check number.
+ *
+ * @param number the number.
+ */
+ void setNumber(int number) {
+ this.number = number;
+ }
+
+ /**
+ * Returns a flag that indicates whether or not the check passed.
+ *
+ * @return A boolean.
+ */
+ public boolean getPassed() {
+ return passed;
+ }
+
+ /**
+ * Sets the flag that indicates whether or not the check passed.
+ *
+ * @param passed the flag.
+ */
+ void setPassed(boolean passed) {
+ this.passed = passed;
+ }
+
+ /**
+ * Returns the check point string.
+ *
+ * @return The check point string.
+ */
+ public String getCheckPoint() {
+ return checkPoint;
+ }
+
+ /**
+ * Sets the check point string.
+ *
+ * @param checkPoint the check point string.
+ */
+ void setCheckPoint(String checkPoint) {
+ this.checkPoint = checkPoint;
+ }
+
+ /**
+ * Returns a string representing the actual value.
+ *
+ * @return The actual value.
+ */
+ public String getActual() {
+ if(actual == null)
+ return "n/a";
+ return actual;
+ }
+
+ /**
+ * Sets the actual value.
+ *
+ * @param actual the actual value.
+ */
+ void setActual(String actual) {
+ this.actual = actual;
+ }
+
+ /**
+ * Returns the expected value.
+ *
+ * @return The expected value.
+ */
+ public String getExpected() {
+ if(expected == null)
+ return "n/a";
+ return expected;
+ }
+
+ /**
+ * Sets the expected value.
+ *
+ * @param expected the expected value.
+ */
+ void setExpected(String expected) {
+ this.expected = expected;
+ }
+
+ /**
+ * Returns the log.
+ *
+ * @return The log.
+ */
+ public String getLog() {
+ if(log == null)
+ return "";
+ return log.toString();
+ }
+
+ /**
+ * Appends the specified message to the log.
+ *
+ * @param message the message to append.
+ */
+ void appendToLog(String message) {
+ if(log == null)
+ log = new StringBuffer();
+ log.append(message);
+ }
+}
Added: trunk/core/src/test/org/jnode/test/mauve/ClassResult.java
===================================================================
--- trunk/core/src/test/org/jnode/test/mauve/ClassResult.java (rev 0)
+++ trunk/core/src/test/org/jnode/test/mauve/ClassResult.java 2007-05-17 19:04:55 UTC (rev 3216)
@@ -0,0 +1,130 @@
+// Tags: not-a-test
+// Copyright (C) 2004 by Object Refinery Limited
+// Written by David Gilbert (dav...@ob...)
+
+// This file is part of Mauve Reporter.
+
+// Mauve Reporter is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+
+// Mauve Reporter is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Mauve Reporter; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+package org.jnode.test.mauve;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Represents the result of running all the tests for a particular class.
+ */
+public class ClassResult implements Comparable {
+
+ /** The name of the test (usually the class name). */
+ private String name;
+
+ /** A list containing results for each test applied for the class. */
+ private List testResults;
+ private boolean sorted = true;
+
+ /**
+ * Creates a new result, initially empty.
+ *
+ * @param name the class name.
+ */
+ ClassResult(String name) {
+ this.name = name;
+ testResults = new ArrayList();
+ }
+
+ /**
+ * Returns the test name (this is most often the name of the method
+ * being tested).
+ *
+ * @return The test name.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Sets the test name.
+ *
+ * @param name the name.
+ */
+ void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Adds a test result.
+ *
+ * @param result the test result.
+ */
+ public void add(TestResult result) {
+ testResults.add(result);
+ sorted = false;
+ }
+
+ /**
+ * Returns an iterator that provides access to all the tests for
+ * this class.
+ *
+ * @return An iterator.
+ */
+ public Iterator getTestIterator() {
+ if(!sorted) {
+ Collections.sort(testResults);
+ sorted = true;
+ }
+ return testResults.iterator();
+ }
+
+ /**
+ * Returns the total number of checks performed for this class.
+ *
+ * @return The check count.
+ */
+ public int getCheckCount() {
+ int result = 0;
+ Iterator iterator = testResults.iterator();
+ while (iterator.hasNext())
+ {
+ TestResult test = (TestResult) iterator.next();
+ result = result + test.getCheckCount();
+ }
+ return result;
+ }
+
+ /**
+ * Returns the number of checks with the specified status.
+ *
+ * @param passed the check status.
+ *
+ * @return The number of checks passed or failed.
+ */
+ public int getCheckCount(boolean passed) {
+ int result = 0;
+ Iterator iterator = testResults.iterator();
+ while (iterator.hasNext())
+ {
+ TestResult test = (TestResult) iterator.next();
+ result = result + test.getCheckCount(passed);
+ }
+ return result;
+ }
+
+ public int compareTo(Object obj) {
+ ClassResult that = (ClassResult) obj;
+ return getName().compareTo(that.getName());
+ }
+}
Added: trunk/core/src/test/org/jnode/test/mauve/HTMLGenerator.java
===================================================================
--- trunk/core/src/test/org/jnode/test/mauve/HTMLGenerator.java (rev 0)
+++ trunk/core/src/test/org/jnode/test/mauve/HTMLGenerator.java 2007-05-17 19:04:55 UTC (rev 3216)
@@ -0,0 +1,410 @@
+// Copyright (C) 2004 by Object Refinery Limited
+// Written by David Gilbert (dav...@ob...)
+
+// This file is part of Mauve Reporter.
+
+// Mauve Reporter is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+
+// Mauve Reporter is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Mauve Reporter; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+package org.jnode.test.mauve;
+
+import java.io.*;
+import java.text.DateFormat;
+import java.util.Date;
+import java.util.Iterator;
+
+/**
+ * Generates a collection of HTML files that summarise the results
+ * of a Mauve run. This is a quick-and-dirty implementation!!
+ */
+public class HTMLGenerator {
+
+ /**
+ * Creates an HTML report in the specified directory.
+ *
+ * @param run the Mauve run results.
+ * @param rootDirectory the root directory.
+ */
+ public static void createReport(RunResult run, File rootDirectory) throws IOException {
+ // write basic HTML with info about package
+ File summaryFile = new File(rootDirectory, "index.html");
+ Writer out = new OutputStreamWriter(new FileOutputStream(summaryFile), "UTF-8");
+ PrintWriter writer = new PrintWriter(out);
+ writer.println("<HTML>");
+ writer.println("<HEAD><TITLE>Mauve Run: " + run.getName() + "</TITLE>");
+ writer.println("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" /></HEAD>");
+ writer.println("<BODY>");
+ writer.println("<h1>Mauve Run</h1>");
+ writer.println("<h2>Summary:</h2>");
+ int checkCount = run.getCheckCount();
+ int passed = run.getCheckCount(true);
+ int failed = checkCount - passed;
+ writer.println("Run Date: " + DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG).format(new Date()) + "<br>");
+ writer.println("Passed: " + passed + "<br>");
+ writer.println("Failed: " + failed + "<p>");
+
+ writer.println("<h2>Environment:</h2>");
+
+ writer.println("<table BORDER=\"0\" CELLPADDING=\"0\">");
+ writer.println("<tr>");
+ writer.println("<td bgcolor=\"black\" VALIGN=\"TOP\">");
+ writer.println("<table BORDER=\"0\" WIDTH=\"100%\" CELLSPACING=\"1\" CELLPADDING=\"3\">");
+ writer.println("<tr>");
+ writer.println("<td bgcolor=\"lightGray\">Property:</td>");
+ writer.println("<td bgcolor=\"lightGray\">Value:</td>");
+ writer.println("</tr>");
+
+ writePropertyRow("java.version", System.getProperty("java.version"), writer);
+ writePropertyRow("java.vendor", System.getProperty("java.vendor"), writer);
+ writePropertyRow("java.vendor.url", System.getProperty("java.vendor.url"), writer);
+ writePropertyRow("os.name", System.getProperty("os.name"), writer);
+ writePropertyRow("os.arch", System.getProperty("os.arch"), writer);
+ writePropertyRow("os.version", System.getProperty("os.version"), writer);
+
+ writePropertyRow("java.vm.specification.version", System.getProperty("java.vm.specification.version"), writer);
+ writePropertyRow("java.vm.specification.vendor", System.getProperty("java.vm.specification.vendor"), writer);
+ writePropertyRow("java.vm.specification.name", System.getProperty("java.vm.specification.name"), writer);
+ writePropertyRow("java.vm.version", System.getProperty("java.vm.version"), writer);
+ writePropertyRow("java.vm.vendor", System.getProperty("java.vm.vendor"), writer);
+ writePropertyRow("java.vm.name", System.getProperty("java.vm.name"), writer);
+ writePropertyRow("java.specification.version", System.getProperty("java.specification.version"), writer);
+ writePropertyRow("java.specification.vendor", System.getProperty("java.specification.vendor"), writer);
+ writePropertyRow("java.specification.name", System.getProperty("java.specification.name"), writer);
+ writePropertyRow("java.class.version", System.getProperty("java.class.version"), writer);
+
+ writer.println("</table>");
+ writer.println("</td>");
+ writer.println("</tr>");
+ writer.println("</table><p>");
+
+ writer.println("<h2>Results:</h2>");
+
+ writer.println("<table BORDER=\"0\" width=\"100%\" CELLPADDING=\"0\">");
+ writer.println("<tr>");
+ writer.println("<td bgcolor=\"black\" VALIGN=\"TOP\">");
+ writer.println("<table BORDER=\"0\" WIDTH=\"100%\" CELLSPACING=\"1\" CELLPADDING=\"3\">");
+ writer.println("<tr>");
+ writer.println("<td bgcolor=\"lightGray\">Package:</td>");
+ writer.println("<td bgcolor=\"lightGray\">Passed:</td>");
+ writer.println("<td bgcolor=\"lightGray\">Failed:</td>");
+ writer.println("<td bgcolor=\"lightGray\">Total:</td>");
+ writer.println("</tr>");
+
+ // loop through tests writing test results
+ String top = null;
+ Iterator iterator = run.getPackageIterator();
+ while (iterator.hasNext()) {
+ PackageResult packageResult = (PackageResult) iterator.next();
+ String packageName = packageResult.getName().replace('.', '/');
+ String name;
+ System.out.println("Generating " + packageName);
+ if(top != null && packageName.startsWith(top))
+ name = " + "+ packageName.substring(top.length()+1);
+ else {
+ top = packageName;
+ name = packageName;
+ }
+ // (1) write the summary line for the class HTML file
+ writer.println("<tr>");
+ writer.println("<td bgcolor=\"white\"><a href=\"" + packageName + "/package_index.html\"" + ">" + name + "</a></td>");
+ writer.println("<td bgcolor=\"white\">" + packageResult.getCheckCount(true) + "</td>");
+ writer.println("<td bgcolor=\"white\">" + packageResult.getCheckCount(false) + "</td>");
+ writer.println("<td bgcolor=\"white\">" + packageResult.getCheckCount() + "</td>");
+ writer.println("</tr>");
+ // (2) generate an HTML page for the test and subfiles
+ // for the tests
+ HTMLGenerator.createPackageReport(packageResult, rootDirectory);
+ }
+ writer.println("</table>");
+ writer.println("</td>");
+ writer.println("</tr>");
+ writer.println("</table>");
+ writer.println("<p>");
+ Iterator missing = run.getMissingTestsIterator();
+ Iterator failures = run.getFaultyTestsIterator();
+ if(missing.hasNext() || failures.hasNext()) {
+ writer.println("<h2>Unrunnable tests:</h2>");
+
+ writer.println("<table BORDER=\"0\" width=\"100%\" CELLPADDING=\"0\">");
+ writer.println("<tr>");
+ writer.println("<td bgcolor=\"black\" VALIGN=\"TOP\">");
+ writer.println("<table BORDER=\"0\" WIDTH=\"100%\" CELLSPACING=\"1\" CELLPADDING=\"3\">");
+ writer.println("<tr>");
+ writer.println("<td bgcolor=\"lightGray\">name:</td>");
+ writer.println("<td bgcolor=\"lightGray\">problem:</td>");
+ writer.println("</tr>");
+ while(missing.hasNext())
+ writer.println("<tr><td bgcolor=\"white\">"+ (String) missing.next()+
+ "</td><td bgcolor=\"white\">Class not found</td></tr>");
+ while(failures.hasNext()) {
+ String[] fail = (String[]) failures.next();
+ writer.println("<tr><td bgcolor=\"white\">"+ fail[0] +"</td><td bgcolor=\"white\">"+
+ fail[1] +"</td></tr>");
+ }
+ writer.println("</table>");
+ writer.println("</td>");
+ writer.println("</tr>");
+ writer.println("</table>");
+ }
+
+ writer.println("</BODY>");
+ writer.println("</HTML>");
+ writer.close();
+ }
+
+ /**
+ * Writes a row in a table for a pair of strings.
+ *
+ * @param property the property key.
+ * @param value the property value.
+ * @param writer the output stream.
+ */
+ private static void writePropertyRow(String property, String value, PrintWriter writer) {
+ writer.println("<tr>");
+ writer.println("<td bgcolor=\"white\">" + property + "</td>");
+ writer.println("<td bgcolor=\"white\">" + value + "</td>");
+ writer.println("</tr>");
+ }
+
+ /**
+ * Returns the number of directory levels in the specified package name.
+ *
+ * @param name the name.
+ *
+ * @return The number of directory levels.
+ */
+ private static int countLevels(String name) {
+ int result = 1;
+ for (int i = 0; i < name.length(); i++) {
+ if (name.charAt(i) == '/') result++;
+ }
+ return result;
+ }
+
+ /**
+ * Creates an HTML page that summaries a package, and processes all the classes within
+ * the package.
+ *
+ * @param packageResult the package result.
+ * @param rootDirectory the root directory.
+ */
+ public static void createPackageReport(PackageResult packageResult, File rootDirectory) throws IOException {
+ // create directory for package
+ String packageName = packageResult.getName().replace('.', '/');
+ String prefix = "";
+ int levels = countLevels(packageName);
+ for (int i = 0; i < levels; i++)
+ prefix += "../";
+ File packageDirectory = new File(rootDirectory, packageName);
+ packageDirectory.mkdirs();
+
+ // write basic HTML with info about package
+ File summaryFile = new File(packageDirectory, "package_index.html");
+ OutputStream out = new BufferedOutputStream(new FileOutputStream(summaryFile));
+ PrintWriter writer = new PrintWriter(out);
+ writer.println("<HTML>");
+ writer.println("<HEAD><TITLE>Package Summary: " + packageResult.getName() + "</TITLE></HEAD>");
+ writer.println("<BODY>");
+ writer.println("<h2>Package: " + packageResult.getName() + "</h2>");
+ writer.println("<a href=\"" + prefix + "index.html\">Summary page</a><p>");
+ int checkCount = packageResult.getCheckCount();
+ int passed = packageResult.getCheckCount(true);
+ int failed = checkCount - passed;
+ writer.println("Passed: " + passed + "<br>");
+ writer.println("Failed: " + failed + "<p>");
+ writer.println("<table BORDER=\"0\" width=\"100%\" CELLPADDING=\"0\">");
+ writer.println("<tr>");
+ writer.println("<td bgcolor=\"black\" VALIGN=\"TOP\">");
+ writer.println("<table BORDER=\"0\" WIDTH=\"100%\" CELLSPACING=\"1\" CELLPADDING=\"3\">");
+ writer.println("<tr>");
+ writer.println("<td bgcolor=\"lightGray\">Class:</td>");
+ writer.println("<td bgcolor=\"lightGray\">Passed:</td>");
+ writer.println("<td bgcolor=\"lightGray\">Failed:</td>");
+ writer.println("<td bgcolor=\"lightGray\">Total:</td>");
+ writer.println("</tr>");
+
+ // loop through tests writing test results
+ Iterator iterator = packageResult.getClassIterator();
+ while (iterator.hasNext()) {
+ ClassResult classResult = (ClassResult) iterator.next();
+ // (1) write the summary line for the class HTML file
+ writer.println("<tr>");
+ writer.println("<td bgcolor=\"white\"><a href=\"" + classResult.getName() + "/class_index.html\"" + ">" + classResult.getName() + "</a></td>");
+ writer.println("<td bgcolor=\"white\">" + classResult.getCheckCount(true) + "</td>");
+ writer.println("<td bgcolor=\"white\">" + classResult.getCheckCount(false) + "</td>");
+ writer.println("<td bgcolor=\"white\">" + classResult.getCheckCount() + "</td>");
+ writer.println("</tr>");
+ // (2) generate an HTML page for the test and subfiles
+ // for the tests
+ HTMLGenerator.createClassReport(classResult, packageResult.getName(), packageDirectory);
+ }
+ // close the class file
+ writer.println("</table>");
+ writer.println("</td>");
+ writer.println("</tr>");
+ writer.println("</table>");
+ writer.println("</BODY>");
+ writer.println("</HTML>");
+ writer.close();
+ }
+
+ /**
+ * Creates an HTML page summarising the results for a class, and processes all the tests for
+ * the class.
+ *
+ * @param classResult the class results.
+ * @param packageName the package name.
+ * @param packageDirectory the package directory.
+ */
+ public static void createClassReport(ClassResult classResult, String packageName, File packageDirectory) throws IOException {
+ // create directory for class
+ File classDirectory = new File(packageDirectory, classResult.getName());
+ classDirectory.mkdirs();
+
+ // write basic HTML with info about class
+ File testFile = new File(classDirectory, "class_index.html");
+ OutputStream out = new BufferedOutputStream(new FileOutputStream(testFile));
+ PrintWriter writer = new PrintWriter(out);
+ writer.println("<HTML>");
+ writer.println("<HEAD><TITLE>Class Summary: " + packageName + "." + classResult.getName() + "</TITLE></HEAD>");
+ writer.println("<BODY>");
+ writer.println("<h2>Class: " + "<a href=\"../package_index.html\">" + packageName +"</a>." + classResult.getName() + "</h2>");
+ int checkCount = classResult.getCheckCount();
+ int passed = classResult.getCheckCount(true);
+ int failed = checkCount - passed;
+ writer.println("Passed: " + passed + "<br>");
+ writer.println("Failed: " + failed + "<p>");
+ writer.println("<table BORDER=\"0\" width=\"100%\" CELLPADDING=\"0\">");
+ writer.println("<tr>");
+ writer.println("<td bgcolor=\"black\" VALIGN=\"TOP\">");
+ writer.println("<table BORDER=\"0\" WIDTH=\"100%\" CELLSPACING=\"1\" CELLPADDING=\"3\">");
+ writer.println("<tr>");
+ writer.println("<td bgcolor=\"lightGray\">Test:</td>");
+ writer.println("<td bgcolor=\"lightGray\">Passed:</td>");
+ writer.println("<td bgcolor=\"lightGray\">Failed:</td>");
+ writer.println("<td bgcolor=\"lightGray\">Total:</td>");
+ writer.println("</tr>");
+
+ // loop through tests writing test results
+ Iterator iterator = classResult.getTestIterator();
+ while (iterator.hasNext()) {
+ TestResult testResult = (TestResult) iterator.next();
+ // (1) write the summary line for the class HTML file
+ writer.println("<tr>");
+ writer.println("<td bgcolor=\"white\"><a href=\"" + testResult.getName() + ".html\"" + ">" + testResult.getName() + "</a></td>");
+ writer.println("<td bgcolor=\"white\">" + testResult.getCheckCount(true) + "</td>");
+ writer.println("<td bgcolor=\"white\">" + testResult.getCheckCount(false) + "</td>");
+ writer.println("<td bgcolor=\"white\">" + testResult.getCheckCount() + "</td>");
+ writer.println("</tr>");
+ // (2) generate an HTML page for the test and subfiles
+ // for the tests
+ HTMLGenerator.createTestReport(testResult, classResult.getName(), classDirectory);
+ }
+ // close the class file
+ writer.println("</table>");
+ writer.println("</td>");
+ writer.println("</tr>");
+ writer.println("</table>");
+ writer.println("</BODY>");
+ writer.println("</HTML>");
+ writer.close();
+ }
+
+ /**
+ * Creates an HTML page that summarises a test.
+ *
+ * @param testResult the test result.
+ * @param className the class name.
+ * @param classDirectory the class directory.
+ */
+ public static void createTestReport(TestResult testResult, String className, File classDirectory) throws IOException {
+
+ // write basic HTML for test
+ File testFile = new File(classDirectory, testResult.getName() + ".html");
+ Writer out = new OutputStreamWriter(new FileOutputStream(testFile), "UTF-8");
+ PrintWriter writer = new PrintWriter(out);
+ writer.println("<HTML>");
+ writer.println("<HEAD><TITLE>Test Summary: " + className + "." + testResult.getName() + "</TITLE>\n");
+ writer.println("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" /></HEAD>");
+ writer.println("<BODY>");
+ writer.println("<h2>Test: <a href=\"class_index.html\">" + className + "</a>." + testResult.getName() + "</h2>");
+ int checkCount = testResult.getCheckCount();
+ int passed = testResult.getCheckCount(true);
+ int failed = checkCount - passed;
+ writer.println("Passed: " + passed + "<br>");
+ writer.println("Failed: " + failed + "<p>");
+ writer.println("<table BORDER=\"0\" width=\"100%\" CELLPADDING=\"0\">");
+ writer.println("<tr>");
+ writer.println("<td bgcolor=\"black\" VALIGN=\"TOP\">");
+ writer.println("<table BORDER=\"0\" WIDTH=\"100%\" CELLSPACING=\"1\" CELLPADDING=\"3\">");
+ writer.println("<tr>");
+ writer.println("<td bgcolor=\"lightGray\">Check Number:</td>");
+ writer.println("<td bgcolor=\"lightGray\">Check Point:</td>");
+ writer.println("<td bgcolor=\"lightGray\">Passed?:</td>");
+ writer.println("<td bgcolor=\"lightGray\">Expected:</td>");
+ writer.println("<td bgcolor=\"lightGray\">Actual:</td>");
+ writer.println("</tr>");
+
+ // loop through checks adding a summary line for each check
+ Iterator iterator = testResult.getCheckIterator();
+ while (iterator.hasNext()) {
+ CheckResult check = (CheckResult) iterator.next();
+ // write a summary line (ID, pass/fail, actual, expected);
+ writer.println("<tr><td bgcolor=\"white\">" + check.getNumber() +
+ "</td><td bgcolor=\"white\">" + check.getCheckPoint() +
+ "</td><td bgcolor=\"" + (check.getPassed() ? "white" : "red") + "\">" +
+ check.getPassed() + "</td><td bgcolor=\"white\">" + check.getExpected() +
+ "</td><td bgcolor=\"white\">" + check.getActual() + "</td>");
+ if (!check.getPassed()) {
+ createLogReport(check, className, testResult.getName(), classDirectory);
+ }
+ writer.println("</td>");
+ writer.println("</tr>");
+ }
+ writer.println("</table>");
+ writer.println("</td>");
+ writer.println("</tr>");
+ writer.println("</table>");
+ if(testResult.isFailed()) {
+ writer.println("<h2>Run aborted due to exception</h2>");
+ writer.println("<pre>"+ testResult.getFailedMessage() +"</pre>");
+ }
+ writer.println("</BODY>");
+ writer.println("</HTML>");
+ writer.close();
+ }
+
+ /**
+ * Creates an HTML page that summarises the log for a check.
+ *
+ * @param checkResult the test result.
+ * @param className the class name.
+ * @param testName the test name.
+ * @param classDirectory the class directory.
+ */
+ public static void createLogReport(CheckResult checkResult, String className, String testName, File classDirectory) throws IOException {
+ // write basic HTML for test
+ File logFile = new File(classDirectory, testName + "_log.html");
+ OutputStream out = new BufferedOutputStream(new FileOutputStream(logFile));
+ PrintWriter writer = new PrintWriter(out);
+ writer.println("<HTML>");
+ writer.println("<HEAD><TITLE>Log: " + testName + "</TITLE>");
+ writer.println("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" /></HEAD>");
+ writer.println("<BODY>");
+ writer.println(checkResult.getLog());
+ writer.println("</BODY>");
+ writer.println("</HTML>");
+
+ writer.close();
+ }
+}
Added: trunk/core/src/test/org/jnode/test/mauve/MauveTestCommand.java
===================================================================
--- trunk/core/src/test/org/jnode/test/mauve/MauveTestCommand.java (rev 0)
+++ trunk/core/src/test/org/jnode/test/mauve/MauveTestCommand.java 2007-05-17 19:04:55 UTC (rev 3216)
@@ -0,0 +1,506 @@
+// Copyright (C) 2004, 2005 by Object Refinery Limited
+// Copyright (C) 2005 by <za...@kd...>
+// Written by David Gilbert (dav...@ob...)
+// Written by Thomas Zander <za...@kd...>
+
+// This file is part of Mauve.
+
+// Mauve is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// Mauve is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Mauve; see the file COPYING. If not, write to
+// the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+// Boston, MA 02110-1301 USA.
+package org.jnode.test.mauve;
+
+import gnu.testlet.ResourceNotFoundException;
+import gnu.testlet.TestHarness;
+import gnu.testlet.Testlet;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.LineNumberReader;
+import java.io.PrintWriter;
+import java.io.Reader;
+import java.util.Locale;
+
+/**
+ * Modified Mauve Test Suite
+ *
+ * @author peda
+ */
+public class MauveTestCommand extends TestHarness {
+
+ private String lastCheckPoint;
+
+ private int checksSinceLastCheckPoint;
+
+ private ClassResult classResult;
+
+ private TestResult currentTest;
+
+ private CheckResult currentCheck;
+
+ private RunResult result;
+
+ /**
+ * runs tests
+ *
+ * @param file
+ * the text file containing test class names.
+ * @param prefix
+ * the prefix for each test class (usually 'gnu.testlet').
+ * @param output
+ * the name of the directory for writing output.
+ */
+ public synchronized void execute(String file, String prefix, String output) {
+
+ // save the default locale, some tests change the default and we want
+ // to restore it before generating the HTML report...
+ Locale savedLocale = Locale.getDefault();
+
+ File out = new File(output);
+ if (out.exists() && !out.isDirectory())
+ throw new IllegalArgumentException("Output should be a directory");
+
+ if (!out.exists())
+ out.mkdirs();
+
+ result = new RunResult("Mauve Test Run");
+ currentCheck = new CheckResult(0, false);
+
+ // initialize
+ // run tests and collect results
+ File f = new File(file);
+ try {
+
+ FileReader testsToRun = new FileReader(f);
+ LineNumberReader r = new LineNumberReader(testsToRun);
+
+ while (r.ready()) {
+
+ String line = r.readLine();
+
+ if ("".equals(line))
+ continue;
+
+ System.out.println(line);
+
+ // check the line is not commented
+ // load the listed class
+ try {
+ Class c = Class.forName(line);
+ // strip prefix ('gnu.testlet.') from front of name
+ String temp = line.substring(prefix.length());
+ // suffix is the name for the TestResult
+ String testName = temp.substring(temp.lastIndexOf('.') + 1);
+
+ temp = temp.substring(0, temp.lastIndexOf('.'));
+ String className = temp
+ .substring(temp.lastIndexOf('.') + 1);
+ if (className.equals("Double") || className.equals("Float")
+ || className.equals("Key")) {
+ if (!temp.startsWith("java.lang.")) {
+ temp = temp.substring(0, temp.lastIndexOf('.'));
+ className = temp
+ .substring(temp.lastIndexOf('.') + 1)
+ + '.' + className;
+ }
+ }
+
+ String packageName = "default package";
+ int index = temp.lastIndexOf('.');
+ if (index >= 0)
+ packageName = temp.substring(0, temp.lastIndexOf('.'));
+
+ // remaining suffix is name for ClassResult
+ // rest of text is name for PackageResult
+ PackageResult pr = result.getPackageResult(packageName);
+ if (pr == null)
+ pr = new PackageResult(packageName);
+
+ classResult = pr.getClassResult(className);
+ if (classResult == null)
+ classResult = new ClassResult(className);
+
+ Testlet testlet;
+ try {
+ testlet = (Testlet) c.newInstance();
+ } catch (ClassCastException e) {
+ System.err.println("Not a test (does not implement Testlet): " + line);
+ result.addFaultyTest(line, "Does not implement Testlet");
+ continue; // not a test
+ } catch (Throwable t) { // instanciation errors etc..
+ t.printStackTrace(System.out);
+ result.addFaultyTest(line, t.getMessage());
+ continue;
+ }
+
+ currentTest = new TestResult(testName);
+ checksSinceLastCheckPoint = 0;
+ lastCheckPoint = "-";
+ try {
+ testlet.test(this);
+ } catch (Throwable t) {
+ t.printStackTrace(System.out);
+ currentTest.failed(t);
+ }
+
+ classResult.add(currentTest);
+ if (pr.indexOf(classResult) < 0)
+ pr.add(classResult);
+ if (result.indexOf(pr) == -1)
+ result.add(pr);
+ } catch (ClassNotFoundException e) {
+ System.err.println("Could not load test: " + line);
+ result.addMissingTest(line);
+ }
+
+ System.out.println("Test done, now running gc");
+ System.gc();
+
+ }
+ } catch (FileNotFoundException e) {
+ throw new IllegalArgumentException(e.getMessage());
+ } catch (IOException e) {
+ e.printStackTrace(System.out);
+ }
+
+ // tests are complete so restore the default locale
+ Locale.setDefault(savedLocale);
+
+ // write results to HTML
+ System.out.println("Creating HTML report...");
+ try {
+ HTMLGenerator.createReport(result, out);
+ } catch (IOException e) {
+ System.out.println("failed to write HTML due to following error:");
+ e.printStackTrace(System.out);
+ }
+ System.out.println("Creating XML report...");
+
+ /*
+ try {
+ new XMLGenerator(result).generate(new File(out, "results.xml"));
+ } catch (IOException e) {
+ System.out.println("failed to write XML due to following error:");
+ e.printStackTrace(System.out);
+ }
+ */
+
+ System.out.println("DONE!");
+ }
+
+ /**
+ * Records the result of a boolean check.
+ *
+ * @param result
+ * the result.
+ */
+ public void check(boolean result) {
+ currentCheck.setPassed(result);
+ checkDone();
+ }
+
+ /**
+ * Checks the two objects for equality and records the result of the check.
+ *
+ * @param result
+ * the actual result.
+ * @param expected
+ * the expected result.
+ */
+ public void check(Object result, Object expected) {
+ currentCheck.setPassed((result != null) ? result.equals(expected) : (expected == null));
+ currentCheck.setActual((result != null) ? result.toString() : "null");
+ currentCheck.setExpected((expected != null) ? expected.toString() : "null");
+ checkDone();
+ }
+
+ /**
+ * Checks two booleans for equality and records the result of the check.
+ *
+ * @param result
+ * the actual result.
+ * @param expected
+ * the expected result.
+ */
+ public void check(boolean result, boolean expected) {
+ currentCheck.setPassed(result == expected);
+ currentCheck.setActual(String.valueOf(result));
+ currentCheck.setExpected(String.valueOf(expected));
+ checkDone();
+ }
+
+ /**
+ * Checks two ints for equality and records the result of the check.
+ *
+ * @param result
+ * the actual result.
+ * @param expected
+ * the expected result.
+ */
+ public void check(int result, int expected) {
+ currentCheck.setPassed(result == expected);
+ currentCheck.setActual(String.valueOf(result));
+ currentCheck.setExpected(String.valueOf(expected));
+ checkDone();
+ }
+
+ /**
+ * Checks two longs for equality and records the result of the check.
+ *
+ * @param result
+ * the actual result.
+ * @param expected
+ * the expected result.
+ */
+ public void check(long result, long expected) {
+ currentCheck.setPassed(result == expected);
+ currentCheck.setActual(String.valueOf(result));
+ currentCheck.setExpected(String.valueOf(expected));
+ checkDone();
+ }
+
+ /**
+ * Checks two doubles for equality and records the result of the check.
+ *
+ * @param result
+ * the actual result.
+ * @param expected
+ * the expected result.
+ */
+ public void check(double result, double expected) {
+ currentCheck.setPassed((result == expected ? (result != 0) || (1 / result == 1 / expected) : (result != result)
+ && (expected != expected)));
+ currentCheck.setActual(String.valueOf(result));
+ currentCheck.setExpected(String.valueOf(expected));
+ checkDone();
+ }
+
+ /**
+ * Records a check point. This can be used to mark a known place in a
+ * testlet. It is useful if you have a large number of tests -- it makes it
+ * easier to find a failing test in the source code.
+ *
+ * @param name
+ * the check point name.
+ */
+ public void checkPoint(String name) {
+ lastCheckPoint = name;
+ checksSinceLastCheckPoint = 0;
+ }
+
+ private void checkDone() {
+ currentCheck.setNumber(++checksSinceLastCheckPoint);
+ currentCheck.setCheckPoint(lastCheckPoint);
+ currentTest.add(currentCheck);
+ currentCheck = new CheckResult(0, false);
+ currentCheck.setCheckPoint(lastCheckPoint);
+ }
+
+ /**
+ * Writes a message to the debug log along with a newline.
+ *
+ * @param message
+ * the message.
+ */
+ public void debug(String message) {
+ debug(message, true);
+ }
+
+ /**
+ * Writes a message to the debug log with or without a newline.
+ *
+ * @param message
+ * the message.
+ * @param newline
+ * a flag to control whether or not a newline is added.
+ */
+ public void debug(String message, boolean newline) {
+ currentCheck.appendToLog(message);
+ if (newline)
+ currentCheck.appendToLog("\n");
+ }
+
+ /**
+ * Writes the contents of an array to the log.
+ *
+ * @param o
+ * the array of objects.
+ * @param desc
+ * the description.
+ */
+ public void debug(Object[] o, String desc) {
+ StringBuffer logMessage = new StringBuffer();
+ logMessage.append("Object array: ");
+ logMessage.append(desc);
+ if (o == null)
+ logMessage.append("null");
+ else
+ expand(o, logMessage);
+ currentCheck.appendToLog(logMessage.toString());
+ currentCheck.appendToLog("\n");
+ }
+
+ // recursive helper method for debug(Object[], String)
+ private void expand(Object[] array, StringBuffer buf) {
+ for (int i = 0; i < array.length; i++) {
+ buf.append("obj[" + i + "]: ");
+ if (array[i] instanceof Object[])
+ expand((Object[]) array[i], buf);
+ else if (array[i] != null)
+ buf.append(array[i].toString());
+ else
+ buf.append("null");
+ if (i < array.length)
+ buf.append(", ");
+ }
+ }
+
+ /**
+ * Writes a stack trace for the specified exception to the log for the
+ * current check.
+ *
+ * @param ex
+ * the exception.
+ */
+ public void debug(Throwable ex) {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ PrintWriter w = new PrintWriter(out, false);
+ ex.printStackTrace(w);
+ w.close();
+ try {
+ out.close();
+ debug(out.toString(), true);
+ } catch (IOException e) {
+ /* this should never happen.. */
+ }
+ }
+
+ /**
+ * This will print a message when in verbose mode.
+ *
+ * @param message
+ * the message.
+ */
+ public void verbose(String message) {
+ debug(message, true);
+ }
+
+ public Reader getResourceReader(String name) throws ResourceNotFoundException {
+ return new BufferedReader(
+ new InputStreamReader(getResourceStream(name)));
+ }
+
+ public InputStream getResourceStream(String name) throws ResourceNotFoundException {
+ // The following code assumes File.separator is a single character.
+ if (File.separator.length() > 1)
+ throw new Error("File.separator length is greater than 1");
+ String realName = name.replace('#', File.separator.charAt(0));
+ try {
+ return new FileInputStream(getSourceDirectory() + File.separator + realName);
+ } catch (FileNotFoundException ex) {
+ throw new ResourceNotFoundException(ex.getLocalizedMessage() + ": "
+ + getSourceDirectory() + File.separator + realName);
+ }
+ }
+
+ public String getSourceDirectory() {
+ return null; // TODO
+ }
+
+ public File getResourceFile(String name) throws ResourceNotFoundException {
+ // The following code assumes File.separator is a single character.
+ if (File.separator.length() > 1)
+ throw new Error("File.separator length is greater than 1");
+ String realName = name.replace('#', File.separator.charAt(0));
+ File f = new File(getSourceDirectory() + File.separator + realName);
+ if (!f.exists()) {
+ throw new ResourceNotFoundException("cannot find mauve resource file" + ": "
+ + getSourceDirectory() + File.separator + realName);
+ }
+ return f;
+ }
+
+ /**
+ * Provide a directory name for writing temporary files.
+ *
+ * @return The temporary directory name.
+ */
+ public String getTempDirectory() {
+ // TODO
+ return "/tmp";
+ }
+
+ /**
+ * Runs the application to generate an HTML report for a collection of Mauve
+ * tests.
+ *
+ * @param args
+ * the command line arguments.
+ */
+ public static void main(String[] args) {
+ // -prefix <package-prefix>
+ // -output <root-directory-for-HTML-output>
+ String file = "tests";
+ String prefix = "gnu.testlet.";
+ String output = "results";
+ for (int i = 0; i < args.length; i++) {
+ String a = args[i];
+ if (a.equals("--prefix") || a.equals("-p")) {
+ if (i < args.length) {
+ prefix = args[i + 1];
+ i++;
+ } else {
+ System.err.println("prefix: value missing");
+ return;
+ }
+ } else if (a.equals("--output") || a.equals("-o")) {
+ if (i < args.length) {
+ output = args[i + 1];
+ i++;
+ } else {
+ System.err.println("output: value missing");
+ return;
+ }
+ } else if (a.equals("--help") || a.equals("-h")) {
+ System.out.println("Usage: Mauve [options] [inputfile]");
+ System.out
+ .println("reads test-class names from inputfile and executes them;");
+ System.out
+ .println("If no inputfile is passed, then tests.txt will be used");
+ System.out.println(" options:");
+ System.out.println(" --help -h this help");
+ System.out
+ .println(" --output -o the output directory [results]");
+ System.out
+ .println(" --prefix -p package prefix [gnu.testlet]");
+ return;
+ } else
+ file = a;
+ }
+ try {
+ new MauveTestCommand().execute(file, prefix, output);
+ } catch (IllegalArgumentException e) {
+ System.err.println(e.getMessage());
+ System.err.println("Try --help for more info");
+ }
+ System.exit(0);
+ }
+}
Added: trunk/core/src/test/org/jnode/test/mauve/PackageResult.java
===================================================================
--- trunk/core/src/test/org/jnode/test/mauve/PackageResult.java (rev 0)
+++ trunk/core/src/test/org/jnode/test/mauve/PackageResult.java 2007-05-17 19:04:55 UTC (rev 3216)
@@ -0,0 +1,161 @@
+// Tags: not-a-test
+// Copyright (C) 2004 by Object Refinery Limited
+// Written by David Gilbert (dav...@ob...)
+
+// This file is part of Mauve Reporter.
+
+// Mauve Reporter is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+
+// Mauve Reporter is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Mauve Reporter; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+package org.jnode.test.mauve;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Represents the result of running all the tests for a particular package.
+ */
+public class PackageResult implements Comparable {
+
+ /** The name of the package. */
+ private String name;
+
+ /** A list containing results for each class in the package. */
+ private List classResults;
+ private boolean sorted=true;
+
+ /**
+ * Creates a new result, initially empty.
+ *
+ * @param name the class name.
+ */
+ PackageResult(String name) {
+ this.name = name;
+ classResults = new ArrayList();
+ }
+
+ /**
+ * Returns the package name.
+ *
+ * @return The package name.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Sets the package name.
+ *
+ * @param name the name.
+ */
+ void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Adds a class result.
+ *
+ * @param result the test result.
+ */
+ void add(ClassResult result) {
+ classResults.add(result);
+ sorted = false;
+ }
+
+ /**
+ * Returns an iterator that provides access to the class results.
+ *
+ * @return An iterator.
+ */
+ public Iterator getClassIterator() {
+ sortClasses();
+ return classResults.iterator();
+ }
+
+ /**
+ * Returns the class result for the named class.
+ *
+ * @param name the class name.
+ *
+ * @return A class result.
+ */
+ public ClassResult getClassResult(String name) {
+ sortClasses();
+ for (int i = 0; i < classResults.size(); i++) {
+ ClassResult cr = (ClassResult) classResults.get(i);
+ if (cr.getName().equals(name))
+ return cr;
+ }
+ return null;
+ }
+
+ /**
+ * Returns the total number of checks performed for this package.
+ *
+ * @return The check count.
+ */
+ public int getCheckCount() {
+ int result = 0;
+ Iterator iterator = getClassIterator();
+ while (iterator.hasNext()) {
+ ClassResult cr = (ClassResult) iterator.next();
+ result = result + cr.getCheckCount();
+ }
+ return result;
+ }
+
+ /**
+ * Returns the number of checks with the specified status.
+ *
+ * @param passed the check status.
+ *
+ * @return The number of checks passed or failed.
+ */
+ public int getCheckCount(boolean passed) {
+ int result = 0;
+ Iterator iterator = getClassIterator();
+ while (iterator.hasNext()) {
+ ClassResult cr = (ClassResult) iterator.next();
+ result = result + cr.getCheckCount(passed);
+ }
+ return result;
+ }
+
+ /**
+ * Returns the index of the specified result.
+ *
+ * @param result the class result.
+ *
+ * @return The index.
+ */
+ public int indexOf(ClassResult result) {
+ sortClasses();
+ return classResults.indexOf(result);
+ }
+
+ public int compareTo(Object obj) {
+ PackageResult that = (PackageResult) obj;
+ return getName().compareTo(that.getName());
+ }
+
+ /**
+ * Sorts the class results.
+ */
+ private void sortClasses() {
+ if(sorted) return;
+ Collections.sort(classResults);
+ sorted = true;
+ }
+}
Added: trunk/core/src/test/org/jnode/test/mauve/RunResult.java
===================================================================
--- trunk/core/src/test/org/jnode/test/mauve/RunResult.java (rev 0)
+++ trunk/core/src/test/org/jnode/test/mauve/RunResult.java 2007-05-17 19:04:55 UTC (rev 3216)
@@ -0,0 +1,176 @@
+// Tags: not-a-test
+// Copyright (C) 2004 by Object Refinery Limited
+// Written by David Gilbert (dav...@ob...)
+
+// This file is part of Mauve Reporter.
+
+// Mauve Reporter is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+
+// Mauve Reporter is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Mauve Reporter; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+package org.jnode.test.mauve;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Represents the result of running a collection of Mauve tests.
+ */
+public class RunResult {
+
+ /** The name of the run. */
+ private String name;
+
+ /** A list containing results for each class in the package. */
+ private List packageResults;
+
+ /** A list containing unfound test-names */
+ private List missingTests = new ArrayList();
+ private List faultyTests = new ArrayList();
+ private boolean sorted=true;
+
+ /**
+ * Creates a new result, initially empty.
+ *
+ * @param name the class name.
+ */
+ RunResult(String name) {
+ this.name = name;
+ packageResults = new ArrayList();
+ }
+
+ /**
+ * Returns the run name.
+ *
+ * @return The run name.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Sets the run name.
+ *
+ * @param name the name.
+ */
+ void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Adds a package result.
+ *
+ * @param result the package result.
+ */
+ void add(PackageResult result) {
+ packageResults.add(result);
+ sorted =false;
+ }
+
+ /**
+ * Returns an iterator that provides access to the package results.
+ *
+ * @return An iterator.
+ */
+ public Iterator getPackageIterator() {
+ sortPackages();
+ return packageResults.iterator();
+ }
+
+ public Iterator getMissingTestsIterator() {
+ return missingTests.iterator();
+ }
+
+ public Iterator getFaultyTestsIterator() {
+ return faultyTests.iterator();
+ }
+
+ /**
+ * Returns the total number of checks performed for this run.
+ *
+ * @return The check count.
+ */
+ public int getCheckCount() {
+ int result = 0;
+ Iterator iterator = getPackageIterator();
+ while (iterator.hasNext()) {
+ PackageResult pr = (PackageResult) iterator.next();
+ result = result + pr.getCheckCount();
+ }
+ return result;
+ }
+
+ /**
+ * Returns the number of checks with the specified status.
+ *
+ * @param passed the check status.
+ *
+ * @return The number of checks passed or failed.
+ */
+ public int getCheckCount(boolean passed) {
+ int result = 0;
+ Iterator iterator = getPackageIterator();
+ while (iterator.hasNext()) {
+ PackageResult pr = (PackageResult) iterator.next();
+ result = result + pr.getCheckCount(passed);
+ }
+ return result;
+ }
+
+ /**
+ * Returns the index of the specified result, or -1.
+ *
+ * @param pr the package result.
+ *
+ * @return The index.
+ */
+ public int indexOf(PackageResult pr) {
+ sortPackages();
+ return packageResults.indexOf(pr);
+ }
+
+ /**
+ * Returns the package result with the specified name.
+ *
+ * @param name the package name.
+ *
+ * @return The package result, or null when not found.
+ */
+ public PackageResult getPackageResult(String name) {
+ sortPackages();
+ for (int i = 0; i < packageResults.size(); i++) {
+ PackageResult rr = (PackageResult) packageResults.get(i);
+ if (rr.getName().equals(name))
+ return rr;
+ }
+ return null;
+ }
+
+ void addMissingTest(String line) {
+ missingTests.add(line);
+ }
+
+ void addFaultyTest(String line, String failure) {
+ faultyTests.add(new String[] {line, failure});
+ }
+
+ /**
+ * Sorts the package results.
+ */
+ private void sortPackages() {
+ if(sorted) return;
+ Collections.sort(packageResults);
+ sorted = true;
+ }
+}
Added: trunk/core/src/test/org/jnode/test/mauve/TestResult.java
===================================================================
--- trunk/core/src/test/org/jnode/test/mauve/TestResult.java (rev 0)
+++ trunk/core/src/test/org/jnode/test/mauve/TestResult.java 2007-05-17 19:04:55 UTC (rev 3216)
@@ -0,0 +1,139 @@
+// Tags: not-a-test
+// Copyright (C) 2004 by Object Refinery Limited
+// Written by David Gilbert (dav...@ob...)
+
+// This file is part of Mauve Reporter.
+
+// Mauve Reporter is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+
+// Mauve Reporter is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Mauve Reporter; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+package org.jnode.test.mauve;
+
+import java.util.*;
+import java.io.*;
+
+/**
+ * Represents the result of running one test. A test usually contains multiple
+ * checks and corresponds to a single method in the API being tested. There
+ * are exceptions of course.
+ */
+public class TestResult implements Comparable {
+
+ /** The name of the test (usually the method name). */
+ private String name;
+
+ /** A list containing results for each of the checks applied by the test. */
+ private List checkResults;
+
+ private String error = null;
+
+ /**
+ * Creates a new result, initially empty.
+ * @param name
+ */
+ TestResult(String name) {
+ this.name = name;
+ checkResults = new ArrayList();
+ }
+
+ /**
+ * Returns the test name (this is most often the name of the method
+ * being tested).
+ *
+ * @return The test name.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Sets the test name.
+ *
+ * @param name the name.
+ */
+ void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Adds a check result.
+ *
+ * @param result the check result.
+ */
+ void add(CheckResult result) {
+ checkResults.add(result);
+ }
+
+ /**
+ * Returns an iterator that provides access to all the check results.
+ *
+ * @return An iterator.
+ */
+ public Iterator getCheckIterator() {
+ return checkResults.iterator();
+ }
+
+ /**
+ * Returns the total number of checks performed by this test.
+ *
+ * @return The check count.
+ */
+ public int getCheckCount() {
+ return checkResults.size();
+ }
+
+ /**
+ * Returns the number of checks with the specified status.
+ *
+ * @param passed the check status.
+ *
+ * @return The number of checks passed or failed.
+ */
+ public int getCheckCount(boolean passed) {
+ int result = 0;
+ Iterator iterator = checkResults.iterator();
+ while (iterator.hasNext()) {
+ CheckResult check = (CheckResult) iterator.next();
+ if (check.getPassed() == passed)
+ result++;
+ }
+ if(!passed && error != null)
+ result++; // count stacktrace as a failure
+ return result;
+ }
+
+ public int compareTo(Object obj) {
+ TestResult that = (TestResult) obj;
+ return getName().compareTo(that.getName());
+ }
+
+ void failed(Throwable t) {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ PrintWriter w = new PrintWriter(out, false);
+ t.printStackTrace(w);
+ w.c...
[truncated message content] |
|
From: <ls...@us...> - 2007-05-17 18:34:47
|
Revision: 3215
http://jnode.svn.sourceforge.net/jnode/?rev=3215&view=rev
Author: lsantha
Date: 2007-05-17 11:34:44 -0700 (Thu, 17 May 2007)
Log Message:
-----------
Fixed misplaced directory.
Added Paths:
-----------
trunk/core/src/openjdk/java/java/util/
trunk/core/src/openjdk/java/java/util/regex/
trunk/core/src/openjdk/java/java/util/regex/ASCII.java
trunk/core/src/openjdk/java/java/util/regex/MatchResult.java
trunk/core/src/openjdk/java/java/util/regex/Matcher.java
trunk/core/src/openjdk/java/java/util/regex/Pattern.java
trunk/core/src/openjdk/java/java/util/regex/PatternSyntaxException.java
trunk/core/src/openjdk/java/java/util/regex/package.html
Removed Paths:
-------------
trunk/core/src/openjdk/java/util/
Copied: trunk/core/src/openjdk/java/java/util/regex/ASCII.java (from rev 3211, trunk/core/src/openjdk/java/util/regex/ASCII.java)
===================================================================
--- trunk/core/src/openjdk/java/java/util/regex/ASCII.java (rev 0)
+++ trunk/core/src/openjdk/java/java/util/regex/ASCII.java 2007-05-17 18:34:44 UTC (rev 3215)
@@ -0,0 +1,274 @@
+/*
+ * Copyright 1999-2000 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package java.util.regex;
+
+
+/**
+ * Utility class that implements the standard C ctype functionality.
+ *
+ * @author Hong Zhang
+ */
+
+final class ASCII {
+
+ static final int UPPER = 0x00000100;
+
+ static final int LOWER = 0x00000200;
+
+ static final int DIGIT = 0x00000400;
+
+ static final int SPACE = 0x00000800;
+
+ static final int PUNCT = 0x00001000;
+
+ static final int CNTRL = 0x00002000;
+
+ static final int BLANK = 0x00004000;
+
+ static final int HEX = 0x00008000;
+
+ static final int UNDER = 0x00010000;
+
+ static final int ASCII = 0x0000FF00;
+
+ static final int ALPHA = (UPPER|LOWER);
+
+ static final int ALNUM = (UPPER|LOWER|DIGIT);
+
+ static final int GRAPH = (PUNCT|UPPER|LOWER|DIGIT);
+
+ static final int WORD = (UPPER|LOWER|UNDER|DIGIT);
+
+ static final int XDIGIT = (HEX);
+
+ private static final int[] ctype = new int[] {
+ CNTRL, /* 00 (NUL) */
+ CNTRL, /* 01 (SOH) */
+ CNTRL, /* 02 (STX) */
+ CNTRL, /* 03 (ETX) */
+ CNTRL, /* 04 (EOT) */
+ CNTRL, /* 05 (ENQ) */
+ CNTRL, /* 06 (ACK) */
+ CNTRL, /* 07 (BEL) */
+ CNTRL, /* 08 (BS) */
+ SPACE+CNTRL+BLANK, /* 09 (HT) */
+ SPACE+CNTRL, /* 0A (LF) */
+ SPACE+CNTRL, /* 0B (VT) */
+ SPACE+CNTRL, /* 0C (FF) */
+ SPACE+CNTRL, /* 0D (CR) */
+ CNTRL, /* 0E (SI) */
+ CNTRL, /* 0F (SO) */
+ CNTRL, /* 10 (DLE) */
+ CNTRL, /* 11 (DC1) */
+ CNTRL, /* 12 (DC2) */
+ CNTRL, /* 13 (DC3) */
+ CNTRL, /* 14 (DC4) */
+ CNTRL, /* 15 (NAK) */
+ CNTRL, /* 16 (SYN) */
+ CNTRL, /* 17 (ETB) */
+ CNTRL, /* 18 (CAN) */
+ CNTRL, /* 19 (EM) */
+ CNTRL, /* 1A (SUB) */
+ CNTRL, /* 1B (ESC) */
+ CNTRL, /* 1C (FS) */
+ CNTRL, /* 1D (GS) */
+ CNTRL, /* 1E (RS) */
+ CNTRL, /* 1F (US) */
+ SPACE+BLANK, /* 20 SPACE */
+ PUNCT, /* 21 ! */
+ PUNCT, /* 22 " */
+ PUNCT, /* 23 # */
+ PUNCT, /* 24 $ */
+ PUNCT, /* 25 % */
+ PUNCT, /* 26 & */
+ PUNCT, /* 27 ' */
+ PUNCT, /* 28 ( */
+ PUNCT, /* 29 ) */
+ PUNCT, /* 2A * */
+ PUNCT, /* 2B + */
+ PUNCT, /* 2C , */
+ PUNCT, /* 2D - */
+ PUNCT, /* 2E . */
+ PUNCT, /* 2F / */
+ DIGIT+HEX+0, /* 30 0 */
+ DIGIT+HEX+1, /* 31 1 */
+ DIGIT+HEX+2, /* 32 2 */
+ DIGIT+HEX+3, /* 33 3 */
+ DIGIT+HEX+4, /* 34 4 */
+ DIGIT+HEX+5, /* 35 5 */
+ DIGIT+HEX+6, /* 36 6 */
+ DIGIT+HEX+7, /* 37 7 */
+ DIGIT+HEX+8, /* 38 8 */
+ DIGIT+HEX+9, /* 39 9 */
+ PUNCT, /* 3A : */
+ PUNCT, /* 3B ; */
+ PUNCT, /* 3C < */
+ PUNCT, /* 3D = */
+ PUNCT, /* 3E > */
+ PUNCT, /* 3F ? */
+ PUNCT, /* 40 @ */
+ UPPER+HEX+10, /* 41 A */
+ UPPER+HEX+11, /* 42 B */
+ UPPER+HEX+12, /* 43 C */
+ UPPER+HEX+13, /* 44 D */
+ UPPER+HEX+14, /* 45 E */
+ UPPER+HEX+15, /* 46 F */
+ UPPER+16, /* 47 G */
+ UPPER+17, /* 48 H */
+ UPPER+18, /* 49 I */
+ UPPER+19, /* 4A J */
+ UPPER+20, /* 4B K */
+ UPPER+21, /* 4C L */
+ UPPER+22, /* 4D M */
+ UPPER+23, /* 4E N */
+ UPPER+24, /* 4F O */
+ UPPER+25, /* 50 P */
+ UPPER+26, /* 51 Q */
+ UPPER+27, /* 52 R */
+ UPPER+28, /* 53 S */
+ UPPER+29, /* 54 T */
+ UPPER+30, /* 55 U */
+ UPPER+31, /* 56 V */
+ UPPER+32, /* 57 W */
+ UPPER+33, /* 58 X */
+ UPPER+34, /* 59 Y */
+ UPPER+35, /* 5A Z */
+ PUNCT, /* 5B [ */
+ PUNCT, /* 5C \ */
+ PUNCT, /* 5D ] */
+ PUNCT, /* 5E ^ */
+ PUNCT|UNDER, /* 5F _ */
+ PUNCT, /* 60 ` */
+ LOWER+HEX+10, /* 61 a */
+ LOWER+HEX+11, /* 62 b */
+ LOWER+HEX+12, /* 63 c */
+ LOWER+HEX+13, /* 64 d */
+ LOWER+HEX+14, /* 65 e */
+ LOWER+HEX+15, /* 66 f */
+ LOWER+16, /* 67 g */
+ LOWER+17, /* 68 h */
+ LOWER+18, /* 69 i */
+ LOWER+19, /* 6A j */
+ LOWER+20, /* 6B k */
+ LOWER+21, /* 6C l */
+ LOWER+22, /* 6D m */
+ LOWER+23, /* 6E n */
+ LOWER+24, /* 6F o */
+ LOWER+25, /* 70 p */
+ LOWER+26, /* 71 q */
+ LOWER+27, /* 72 r */
+ LOWER+28, /* 73 s */
+ LOWER+29, /* 74 t */
+ LOWER+30, /* 75 u */
+ LOWER+31, /* 76 v */
+ LOWER+32, /* 77 w */
+ LOWER+33, /* 78 x */
+ LOWER+34, /* 79 y */
+ LOWER+35, /* 7A z */
+ PUNCT, /* 7B { */
+ PUNCT, /* 7C | */
+ PUNCT, /* 7D } */
+ PUNCT, /* 7E ~ */
+ CNTRL, /* 7F (DEL) */
+ };
+
+ static int getType(int ch) {
+ return ((ch & 0xFFFFFF80) == 0 ? ctype[ch] : 0);
+ }
+
+ static boolean isType(int ch, int type) {
+ return (getType(ch) & type) != 0;
+ }
+
+ static boolean isAscii(int ch) {
+ return ((ch & 0xFFFFFF80) == 0);
+ }
+
+ static boolean isAlpha(int ch) {
+ return isType(ch, ALPHA);
+ }
+
+ static boolean isDigit(int ch) {
+ return ((ch-'0')|('9'-ch)) >= 0;
+ }
+
+ static boolean isAlnum(int ch) {
+ return isType(ch, ALNUM);
+ }
+
+ static boolean isGraph(int ch) {
+ return isType(ch, GRAPH);
+ }
+
+ static boolean isPrint(int ch) {
+ return ((ch-0x20)|(0x7E-ch)) >= 0;
+ }
+
+ static boolean isPunct(int ch) {
+ return isType(ch, PUNCT);
+ }
+
+ static boolean isSpace(int ch) {
+ return isType(ch, SPACE);
+ }
+
+ static boolean isHexDigit(int ch) {
+ return isType(ch, HEX);
+ }
+
+ static boolean isOctDigit(int ch) {
+ return ((ch-'0')|('7'-ch)) >= 0;
+ }
+
+ static boolean isCntrl(int ch) {
+ return isType(ch, CNTRL);
+ }
+
+ static boolean isLower(int ch) {
+ return ((ch-'a')|('z'-ch)) >= 0;
+ }
+
+ static boolean isUpper(int ch) {
+ return ((ch-'A')|('Z'-ch)) >= 0;
+ }
+
+ static boolean isWord(int ch) {
+ return isType(ch, WORD);
+ }
+
+ static int toDigit(int ch) {
+ return (ctype[ch & 0x7F] & 0x3F);
+ }
+
+ static int toLower(int ch) {
+ return isUpper(ch) ? (ch + 0x20) : ch;
+ }
+
+ static int toUpper(int ch) {
+ return isLower(ch) ? (ch - 0x20) : ch;
+ }
+
+}
Copied: trunk/core/src/openjdk/java/java/util/regex/MatchResult.java (from rev 3211, trunk/core/src/openjdk/java/util/regex/MatchResult.java)
===================================================================
--- trunk/core/src/openjdk/java/java/util/regex/MatchResult.java (rev 0)
+++ trunk/core/src/openjdk/java/java/util/regex/MatchResult.java 2007-05-17 18:34:44 UTC (rev 3215)
@@ -0,0 +1,189 @@
+/*
+ * Copyright 2003-2004 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package java.util.regex;
+
+/**
+ * The result of a match operation.
+ *
+ * <p>This interface contains query methods used to determine the
+ * results of a match against a regular expression. The match boundaries,
+ * groups and group boundaries can be seen but not modified through
+ * a <code>MatchResult</code>.
+ *
+ * @author Michael McCloskey
+ * @version 1.12 05/05/07
+ * @see Matcher
+ * @since 1.5
+ */
+public interface MatchResult {
+
+ /**
+ * Returns the start index of the match.
+ *
+ * @return The index of the first character matched
+ *
+ * @throws IllegalStateException
+ * If no match has yet been attempted,
+ * or if the previous match operation failed
+ */
+ public int start();
+
+ /**
+ * Returns the start index of the subsequence captured by the given group
+ * during this match.
+ *
+ * <p> <a href="Pattern.html#cg">Capturing groups</a> are indexed from left
+ * to right, starting at one. Group zero denotes the entire pattern, so
+ * the expression <i>m.</i><tt>start(0)</tt> is equivalent to
+ * <i>m.</i><tt>start()</tt>. </p>
+ *
+ * @param group
+ * The index of a capturing group in this matcher's pattern
+ *
+ * @return The index of the first character captured by the group,
+ * or <tt>-1</tt> if the match was successful but the group
+ * itself did not match anything
+ *
+ * @throws IllegalStateException
+ * If no match has yet been attempted,
+ * or if the previous match operation failed
+ *
+ * @throws IndexOutOfBoundsException
+ * If there is no capturing group in the pattern
+ * with the given index
+ */
+ public int start(int group);
+
+ /**
+ * Returns the offset after the last character matched. </p>
+ *
+ * @return @return The offset after the last character matched
+ *
+ * @throws IllegalStateException
+ * If no match has yet been attempted,
+ * or if the previous match operation failed
+ */
+ public int end();
+
+ /**
+ * Returns the offset after the last character of the subsequence
+ * captured by the given group during this match.
+ *
+ * <p> <a href="Pattern.html#cg">Capturing groups</a> are indexed from left
+ * to right, starting at one. Group zero denotes the entire pattern, so
+ * the expression <i>m.</i><tt>end(0)</tt> is equivalent to
+ * <i>m.</i><tt>end()</tt>. </p>
+ *
+ * @param group
+ * The index of a capturing group in this matcher's pattern
+ *
+ * @return The offset after the last character captured by the group,
+ * or <tt>-1</tt> if the match was successful
+ * but the group itself did not match anything
+ *
+ * @throws IllegalStateException
+ * If no match has yet been attempted,
+ * or if the previous match operation failed
+ *
+ * @throws IndexOutOfBoundsException
+ * If there is no capturing group in the pattern
+ * with the given index
+ */
+ public int end(int group);
+
+ /**
+ * Returns the input subsequence matched by the previous match.
+ *
+ * <p> For a matcher <i>m</i> with input sequence <i>s</i>,
+ * the expressions <i>m.</i><tt>group()</tt> and
+ * <i>s.</i><tt>substring(</tt><i>m.</i><tt>start(),</tt> <i>m.</i><tt>end())</tt>
+ * are equivalent. </p>
+ *
+ * <p> Note that some patterns, for example <tt>a*</tt>, match the empty
+ * string. This method will return the empty string when the pattern
+ * successfully matches the empty string in the input. </p>
+ *
+ * @return The (possibly empty) subsequence matched by the previous match,
+ * in string form
+ *
+ * @throws IllegalStateException
+ * If no match has yet been attempted,
+ * or if the previous match operation failed
+ */
+ public String group();
+
+ /**
+ * Returns the input subsequence captured by the given group during the
+ * previous match operation.
+ *
+ * <p> For a matcher <i>m</i>, input sequence <i>s</i>, and group index
+ * <i>g</i>, the expressions <i>m.</i><tt>group(</tt><i>g</i><tt>)</tt> and
+ * <i>s.</i><tt>substring(</tt><i>m.</i><tt>start(</tt><i>g</i><tt>),</tt> <i>m.</i><tt>end(</tt><i>g</i><tt>))</tt>
+ * are equivalent. </p>
+ *
+ * <p> <a href="Pattern.html#cg">Capturing groups</a> are indexed from left
+ * to right, starting at one. Group zero denotes the entire pattern, so
+ * the expression <tt>m.group(0)</tt> is equivalent to <tt>m.group()</tt>.
+ * </p>
+ *
+ * <p> If the match was successful but the group specified failed to match
+ * any part of the input sequence, then <tt>null</tt> is returned. Note
+ * that some groups, for example <tt>(a*)</tt>, match the empty string.
+ * This method will return the empty string when such a group successfully
+ * matches the empty string in the input. </p>
+ *
+ * @param group
+ * The index of a capturing group in this matcher's pattern
+ *
+ * @return The (possibly empty) subsequence captured by the group
+ * during the previous match, or <tt>null</tt> if the group
+ * failed to match part of the input
+ *
+ * @throws IllegalStateException
+ * If no match has yet been attempted,
+ * or if the previous match operation failed
+ *
+ * @throws IndexOutOfBoundsException
+ * If there is no capturing group in the pattern
+ * with the given index
+ */
+ public String group(int group);
+
+ /**
+ * Returns the number of capturing groups in this match result's pattern.
+ *
+ * <p> Group zero denotes the entire pattern by convention. It is not
+ * included in this count.
+ *
+ * <p> Any non-negative integer smaller than or equal to the value
+ * returned by this method is guaranteed to be a valid group index for
+ * this matcher. </p>
+ *
+ * @return The number of capturing groups in this matcher's pattern
+ */
+ public int groupCount();
+
+}
Copied: trunk/core/src/openjdk/java/java/util/regex/Matcher.java (from rev 3211, trunk/core/src/openjdk/java/util/regex/Matcher.java)
===================================================================
--- trunk/core/src/openjdk/java/java/util/regex/Matcher.java (rev 0)
+++ trunk/core/src/openjdk/java/java/util/regex/Matcher.java 2007-05-17 18:34:44 UTC (rev 3215)
@@ -0,0 +1,1175 @@
+/*
+ * Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package java.util.regex;
+
+
+/**
+ * An engine that performs match operations on a {@link java.lang.CharSequence
+ * </code>character sequence<code>} by interpreting a {@link Pattern}.
+ *
+ * <p> A matcher is created from a pattern by invoking the pattern's {@link
+ * Pattern#matcher matcher} method. Once created, a matcher can be used to
+ * perform three different kinds of match operations:
+ *
+ * <ul>
+ *
+ * <li><p> The {@link #matches matches} method attempts to match the entire
+ * input sequence against the pattern. </p></li>
+ *
+ * <li><p> The {@link #lookingAt lookingAt} method attempts to match the
+ * input sequence, starting at the beginning, against the pattern. </p></li>
+ *
+ * <li><p> The {@link #find find} method scans the input sequence looking for
+ * the next subsequence that matches the pattern. </p></li>
+ *
+ * </ul>
+ *
+ * <p> Each of these methods returns a boolean indicating success or failure.
+ * More information about a successful match can be obtained by querying the
+ * state of the matcher.
+ *
+ * <p> A matcher finds matches in a subset of its input called the
+ * <i>region</i>. By default, the region contains all of the matcher's input.
+ * The region can be modified via the{@link #region region} method and queried
+ * via the {@link #regionStart regionStart} and {@link #regionEnd regionEnd}
+ * methods. The way that the region boundaries interact with some pattern
+ * constructs can be changed. See {@link #useAnchoringBounds
+ * useAnchoringBounds} and {@link #useTransparentBounds useTransparentBounds}
+ * for more details.
+ *
+ * <p> This class also defines methods for replacing matched subsequences with
+ * new strings whose contents can, if desired, be computed from the match
+ * result. The {@link #appendReplacement appendReplacement} and {@link
+ * #appendTail appendTail} methods can be used in tandem in order to collect
+ * the result into an existing string buffer, or the more convenient {@link
+ * #replaceAll replaceAll} method can be used to create a string in which every
+ * matching subsequence in the input sequence is replaced.
+ *
+ * <p> The explicit state of a matcher includes the start and end indices of
+ * the most recent successful match. It also includes the start and end
+ * indices of the input subsequence captured by each <a
+ * href="Pattern.html#cg">capturing group</a> in the pattern as well as a total
+ * count of such subsequences. As a convenience, methods are also provided for
+ * returning these captured subsequences in string form.
+ *
+ * <p> The explicit state of a matcher is initially undefined; attempting to
+ * query any part of it before a successful match will cause an {@link
+ * IllegalStateException} to be thrown. The explicit state of a matcher is
+ * recomputed by every match operation.
+ *
+ * <p> The implicit state of a matcher includes the input character sequence as
+ * well as the <i>append position</i>, which is initially zero and is updated
+ * by the {@link #appendReplacement appendReplacement} method.
+ *
+ * <p> A matcher may be reset explicitly by invoking its {@link #reset()}
+ * method or, if a new input sequence is desired, its {@link
+ * #reset(java.lang.CharSequence) reset(CharSequence)} method. Resetting a
+ * matcher discards its explicit state information and sets the append position
+ * to zero.
+ *
+ * <p> Instances of this class are not safe for use by multiple concurrent
+ * threads. </p>
+ *
+ *
+ * @author Mike McCloskey
+ * @author Mark Reinhold
+ * @author JSR-51 Expert Group
+ * @version 1.73, 07/05/05
+ * @since 1.4
+ * @spec JSR-51
+ */
+
+public final class Matcher implements MatchResult {
+
+ /**
+ * The Pattern object that created this Matcher.
+ */
+ Pattern parentPattern;
+
+ /**
+ * The storage used by groups. They may contain invalid values if
+ * a group was skipped during the matching.
+ */
+ int[] groups;
+
+ /**
+ * The range within the sequence that is to be matched. Anchors
+ * will match at these "hard" boundaries. Changing the region
+ * changes these values.
+ */
+ int from, to;
+
+ /**
+ * Lookbehind uses this value to ensure that the subexpression
+ * match ends at the point where the lookbehind was encountered.
+ */
+ int lookbehindTo;
+
+ /**
+ * The original string being matched.
+ */
+ CharSequence text;
+
+ /**
+ * Matcher state used by the last node. NOANCHOR is used when a
+ * match does not have to consume all of the input. ENDANCHOR is
+ * the mode used for matching all the input.
+ */
+ static final int ENDANCHOR = 1;
+ static final int NOANCHOR = 0;
+ int acceptMode = NOANCHOR;
+
+ /**
+ * The range of string that last matched the pattern. If the last
+ * match failed then first is -1; last initially holds 0 then it
+ * holds the index of the end of the last match (which is where the
+ * next search starts).
+ */
+ int first = -1, last = 0;
+
+ /**
+ * The end index of what matched in the last match operation.
+ */
+ int oldLast = -1;
+
+ /**
+ * The index of the last position appended in a substitution.
+ */
+ int lastAppendPosition = 0;
+
+ /**
+ * Storage used by nodes to tell what repetition they are on in
+ * a pattern, and where groups begin. The nodes themselves are stateless,
+ * so they rely on this field to hold state during a match.
+ */
+ int[] locals;
+
+ /**
+ * Boolean indicating whether or not more input could change
+ * the results of the last match.
+ *
+ * If hitEnd is true, and a match was found, then more input
+ * might cause a different match to be found.
+ * If hitEnd is true and a match was not found, then more
+ * input could cause a match to be found.
+ * If hitEnd is false and a match was found, then more input
+ * will not change the match.
+ * If hitEnd is false and a match was not found, then more
+ * input will not cause a match to be found.
+ */
+ boolean hitEnd;
+
+ /**
+ * Boolean indicating whether or not more input could change
+ * a positive match into a negative one.
+ *
+ * If requireEnd is true, and a match was found, then more
+ * input could cause the match to be lost.
+ * If requireEnd is false and a match was found, then more
+ * input might change the match but the match won't be lost.
+ * If a match was not found, then requireEnd has no meaning.
+ */
+ boolean requireEnd;
+
+ /**
+ * If transparentBounds is true then the boundaries of this
+ * matcher's region are transparent to lookahead, lookbehind,
+ * and boundary matching constructs that try to see beyond them.
+ */
+ boolean transparentBounds = false;
+
+ /**
+ * If anchoringBounds is true then the boundaries of this
+ * matcher's region match anchors such as ^ and $.
+ */
+ boolean anchoringBounds = true;
+
+ /**
+ * No default constructor.
+ */
+ Matcher() {
+ }
+
+ /**
+ * All matchers have the state used by Pattern during a match.
+ */
+ Matcher(Pattern parent, CharSequence text) {
+ this.parentPattern = parent;
+ this.text = text;
+
+ // Allocate state storage
+ int parentGroupCount = Math.max(parent.capturingGroupCount, 10);
+ groups = new int[parentGroupCount * 2];
+ locals = new int[parent.localCount];
+
+ // Put fields into initial states
+ reset();
+ }
+
+ /**
+ * Returns the pattern that is interpreted by this matcher.
+ *
+ * @return The pattern for which this matcher was created
+ */
+ public Pattern pattern() {
+ return parentPattern;
+ }
+
+ /**
+ * Returns the match state of this matcher as a {@link MatchResult}.
+ * The result is unaffected by subsequent operations performed upon this
+ * matcher.
+ *
+ * @return a <code>MatchResult</code> with the state of this matcher
+ * @since 1.5
+ */
+ public MatchResult toMatchResult() {
+ Matcher result = new Matcher(this.parentPattern, text.toString());
+ result.first = this.first;
+ result.last = this.last;
+ result.groups = (int[])(this.groups.clone());
+ return result;
+ }
+
+ /**
+ * Changes the <tt>Pattern</tt> that this <tt>Matcher</tt> uses to
+ * find matches with.
+ *
+ * <p> This method causes this matcher to lose information
+ * about the groups of the last match that occurred. The
+ * matcher's position in the input is maintained and its
+ * last append position is unaffected.</p>
+ *
+ * @param newPattern
+ * The new pattern used by this matcher
+ * @return This matcher
+ * @throws IllegalArgumentException
+ * If newPattern is <tt>null</tt>
+ * @since 1.5
+ */
+ public Matcher usePattern(Pattern newPattern) {
+ if (newPattern == null)
+ throw new IllegalArgumentException("Pattern cannot be null");
+ parentPattern = newPattern;
+
+ // Reallocate state storage
+ int parentGroupCount = Math.max(newPattern.capturingGroupCount, 10);
+ groups = new int[parentGroupCount * 2];
+ locals = new int[newPattern.localCount];
+ for (int i = 0; i < groups.length; i++)
+ groups[i] = -1;
+ for (int i = 0; i < locals.length; i++)
+ locals[i] = -1;
+ return this;
+ }
+
+ /**
+ * Resets this matcher.
+ *
+ * <p> Resetting a matcher discards all of its explicit state information
+ * and sets its append position to zero. The matcher's region is set to the
+ * default region, which is its entire character sequence. The anchoring
+ * and transparency of this matcher's region boundaries are unaffected.
+ *
+ * @return This matcher
+ */
+ public Matcher reset() {
+ first = -1;
+ last = 0;
+ oldLast = -1;
+ for(int i=0; i<groups.length; i++)
+ groups[i] = -1;
+ for(int i=0; i<locals.length; i++)
+ locals[i] = -1;
+ lastAppendPosition = 0;
+ from = 0;
+ to = getTextLength();
+ return this;
+ }
+
+ /**
+ * Resets this matcher with a new input sequence.
+ *
+ * <p> Resetting a matcher discards all of its explicit state information
+ * and sets its append position to zero. The matcher's region is set to
+ * the default region, which is its entire character sequence. The
+ * anchoring and transparency of this matcher's region boundaries are
+ * unaffected.
+ *
+ * @param input
+ * The new input character sequence
+ *
+ * @return This matcher
+ */
+ public Matcher reset(CharSequence input) {
+ text = input;
+ return reset();
+ }
+
+ /**
+ * Returns the start index of the previous match. </p>
+ *
+ * @return The index of the first character matched
+ *
+ * @throws IllegalStateException
+ * If no match has yet been attempted,
+ * or if the previous match operation failed
+ */
+ public int start() {
+ if (first < 0)
+ throw new IllegalStateException("No match available");
+ return first;
+ }
+
+ /**
+ * Returns the start index of the subsequence captured by the given group
+ * during the previous match operation.
+ *
+ * <p> <a href="Pattern.html#cg">Capturing groups</a> are indexed from left
+ * to right, starting at one. Group zero denotes the entire pattern, so
+ * the expression <i>m.</i><tt>start(0)</tt> is equivalent to
+ * <i>m.</i><tt>start()</tt>. </p>
+ *
+ * @param group
+ * The index of a capturing group in this matcher's pattern
+ *
+ * @return The index of the first character captured by the group,
+ * or <tt>-1</tt> if the match was successful but the group
+ * itself did not match anything
+ *
+ * @throws IllegalStateException
+ * If no match has yet been attempted,
+ * or if the previous match operation failed
+ *
+ * @throws IndexOutOfBoundsException
+ * If there is no capturing group in the pattern
+ * with the given index
+ */
+ public int start(int group) {
+ if (first < 0)
+ throw new IllegalStateException("No match available");
+ if (group > groupCount())
+ throw new IndexOutOfBoundsException("No group " + group);
+ return groups[group * 2];
+ }
+
+ /**
+ * Returns the offset after the last character matched. </p>
+ *
+ * @return The offset after the last character matched
+ *
+ * @throws IllegalStateException
+ * If no match has yet been attempted,
+ * or if the previous match operation failed
+ */
+ public int end() {
+ if (first < 0)
+ throw new IllegalStateException("No match available");
+ return last;
+ }
+
+ /**
+ * Returns the offset after the last character of the subsequence
+ * captured by the given group during the previous match operation.
+ *
+ * <p> <a href="Pattern.html#cg">Capturing groups</a> are indexed from left
+ * to right, starting at one. Group zero denotes the entire pattern, so
+ * the expression <i>m.</i><tt>end(0)</tt> is equivalent to
+ * <i>m.</i><tt>end()</tt>. </p>
+ *
+ * @param group
+ * The index of a capturing group in this matcher's pattern
+ *
+ * @return The offset after the last character captured by the group,
+ * or <tt>-1</tt> if the match was successful
+ * but the group itself did not match anything
+ *
+ * @throws IllegalStateException
+ * If no match has yet been attempted,
+ * or if the previous match operation failed
+ *
+ * @throws IndexOutOfBoundsException
+ * If there is no capturing group in the pattern
+ * with the given index
+ */
+ public int end(int group) {
+ if (first < 0)
+ throw new IllegalStateException("No match available");
+ if (group > groupCount())
+ throw new IndexOutOfBoundsException("No group " + group);
+ return groups[group * 2 + 1];
+ }
+
+ /**
+ * Returns the input subsequence matched by the previous match.
+ *
+ * <p> For a matcher <i>m</i> with input sequence <i>s</i>,
+ * the expressions <i>m.</i><tt>group()</tt> and
+ * <i>s.</i><tt>substring(</tt><i>m.</i><tt>start(),</tt> <i>m.</i><tt>end())</tt>
+ * are equivalent. </p>
+ *
+ * <p> Note that some patterns, for example <tt>a*</tt>, match the empty
+ * string. This method will return the empty string when the pattern
+ * successfully matches the empty string in the input. </p>
+ *
+ * @return The (possibly empty) subsequence matched by the previous match,
+ * in string form
+ *
+ * @throws IllegalStateException
+ * If no match has yet been attempted,
+ * or if the previous match operation failed
+ */
+ public String group() {
+ return group(0);
+ }
+
+ /**
+ * Returns the input subsequence captured by the given group during the
+ * previous match operation.
+ *
+ * <p> For a matcher <i>m</i>, input sequence <i>s</i>, and group index
+ * <i>g</i>, the expressions <i>m.</i><tt>group(</tt><i>g</i><tt>)</tt> and
+ * <i>s.</i><tt>substring(</tt><i>m.</i><tt>start(</tt><i>g</i><tt>),</tt> <i>m.</i><tt>end(</tt><i>g</i><tt>))</tt>
+ * are equivalent. </p>
+ *
+ * <p> <a href="Pattern.html#cg">Capturing groups</a> are indexed from left
+ * to right, starting at one. Group zero denotes the entire pattern, so
+ * the expression <tt>m.group(0)</tt> is equivalent to <tt>m.group()</tt>.
+ * </p>
+ *
+ * <p> If the match was successful but the group specified failed to match
+ * any part of the input sequence, then <tt>null</tt> is returned. Note
+ * that some groups, for example <tt>(a*)</tt>, match the empty string.
+ * This method will return the empty string when such a group successfully
+ * matches the empty string in the input. </p>
+ *
+ * @param group
+ * The index of a capturing group in this matcher's pattern
+ *
+ * @return The (possibly empty) subsequence captured by the group
+ * during the previous match, or <tt>null</tt> if the group
+ * failed to match part of the input
+ *
+ * @throws IllegalStateException
+ * If no match has yet been attempted,
+ * or if the previous match operation failed
+ *
+ * @throws IndexOutOfBoundsException
+ * If there is no capturing group in the pattern
+ * with the given index
+ */
+ public String group(int group) {
+ if (first < 0)
+ throw new IllegalStateException("No match found");
+ if (group < 0 || group > groupCount())
+ throw new IndexOutOfBoundsException("No group " + group);
+ if ((groups[group*2] == -1) || (groups[group*2+1] == -1))
+ return null;
+ return getSubSequence(groups[group * 2], groups[group * 2 + 1]).toString();
+ }
+
+ /**
+ * Returns the number of capturing groups in this matcher's pattern.
+ *
+ * <p> Group zero denotes the entire pattern by convention. It is not
+ * included in this count.
+ *
+ * <p> Any non-negative integer smaller than or equal to the value
+ * returned by this method is guaranteed to be a valid group index for
+ * this matcher. </p>
+ *
+ * @return The number of capturing groups in this matcher's pattern
+ */
+ public int groupCount() {
+ return parentPattern.capturingGroupCount - 1;
+ }
+
+ /**
+ * Attempts to match the entire region against the pattern.
+ *
+ * <p> If the match succeeds then more information can be obtained via the
+ * <tt>start</tt>, <tt>end</tt>, and <tt>group</tt> methods. </p>
+ *
+ * @return <tt>true</tt> if, and only if, the entire region sequence
+ * matches this matcher's pattern
+ */
+ public boolean matches() {
+ return match(from, ENDANCHOR);
+ }
+
+ /**
+ * Attempts to find the next subsequence of the input sequence that matches
+ * the pattern.
+ *
+ * <p> This method starts at the beginning of this matcher's region, or, if
+ * a previous invocation of the method was successful and the matcher has
+ * not since been reset, at the first character not matched by the previous
+ * match.
+ *
+ * <p> If the match succeeds then more information can be obtained via the
+ * <tt>start</tt>, <tt>end</tt>, and <tt>group</tt> methods. </p>
+ *
+ * @return <tt>true</tt> if, and only if, a subsequence of the input
+ * sequence matches this matcher's pattern
+ */
+ public boolean find() {
+ int nextSearchIndex = last;
+ if (nextSearchIndex == first)
+ nextSearchIndex++;
+
+ // If next search starts before region, start it at region
+ if (nextSearchIndex < from)
+ nextSearchIndex = from;
+
+ // If next search starts beyond region then it fails
+ if (nextSearchIndex > to) {
+ for (int i = 0; i < groups.length; i++)
+ groups[i] = -1;
+ return false;
+ }
+ return search(nextSearchIndex);
+ }
+
+ /**
+ * Resets this matcher and then attempts to find the next subsequence of
+ * the input sequence that matches the pattern, starting at the specified
+ * index.
+ *
+ * <p> If the match succeeds then more information can be obtained via the
+ * <tt>start</tt>, <tt>end</tt>, and <tt>group</tt> methods, and subsequent
+ * invocations of the {@link #find()} method will start at the first
+ * character not matched by this match. </p>
+ *
+ * @throws IndexOutOfBoundsException
+ * If start is less than zero or if start is greater than the
+ * length of the input sequence.
+ *
+ * @return <tt>true</tt> if, and only if, a subsequence of the input
+ * sequence starting at the given index matches this matcher's
+ * pattern
+ */
+ public boolean find(int start) {
+ int limit = getTextLength();
+ if ((start < 0) || (start > limit))
+ throw new IndexOutOfBoundsException("Illegal start index");
+ reset();
+ return search(start);
+ }
+
+ /**
+ * Attempts to match the input sequence, starting at the beginning of the
+ * region, against the pattern.
+ *
+ * <p> Like the {@link #matches matches} method, this method always starts
+ * at the beginning of the region; unlike that method, it does not
+ * require that the entire region be matched.
+ *
+ * <p> If the match succeeds then more information can be obtained via the
+ * <tt>start</tt>, <tt>end</tt>, and <tt>group</tt> methods. </p>
+ *
+ * @return <tt>true</tt> if, and only if, a prefix of the input
+ * sequence matches this matcher's pattern
+ */
+ public boolean lookingAt() {
+ return match(from, NOANCHOR);
+ }
+
+ /**
+ * Returns a literal replacement <code>String</code> for the specified
+ * <code>String</code>.
+ *
+ * This method produces a <code>String</code> that will work
+ * as a literal replacement <code>s</code> in the
+ * <code>appendReplacement</code> method of the {@link Matcher} class.
+ * The <code>String</code> produced will match the sequence of characters
+ * in <code>s</code> treated as a literal sequence. Slashes ('\') and
+ * dollar signs ('$') will be given no special meaning.
+ *
+ * @param s The string to be literalized
+ * @return A literal string replacement
+ * @since 1.5
+ */
+ public static String quoteReplacement(String s) {
+ if ((s.indexOf('\\') == -1) && (s.indexOf('$') == -1))
+ return s;
+ StringBuilder sb = new StringBuilder();
+ for (int i=0; i<s.length(); i++) {
+ char c = s.charAt(i);
+ if (c == '\\' || c == '$') {
+ sb.append('\\');
+ }
+ sb.append(c);
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Implements a non-terminal append-and-replace step.
+ *
+ * <p> This method performs the following actions: </p>
+ *
+ * <ol>
+ *
+ * <li><p> It reads characters from the input sequence, starting at the
+ * append position, and appends them to the given string buffer. It
+ * stops after reading the last character preceding the previous match,
+ * that is, the character at index {@link
+ * #start()} <tt>-</tt> <tt>1</tt>. </p></li>
+ *
+ * <li><p> It appends the given replacement string to the string buffer.
+ * </p></li>
+ *
+ * <li><p> It sets the append position of this matcher to the index of
+ * the last character matched, plus one, that is, to {@link #end()}.
+ * </p></li>
+ *
+ * </ol>
+ *
+ * <p> The replacement string may contain references to subsequences
+ * captured during the previous match: Each occurrence of
+ * <tt>$</tt><i>g</i><tt></tt> will be replaced by the result of
+ * evaluating {@link #group(int) group}<tt>(</tt><i>g</i><tt>)</tt>.
+ * The first number after the <tt>$</tt> is always treated as part of
+ * the group reference. Subsequent numbers are incorporated into g if
+ * they would form a legal group reference. Only the numerals '0'
+ * through '9' are considered as potential components of the group
+ * reference. If the second group matched the string <tt>"foo"</tt>, for
+ * example, then passing the replacement string <tt>"$2bar"</tt> would
+ * cause <tt>"foobar"</tt> to be appended to the string buffer. A dollar
+ * sign (<tt>$</tt>) may be included as a literal in the replacement
+ * string by preceding it with a backslash (<tt>\$</tt>).
+ *
+ * <p> Note that backslashes (<tt>\</tt>) and dollar signs (<tt>$</tt>) in
+ * the replacement string may cause the results to be different than if it
+ * were being treated as a literal replacement string. Dollar signs may be
+ * treated as references to captured subsequences as described above, and
+ * backslashes are used to escape literal characters in the replacement
+ * string.
+ *
+ * <p> This method is intended to be used in a loop together with the
+ * {@link #appendTail appendTail} and {@link #find find} methods. The
+ * following code, for example, writes <tt>one dog two dogs in the
+ * yard</tt> to the standard-output stream: </p>
+ *
+ * <blockquote><pre>
+ * Pattern p = Pattern.compile("cat");
+ * Matcher m = p.matcher("one cat two cats in the yard");
+ * StringBuffer sb = new StringBuffer();
+ * while (m.find()) {
+ * m.appendReplacement(sb, "dog");
+ * }
+ * m.appendTail(sb);
+ * System.out.println(sb.toString());</pre></blockquote>
+ *
+ * @param sb
+ * The target string buffer
+ *
+ * @param replacement
+ * The replacement string
+ *
+ * @return This matcher
+ *
+ * @throws IllegalStateException
+ * If no match has yet been attempted,
+ * or if the previous match operation failed
+ *
+ * @throws IndexOutOfBoundsException
+ * If the replacement string refers to a capturing group
+ * that does not exist in the pattern
+ */
+ public Matcher appendReplacement(StringBuffer sb, String replacement) {
+
+ // If no match, return error
+ if (first < 0)
+ throw new IllegalStateException("No match available");
+
+ // Process substitution string to replace group references with groups
+ int cursor = 0;
+ StringBuilder result = new StringBuilder();
+
+ while (cursor < replacement.length()) {
+ char nextChar = replacement.charAt(cursor);
+ if (nextChar == '\\') {
+ cursor++;
+ nextChar = replacement.charAt(cursor);
+ result.append(nextChar);
+ cursor++;
+ } else if (nextChar == '$') {
+ // Skip past $
+ cursor++;
+ // The first number is always a group
+ int refNum = (int)replacement.charAt(cursor) - '0';
+ if ((refNum < 0)||(refNum > 9))
+ throw new IllegalArgumentException(
+ "Illegal group reference");
+ cursor++;
+
+ // Capture the largest legal group string
+ boolean done = false;
+ while (!done) {
+ if (cursor >= replacement.length()) {
+ break;
+ }
+ int nextDigit = replacement.charAt(cursor) - '0';
+ if ((nextDigit < 0)||(nextDigit > 9)) { // not a number
+ break;
+ }
+ int newRefNum = (refNum * 10) + nextDigit;
+ if (groupCount() < newRefNum) {
+ done = true;
+ } else {
+ refNum = newRefNum;
+ cursor++;
+ }
+ }
+ // Append group
+ if (start(refNum) != -1 && end(refNum) != -1)
+ result.append(text, start(refNum), end(refNum));
+ } else {
+ result.append(nextChar);
+ cursor++;
+ }
+ }
+ // Append the intervening text
+ sb.append(text, lastAppendPosition, first);
+ // Append the match substitution
+ sb.append(result);
+
+ lastAppendPosition = last;
+ return this;
+ }
+
+ /**
+ * Implements a terminal append-and-replace step.
+ *
+ * <p> This method reads characters from the input sequence, starting at
+ * the append position, and appends them to the given string buffer. It is
+ * intended to be invoked after one or more invocations of the {@link
+ * #appendReplacement appendReplacement} method in order to copy the
+ * remainder of the input sequence. </p>
+ *
+ * @param sb
+ * The target string buffer
+ *
+ * @return The target string buffer
+ */
+ public StringBuffer appendTail(StringBuffer sb) {
+ sb.append(text, lastAppendPosition, getTextLength());
+ return sb;
+ }
+
+ /**
+ * Replaces every subsequence of the input sequence that matches the
+ * pattern with the given replacement string.
+ *
+ * <p> This method first resets this matcher. It then scans the input
+ * sequence looking for matches of the pattern. Characters that are not
+ * part of any match are appended directly to the result string; each match
+ * is replaced in the result by the replacement string. The replacement
+ * string may contain references to captured subsequences as in the {@link
+ * #appendReplacement appendReplacement} method.
+ *
+ * <p> Note that backslashes (<tt>\</tt>) and dollar signs (<tt>$</tt>) in
+ * the replacement string may cause the results to be different than if it
+ * were being treated as a literal replacement string. Dollar signs may be
+ * treated as references to captured subsequences as described above, and
+ * backslashes are used to escape literal characters in the replacement
+ * string.
+ *
+ * <p> Given the regular expression <tt>a*b</tt>, the input
+ * <tt>"aabfooaabfooabfoob"</tt>, and the replacement string
+ * <tt>"-"</tt>, an invocation of this method on a matcher for that
+ * expression would yield the string <tt>"-foo-foo-foo-"</tt>.
+ *
+ * <p> Invoking this method changes this matcher's state. If the matcher
+ * is to be used in further matching operations then it should first be
+ * reset. </p>
+ *
+ * @param replacement
+ * The replacement string
+ *
+ * @return The string constructed by replacing each matching subsequence
+ * by the replacement string, substituting captured subsequences
+ * as needed
+ */
+ public String replaceAll(String replacement) {
+ reset();
+ boolean result = find();
+ if (result) {
+ StringBuffer sb = new StringBuffer();
+ do {
+ appendReplacement(sb, replacement);
+ result = find();
+ } while (result);
+ appendTail(sb);
+ return sb.toString();
+ }
+ return text.toString();
+ }
+
+ /**
+ * Replaces the first subsequence of the input sequence that matches the
+ * pattern with the given replacement string.
+ *
+ * <p> This method first resets this matcher. It then scans the input
+ * sequence looking for a match of the pattern. Characters that are not
+ * part of the match are appended directly to the result string; the match
+ * is replaced in the result by the replacement string. The replacement
+ * string may contain references to captured subsequences as in the {@link
+ * #appendReplacement appendReplacement} method.
+ *
+ * <p>Note that backslashes (<tt>\</tt>) and dollar signs (<tt>$</tt>) in
+ * the replacement string may cause the results to be different than if it
+ * were being treated as a literal replacement string. Dollar signs may be
+ * treated as references to captured subsequences as described above, and
+ * backslashes are used to escape literal characters in the replacement
+ * string.
+ *
+ * <p> Given the regular expression <tt>dog</tt>, the input
+ * <tt>"zzzdogzzzdogzzz"</tt>, and the replacement string
+ * <tt>"cat"</tt>, an invocation of this method on a matcher for that
+ * expression would yield the string <tt>"zzzcatzzzdogzzz"</tt>. </p>
+ *
+ * <p> Invoking this method changes this matcher's state. If the matcher
+ * is to be used in further matching operations then it should first be
+ * reset. </p>
+ *
+ * @param replacement
+ * The replacement string
+ * @return The string constructed by replacing the first matching
+ * subsequence by the replacement string, substituting captured
+ * subsequences as needed
+ */
+ public String replaceFirst(String replacement) {
+ if (replacement == null)
+ throw new NullPointerException("replacement");
+ reset();
+ if (!find())
+ return text.toString();
+ StringBuffer sb = new StringBuffer();
+ appendReplacement(sb, replacement);
+ appendTail(sb);
+ return sb.toString();
+ }
+
+ /**
+ * Sets the limits of this matcher's region. The region is the part of the
+ * input sequence that will be searched to find a match. Invoking this
+ * method resets the matcher, and then sets the region to start at the
+ * index specified by the <code>start</code> parameter and end at the
+ * index specified by the <code>end</code> parameter.
+ *
+ * <p>Depending on the transparency and anchoring being used (see
+ * {@link #useTransparentBounds useTransparentBounds} and
+ * {@link #useAnchoringBounds useAnchoringBounds}), certain constructs such
+ * as anchors may behave differently at or around the boundaries of the
+ * region.
+ *
+ * @param start
+ * The index to start searching at (inclusive)
+ * @param end
+ * The index to end searching at (exclusive)
+ * @throws IndexOutOfBoundsException
+ * If start or end is less than zero, if
+ * start is greater than the length of the input sequence, if
+ * end is greater than the length of the input sequence, or if
+ * start is greater than end.
+ * @return this matcher
+ * @since 1.5
+ */
+ public Matcher region(int start, int end) {
+ if ((start < 0) || (start > getTextLength()))
+ throw new IndexOutOfBoundsException("start");
+ if ((end < 0) || (end > getTextLength()))
+ throw new IndexOutOfBoundsException("end");
+ if (start > end)
+ throw new IndexOutOfBoundsException("start > end");
+ reset();
+ from = start;
+ to = end;
+ return this;
+ }
+
+ /**
+ * Reports the start index of this matcher's region. The
+ * searches this matcher conducts are limited to finding matches
+ * within {@link #regionStart regionStart} (inclusive) and
+ * {@link #regionEnd regionEnd} (exclusive).
+ *
+ * @return The starting point of this matcher's region
+ * @since 1.5
+ */
+ public int regionStart() {
+ return from;
+ }
+
+ /**
+ * Reports the end index (exclusive) of this matcher's region.
+ * The searches this matcher conducts are limited to finding matches
+ * within {@link #regionStart regionStart} (inclusive) and
+ * {@link #regionEnd regionEnd} (exclusive).
+ *
+ * @return the ending point of this matcher's region
+ * @since 1.5
+ */
+ public int regionEnd() {
+ return to;
+ }
+
+ /**
+ * Queries the transparency of region bounds for this matcher.
+ *
+ * <p> This method returns <tt>true</tt> if this matcher uses
+ * <i>transparent</i> bounds, <tt>false</tt> if it uses <i>opaque</i>
+ * bounds.
+ *
+ * <p> See {@link #useTransparentBounds useTransparentBounds} for a
+ * description of transparent and opaque bounds.
+ *
+ * <p> By default, a matcher uses opaque region boundaries.
+ *
+ * @return <tt>true</tt> iff this matcher is using transparent bounds,
+ * <tt>false</tt> otherwise.
+ * @see java.util.regex.Matcher#useTransparentBounds(boolean)
+ * @since 1.5
+ */
+ public boolean hasTransparentBounds() {
+ return transparentBounds;
+ }
+
+ /**
+ * Sets the transparency of region bounds for this matcher.
+ *
+ * <p> Invoking this method with an argument of <tt>true</tt> will set this
+ * matcher to use <i>transparent</i> bounds. If the boolean
+ * argument is <tt>false</tt>, then <i>opaque</i> bounds will be used.
+ *
+ * <p> Using transparent bounds, the boundaries of this
+ * matcher's region are transparent to lookahead, lookbehind,
+ * and boundary matching constructs. Those constructs can see beyond the
+ * boundaries of the region to see if a match is appropriate.
+ *
+ * <p> Using opaque bounds, the boundaries of this matcher's
+ * region are opaque to lookahead, lookbehind, and boundary matching
+ * constructs that may try to see beyond them. Those constructs cannot
+ * look past the boundaries so they will fail to match anything outside
+ * of the region.
+ *
+ * <p> By default, a matcher uses opaque bounds.
+ *
+ * @param b a boolean indicating whether to use opaque or transparent
+ * regions
+ * @return this matcher
+ * @see java.util.regex.Matcher#hasTransparentBounds
+ * @since 1.5
+ */
+ public Matcher useTransparentBounds(boolean b) {
+ transparentBounds = b;
+ return this;
+ }
+
+ /**
+ * Queries the anchoring of region bounds for this matcher.
+ *
+ * <p> This method returns <tt>true</tt> if this matcher uses
+ * <i>anchoring</i> bounds, <tt>false</tt> otherwise.
+ *
+ * <p> See {@link #useAnchoringBounds useAnchoringBounds} for a
+ * description of anchoring bounds.
+ *
+ * <p> By default, a matcher uses anchoring region boundaries.
+ *
+ * @return <tt>true</tt> iff this matcher is using anchoring bounds,
+ * <tt>false</tt> otherwise.
+ * @see java.util.regex.Matcher#useAnchoringBounds(boolean)
+ * @since 1.5
+ */
+ public boolean hasAnchoringBounds() {
+ return anchoringBounds;
+ }
+
+ /**
+ * Sets the anchoring of region bounds for this matcher.
+ *
+ * <p> Invoking this method with an argument of <tt>true</tt> will set this
+ * matcher to use <i>anchoring</i> bounds. If the boolean
+ * argument is <tt>false</tt>, then <i>non-anchoring</i> bounds will be
+ * used.
+ *
+ * <p> Using anchoring bounds, the boundaries of this
+ * matcher's region match anchors such as ^ and $.
+ *
+ * <p> Without anchoring bounds, the boundaries of this
+ * matcher's region will not match anchors such as ^ and $.
+ *
+ * <p> By default, a matcher uses anchoring region boundaries.
+ *
+ * @param b a boolean indicating whether or not to use anchoring bounds.
+ * @return this matcher
+ * @see java.util.regex.Matcher#hasAnchoringBounds
+ * @since 1.5
+ */
+ public Matcher useAnchoringBounds(boolean b) {
+ anchoringBounds = b;
+ return this;
+ }
+
+ /**
+ * <p>Returns the string representation of this matcher. The
+ * string representation of a ...
[truncated message content] |
|
From: <ls...@us...> - 2007-05-17 17:13:15
|
Revision: 3214
http://jnode.svn.sourceforge.net/jnode/?rev=3214&view=rev
Author: lsantha
Date: 2007-05-17 10:13:14 -0700 (Thu, 17 May 2007)
Log Message:
-----------
Created openjdk speciffic vm source tree.
Modified Paths:
--------------
trunk/core/build.xml
Modified: trunk/core/build.xml
===================================================================
--- trunk/core/build.xml 2007-05-17 17:12:56 UTC (rev 3213)
+++ trunk/core/build.xml 2007-05-17 17:13:14 UTC (rev 3214)
@@ -29,6 +29,7 @@
<pathelement location="${my-src.dir}/openjdk/java"/>
<pathelement location="${my-src.dir}/openjdk/javax"/>
<pathelement location="${my-src.dir}/openjdk/sun"/>
+ <pathelement location="${my-src.dir}/openjdk/vm"/>
</path>
<path id="my-sources1">
<path refid="classpath-sources"/>
@@ -98,6 +99,7 @@
<fileset dir="${my-src.dir}/openjdk/java" includes="**/*.jav"/>
<fileset dir="${my-src.dir}/openjdk/javax" includes="**/*.jav"/>
<fileset dir="${my-src.dir}/openjdk/sun" includes="**/*.jav"/>
+ <fileset dir="${my-src.dir}/openjdk/vm" includes="**/*.jav"/>
</copy>
<ExpandTest classname="PrimitiveIntTest" type="int"/>
<ExpandTest classname="PrimitiveLongTest" type="long"/>
@@ -127,6 +129,7 @@
<fileset dir="${my-src.dir}/openjdk/java" excludes="${my-non-resources}"/>
<fileset dir="${my-src.dir}/openjdk/javax" excludes="${my-non-resources}"/>
<fileset dir="${my-src.dir}/openjdk/sun" excludes="${my-non-resources}"/>
+ <fileset dir="${my-src.dir}/openjdk/vm" excludes="${my-non-resources}"/>
<fileset dir="${my-src.dir}/core" excludes="${my-non-resources}"/>
<fileset dir="${my-src.dir}/nanoxml" excludes="${my-non-resources}"/>
<fileset dir="${my-src.dir}/vmmagic" excludes="${my-non-resources}"/>
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ls...@us...> - 2007-05-17 17:12:57
|
Revision: 3213
http://jnode.svn.sourceforge.net/jnode/?rev=3213&view=rev
Author: lsantha
Date: 2007-05-17 10:12:56 -0700 (Thu, 17 May 2007)
Log Message:
-----------
Created openjdk speciffic vm source tree.
Added Paths:
-----------
trunk/core/src/openjdk/vm/java/
trunk/core/src/openjdk/vm/java/lang/
trunk/core/src/openjdk/vm/java/lang/NativeDouble.java
trunk/core/src/openjdk/vm/java/lang/NativeFloat.java
Copied: trunk/core/src/openjdk/vm/java/lang/NativeDouble.java (from rev 3205, trunk/core/src/classpath/vm/java/lang/NativeDouble.java)
===================================================================
--- trunk/core/src/openjdk/vm/java/lang/NativeDouble.java (rev 0)
+++ trunk/core/src/openjdk/vm/java/lang/NativeDouble.java 2007-05-17 17:12:56 UTC (rev 3213)
@@ -0,0 +1,47 @@
+/*
+ * $Id$
+ */
+package java.lang;
+
+import org.jnode.vm.VmMagic;
+
+/**
+ * @author Levente S\xE1ntha
+ */
+class NativeDouble {
+ /**
+ * Convert the double to the IEEE 754 floating-point "double format" bit
+ * layout. Bit 63 (the most significant) is the sign bit, bits 62-52 (masked
+ * by 0x7ff0000000000000L) represent the exponent, and bits 51-0 (masked by
+ * 0x000fffffffffffffL) are the mantissa. This function leaves NaN alone,
+ * rather than collapsing to a canonical value. The result of this function
+ * can be used as the argument to <code>Double.longBitsToDouble(long)</code>
+ * to obtain the original <code>double</code> value.
+ *
+ * @param value
+ * the <code>double</code> to convert
+ * @return the bits of the <code>double</code>
+ * @see java.lang.Double#longBitsToDouble(long)
+ */
+ static long doubleToRawLongBits(double value) {
+ return VmMagic.doubleToRawLongBits(value);
+ }
+
+ /**
+ * Convert the argument in IEEE 754 floating-point "double format" bit
+ * layout to the corresponding float. Bit 63 (the most significant) is the
+ * sign bit, bits 62-52 (masked by 0x7ff0000000000000L) represent the
+ * exponent, and bits 51-0 (masked by 0x000fffffffffffffL) are the mantissa.
+ * This function leaves NaN alone, so that you can recover the bit pattern
+ * with <code>Double.doubleToRawLongBits(double)</code>.
+ *
+ * @param bits
+ * the bits to convert
+ * @return the <code>double</code> represented by the bits
+ * @see java.lang.Double#doubleToLongBits(double)
+ * @see #doubleToRawLongBits(double)
+ */
+ static double longBitsToDouble(long bits) {
+ return VmMagic.longBitsToDouble(bits);
+ }
+}
Copied: trunk/core/src/openjdk/vm/java/lang/NativeFloat.java (from rev 3205, trunk/core/src/classpath/vm/java/lang/NativeFloat.java)
===================================================================
--- trunk/core/src/openjdk/vm/java/lang/NativeFloat.java (rev 0)
+++ trunk/core/src/openjdk/vm/java/lang/NativeFloat.java 2007-05-17 17:12:56 UTC (rev 3213)
@@ -0,0 +1,47 @@
+/*
+ * $Id$
+ */
+package java.lang;
+
+import org.jnode.vm.VmMagic;
+
+/**
+ * @author Levente S\xE1ntha
+ */
+class NativeFloat {
+ /**
+ * Convert the float to the IEEE 754 floating-point "single format" bit
+ * layout. Bit 31 (the most significant) is the sign bit, bits 30-23 (masked
+ * by 0x7f800000) represent the exponent, and bits 22-0 (masked by
+ * 0x007fffff) are the mantissa. This function leaves NaN alone, rather than
+ * collapsing to a canonical value. The result of this function can be used
+ * as the argument to <code>Float.intBitsToFloat(int)</code> to obtain the
+ * original <code>float</code> value.
+ *
+ * @param value
+ * the <code>float</code> to convert
+ * @return the bits of the <code>float</code>
+ * @see #intBitsToFloat(int)
+ */
+ static int floatToRawIntBits(float value) {
+ return VmMagic.floatToRawIntBits(value);
+ }
+
+ /**
+ * Convert the argument in IEEE 754 floating-point "single format" bit
+ * layout to the corresponding float. Bit 31 (the most significant) is the
+ * sign bit, bits 30-23 (masked by 0x7f800000) represent the exponent, and
+ * bits 22-0 (masked by 0x007fffff) are the mantissa. This function leaves
+ * NaN alone, so that you can recover the bit pattern with
+ * <code>Float.floatToRawIntBits(float)</code>.
+ *
+ * @param bits
+ * the bits to convert
+ * @return the <code>float</code> represented by the bits
+ * @see java.lang.Float#floatToIntBits(float)
+ * @see #floatToRawIntBits(float)
+ */
+ static float intBitsToFloat(int bits) {
+ return VmMagic.intBitsToFloat(bits);
+ }
+}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ls...@us...> - 2007-05-17 17:12:28
|
Revision: 3212
http://jnode.svn.sourceforge.net/jnode/?rev=3212&view=rev
Author: lsantha
Date: 2007-05-17 10:12:27 -0700 (Thu, 17 May 2007)
Log Message:
-----------
Created openjdk speciffic vm source tree.
Removed Paths:
-------------
trunk/core/src/classpath/vm/java/lang/NativeDouble.java
trunk/core/src/classpath/vm/java/lang/NativeFloat.java
Deleted: trunk/core/src/classpath/vm/java/lang/NativeDouble.java
===================================================================
--- trunk/core/src/classpath/vm/java/lang/NativeDouble.java 2007-05-17 17:03:05 UTC (rev 3211)
+++ trunk/core/src/classpath/vm/java/lang/NativeDouble.java 2007-05-17 17:12:27 UTC (rev 3212)
@@ -1,47 +0,0 @@
-/*
- * $Id$
- */
-package java.lang;
-
-import org.jnode.vm.VmMagic;
-
-/**
- * @author Levente S\xE1ntha
- */
-class NativeDouble {
- /**
- * Convert the double to the IEEE 754 floating-point "double format" bit
- * layout. Bit 63 (the most significant) is the sign bit, bits 62-52 (masked
- * by 0x7ff0000000000000L) represent the exponent, and bits 51-0 (masked by
- * 0x000fffffffffffffL) are the mantissa. This function leaves NaN alone,
- * rather than collapsing to a canonical value. The result of this function
- * can be used as the argument to <code>Double.longBitsToDouble(long)</code>
- * to obtain the original <code>double</code> value.
- *
- * @param value
- * the <code>double</code> to convert
- * @return the bits of the <code>double</code>
- * @see java.lang.Double#longBitsToDouble(long)
- */
- static long doubleToRawLongBits(double value) {
- return VmMagic.doubleToRawLongBits(value);
- }
-
- /**
- * Convert the argument in IEEE 754 floating-point "double format" bit
- * layout to the corresponding float. Bit 63 (the most significant) is the
- * sign bit, bits 62-52 (masked by 0x7ff0000000000000L) represent the
- * exponent, and bits 51-0 (masked by 0x000fffffffffffffL) are the mantissa.
- * This function leaves NaN alone, so that you can recover the bit pattern
- * with <code>Double.doubleToRawLongBits(double)</code>.
- *
- * @param bits
- * the bits to convert
- * @return the <code>double</code> represented by the bits
- * @see java.lang.Double#doubleToLongBits(double)
- * @see #doubleToRawLongBits(double)
- */
- static double longBitsToDouble(long bits) {
- return VmMagic.longBitsToDouble(bits);
- }
-}
Deleted: trunk/core/src/classpath/vm/java/lang/NativeFloat.java
===================================================================
--- trunk/core/src/classpath/vm/java/lang/NativeFloat.java 2007-05-17 17:03:05 UTC (rev 3211)
+++ trunk/core/src/classpath/vm/java/lang/NativeFloat.java 2007-05-17 17:12:27 UTC (rev 3212)
@@ -1,47 +0,0 @@
-/*
- * $Id$
- */
-package java.lang;
-
-import org.jnode.vm.VmMagic;
-
-/**
- * @author Levente S\xE1ntha
- */
-class NativeFloat {
- /**
- * Convert the float to the IEEE 754 floating-point "single format" bit
- * layout. Bit 31 (the most significant) is the sign bit, bits 30-23 (masked
- * by 0x7f800000) represent the exponent, and bits 22-0 (masked by
- * 0x007fffff) are the mantissa. This function leaves NaN alone, rather than
- * collapsing to a canonical value. The result of this function can be used
- * as the argument to <code>Float.intBitsToFloat(int)</code> to obtain the
- * original <code>float</code> value.
- *
- * @param value
- * the <code>float</code> to convert
- * @return the bits of the <code>float</code>
- * @see #intBitsToFloat(int)
- */
- static int floatToRawIntBits(float value) {
- return VmMagic.floatToRawIntBits(value);
- }
-
- /**
- * Convert the argument in IEEE 754 floating-point "single format" bit
- * layout to the corresponding float. Bit 31 (the most significant) is the
- * sign bit, bits 30-23 (masked by 0x7f800000) represent the exponent, and
- * bits 22-0 (masked by 0x007fffff) are the mantissa. This function leaves
- * NaN alone, so that you can recover the bit pattern with
- * <code>Float.floatToRawIntBits(float)</code>.
- *
- * @param bits
- * the bits to convert
- * @return the <code>float</code> represented by the bits
- * @see java.lang.Float#floatToIntBits(float)
- * @see #floatToRawIntBits(float)
- */
- static float intBitsToFloat(int bits) {
- return VmMagic.intBitsToFloat(bits);
- }
-}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ls...@us...> - 2007-05-17 17:03:19
|
Revision: 3211
http://jnode.svn.sourceforge.net/jnode/?rev=3211&view=rev
Author: lsantha
Date: 2007-05-17 10:03:05 -0700 (Thu, 17 May 2007)
Log Message:
-----------
Openjdk patches.
Added Paths:
-----------
trunk/core/src/openjdk/java/util/
Copied: trunk/core/src/openjdk/java/util (from rev 3209, trunk/core/src/openjdk/java/ustil)
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ls...@us...> - 2007-05-17 17:02:12
|
Revision: 3210
http://jnode.svn.sourceforge.net/jnode/?rev=3210&view=rev
Author: lsantha
Date: 2007-05-17 10:02:11 -0700 (Thu, 17 May 2007)
Log Message:
-----------
Openjdk patches.
Removed Paths:
-------------
trunk/core/src/openjdk/java/ustil/
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ls...@us...> - 2007-05-17 16:57:13
|
Revision: 3209
http://jnode.svn.sourceforge.net/jnode/?rev=3209&view=rev
Author: lsantha
Date: 2007-05-17 09:57:10 -0700 (Thu, 17 May 2007)
Log Message:
-----------
Openjdk patches.
Removed Paths:
-------------
trunk/core/src/openjdk/java/java/ustil/
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ls...@us...> - 2007-05-17 16:56:21
|
Revision: 3208
http://jnode.svn.sourceforge.net/jnode/?rev=3208&view=rev
Author: lsantha
Date: 2007-05-17 09:56:12 -0700 (Thu, 17 May 2007)
Log Message:
-----------
Openjdk patches.
Added Paths:
-----------
trunk/core/src/openjdk/java/java/ustil/
trunk/core/src/openjdk/vm/
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kon...@us...> - 2007-05-17 16:29:43
|
Revision: 3207
http://jnode.svn.sourceforge.net/jnode/?rev=3207&view=rev
Author: konkubinaten
Date: 2007-05-17 09:29:33 -0700 (Thu, 17 May 2007)
Log Message:
-----------
removed old outdated branch that got merged back a long time ago.
Removed Paths:
-------------
branches/BlockDeviceAPI_with_ByteBuffer/
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ls...@us...> - 2007-05-16 20:04:38
|
Revision: 3206
http://jnode.svn.sourceforge.net/jnode/?rev=3206&view=rev
Author: lsantha
Date: 2007-05-16 13:04:35 -0700 (Wed, 16 May 2007)
Log Message:
-----------
Openjdk patches.
Added Paths:
-----------
trunk/core/src/openjdk/java/java/lang/Float.java
Added: trunk/core/src/openjdk/java/java/lang/Float.java
===================================================================
--- trunk/core/src/openjdk/java/java/lang/Float.java (rev 0)
+++ trunk/core/src/openjdk/java/java/lang/Float.java 2007-05-16 20:04:35 UTC (rev 3206)
@@ -0,0 +1,879 @@
+/*
+ * Copyright 1994-2006 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package java.lang;
+
+import sun.misc.FloatingDecimal;
+import sun.misc.FpUtils;
+import sun.misc.FloatConsts;
+import sun.misc.DoubleConsts;
+
+/**
+ * The {@code Float} class wraps a value of primitive type
+ * {@code float} in an object. An object of type
+ * {@code Float} contains a single field whose type is
+ * {@code float}.
+ *
+ * <p>In addition, this class provides several methods for converting a
+ * {@code float} to a {@code String} and a
+ * {@code String} to a {@code float}, as well as other
+ * constants and methods useful when dealing with a
+ * {@code float}.
+ *
+ * @author Lee Boynton
+ * @author Arthur van Hoff
+ * @author Joseph D. Darcy
+ * @version 1.108, 05/05/07
+ * @since JDK1.0
+ */
+public final class Float extends Number implements Comparable<Float> {
+ /**
+ * A constant holding the positive infinity of type
+ * {@code float}. It is equal to the value returned by
+ * {@code Float.intBitsToFloat(0x7f800000)}.
+ */
+ public static final float POSITIVE_INFINITY = 1.0f / 0.0f;
+
+ /**
+ * A constant holding the negative infinity of type
+ * {@code float}. It is equal to the value returned by
+ * {@code Float.intBitsToFloat(0xff800000)}.
+ */
+ public static final float NEGATIVE_INFINITY = -1.0f / 0.0f;
+
+ /**
+ * A constant holding a Not-a-Number (NaN) value of type
+ * {@code float}. It is equivalent to the value returned by
+ * {@code Float.intBitsToFloat(0x7fc00000)}.
+ */
+ public static final float NaN = 0.0f / 0.0f;
+
+ /**
+ * A constant holding the largest positive finite value of type
+ * {@code float}, (2-2<sup>-23</sup>)·2<sup>127</sup>.
+ * It is equal to the hexadecimal floating-point literal
+ * {@code 0x1.fffffeP+127f} and also equal to
+ * {@code Float.intBitsToFloat(0x7f7fffff)}.
+ */
+ public static final float MAX_VALUE = 0x1.fffffeP+127f; // 3.4028235e+38f
+
+ /**
+ * A constant holding the smallest positive normal value of type
+ * {@code float}, 2<sup>-126</sup>. It is equal to the
+ * hexadecimal floating-point literal {@code 0x1.0p-126f} and also
+ * equal to {@code Float.intBitsToFloat(0x00800000)}.
+ *
+ * @since 1.6
+ */
+ public static final float MIN_NORMAL = 0x1.0p-126f; // 1.17549435E-38f
+
+ /**
+ * A constant holding the smallest positive nonzero value of type
+ * {@code float}, 2<sup>-149</sup>. It is equal to the
+ * hexadecimal floating-point literal {@code 0x0.000002P-126f}
+ * and also equal to {@code Float.intBitsToFloat(0x1)}.
+ */
+ public static final float MIN_VALUE = 0x0.000002P-126f; // 1.4e-45f
+
+ /**
+ * Maximum exponent a finite {@code float} variable may have. It
+ * is equal to the value returned by {@code
+ * Math.getExponent(Float.MAX_VALUE)}.
+ *
+ * @since 1.6
+ */
+ public static final int MAX_EXPONENT = 127;
+
+ /**
+ * Minimum exponent a normalized {@code float} variable may have.
+ * It is equal to the value returned by {@code
+ * Math.getExponent(Float.MIN_NORMAL)}.
+ *
+ * @since 1.6
+ */
+ public static final int MIN_EXPONENT = -126;
+
+ /**
+ * The number of bits used to represent a {@code float} value.
+ *
+ * @since 1.5
+ */
+ public static final int SIZE = 32;
+
+ /**
+ * The {@code Class} instance representing the primitive type
+ * {@code float}.
+ *
+ * @since JDK1.1
+ */
+ public static final Class<Float> TYPE = Class.getPrimitiveClass("float");
+
+ /**
+ * Returns a string representation of the {@code float}
+ * argument. All characters mentioned below are ASCII characters.
+ * <ul>
+ * <li>If the argument is NaN, the result is the string
+ * "{@code NaN}".
+ * <li>Otherwise, the result is a string that represents the sign and
+ * magnitude (absolute value) of the argument. If the sign is
+ * negative, the first character of the result is
+ * '{@code -}' (<code>'\u002D'</code>); if the sign is
+ * positive, no sign character appears in the result. As for
+ * the magnitude <i>m</i>:
+ * <ul>
+ * <li>If <i>m</i> is infinity, it is represented by the characters
+ * {@code "Infinity"}; thus, positive infinity produces
+ * the result {@code "Infinity"} and negative infinity
+ * produces the result {@code "-Infinity"}.
+ * <li>If <i>m</i> is zero, it is represented by the characters
+ * {@code "0.0"}; thus, negative zero produces the result
+ * {@code "-0.0"} and positive zero produces the result
+ * {@code "0.0"}.
+ * <li> If <i>m</i> is greater than or equal to 10<sup>-3</sup> but
+ * less than 10<sup>7</sup>, then it is represented as the
+ * integer part of <i>m</i>, in decimal form with no leading
+ * zeroes, followed by '{@code .}'
+ * (<code>'\u002E'</code>), followed by one or more
+ * decimal digits representing the fractional part of
+ * <i>m</i>.
+ * <li> If <i>m</i> is less than 10<sup>-3</sup> or greater than or
+ * equal to 10<sup>7</sup>, then it is represented in
+ * so-called "computerized scientific notation." Let <i>n</i>
+ * be the unique integer such that 10<sup><i>n</i> </sup>≤
+ * <i>m</i> {@literal <} 10<sup><i>n</i>+1</sup>; then let <i>a</i>
+ * be the mathematically exact quotient of <i>m</i> and
+ * 10<sup><i>n</i></sup> so that 1 ≤ <i>a</i> {@literal <} 10.
+ * The magnitude is then represented as the integer part of
+ * <i>a</i>, as a single decimal digit, followed by
+ * '{@code .}' (<code>'\u002E'</code>), followed by
+ * decimal digits representing the fractional part of
+ * <i>a</i>, followed by the letter '{@code E}'
+ * (<code>'\u0045'</code>), followed by a representation
+ * of <i>n</i> as a decimal integer, as produced by the
+ * method {@link java.lang.Integer#toString(int)}.
+ *
+ * </ul>
+ * </ul>
+ * How many digits must be printed for the fractional part of
+ * <i>m</i> or <i>a</i>? There must be at least one digit
+ * to represent the fractional part, and beyond that as many, but
+ * only as many, more digits as are needed to uniquely distinguish
+ * the argument value from adjacent values of type
+ * {@code float}. That is, suppose that <i>x</i> is the
+ * exact mathematical value represented by the decimal
+ * representation produced by this method for a finite nonzero
+ * argument <i>f</i>. Then <i>f</i> must be the {@code float}
+ * value nearest to <i>x</i>; or, if two {@code float} values are
+ * equally close to <i>x</i>, then <i>f</i> must be one of
+ * them and the least significant bit of the significand of
+ * <i>f</i> must be {@code 0}.
+ *
+ * <p>To create localized string representations of a floating-point
+ * value, use subclasses of {@link java.text.NumberFormat}.
+ *
+ * @param f the float to be converted.
+ * @return a string representation of the argument.
+ */
+ public static String toString(float f) {
+ return new FloatingDecimal(f).toJavaFormatString();
+ }
+
+ /**
+ * Returns a hexadecimal string representation of the
+ * {@code float} argument. All characters mentioned below are
+ * ASCII characters.
+ *
+ * <ul>
+ * <li>If the argument is NaN, the result is the string
+ * "{@code NaN}".
+ * <li>Otherwise, the result is a string that represents the sign and
+ * magnitude (absolute value) of the argument. If the sign is negative,
+ * the first character of the result is '{@code -}'
+ * (<code>'\u002D'</code>); if the sign is positive, no sign character
+ * appears in the result. As for the magnitude <i>m</i>:
+ *
+ * <ul>
+ * <li>If <i>m</i> is infinity, it is represented by the string
+ * {@code "Infinity"}; thus, positive infinity produces the
+ * result {@code "Infinity"} and negative infinity produces
+ * the result {@code "-Infinity"}.
+ *
+ * <li>If <i>m</i> is zero, it is represented by the string
+ * {@code "0x0.0p0"}; thus, negative zero produces the result
+ * {@code "-0x0.0p0"} and positive zero produces the result
+ * {@code "0x0.0p0"}.
+ *
+ * <li>If <i>m</i> is a {@code float} value with a
+ * normalized representation, substrings are used to represent the
+ * significand and exponent fields. The significand is
+ * represented by the characters {@code "0x1."}
+ * followed by a lowercase hexadecimal representation of the rest
+ * of the significand as a fraction. Trailing zeros in the
+ * hexadecimal representation are removed unless all the digits
+ * are zero, in which case a single zero is used. Next, the
+ * exponent is represented by {@code "p"} followed
+ * by a decimal string of the unbiased exponent as if produced by
+ * a call to {@link Integer#toString(int) Integer.toString} on the
+ * exponent value.
+ *
+ * <li>If <i>m</i> is a {@code float} value with a subnormal
+ * representation, the significand is represented by the
+ * characters {@code "0x0."} followed by a
+ * hexadecimal representation of the rest of the significand as a
+ * fraction. Trailing zeros in the hexadecimal representation are
+ * removed. Next, the exponent is represented by
+ * {@code "p-126"}. Note that there must be at
+ * least one nonzero digit in a subnormal significand.
+ *
+ * </ul>
+ *
+ * </ul>
+ *
+ * <table border>
+ * <caption><h3>Examples</h3></caption>
+ * <tr><th>Floating-point Value</th><th>Hexadecimal String</th>
+ * <tr><td>{@code 1.0}</td> <td>{@code 0x1.0p0}</td>
+ * <tr><td>{@code -1.0}</td> <td>{@code -0x1.0p0}</td>
+ * <tr><td>{@code 2.0}</td> <td>{@code 0x1.0p1}</td>
+ * <tr><td>{@code 3.0}</td> <td>{@code 0x1.8p1}</td>
+ * <tr><td>{@code 0.5}</td> <td>{@code 0x1.0p-1}</td>
+ * <tr><td>{@code 0.25}</td> <td>{@code 0x1.0p-2}</td>
+ * <tr><td>{@code Float.MAX_VALUE}</td>
+ * <td>{@code 0x1.fffffep127}</td>
+ * <tr><td>{@code Minimum Normal Value}</td>
+ * <td>{@code 0x1.0p-126}</td>
+ * <tr><td>{@code Maximum Subnormal Value}</td>
+ * <td>{@code 0x0.fffffep-126}</td>
+ * <tr><td>{@code Float.MIN_VALUE}</td>
+ * <td>{@code 0x0.000002p-126}</td>
+ * </table>
+ * @param f the {@code float} to be converted.
+ * @return a hex string representation of the argument.
+ * @since 1.5
+ * @author Joseph D. Darcy
+ */
+ public static String toHexString(float f) {
+ if (Math.abs(f) < FloatConsts.MIN_NORMAL
+ && f != 0.0f ) {// float subnormal
+ // Adjust exponent to create subnormal double, then
+ // replace subnormal double exponent with subnormal float
+ // exponent
+ String s = Double.toHexString(FpUtils.scalb((double)f,
+ /* -1022+126 */
+ DoubleConsts.MIN_EXPONENT-
+ FloatConsts.MIN_EXPONENT));
+ return s.replaceFirst("p-1022$", "p-126");
+ }
+ else // double string will be the same as float string
+ return Double.toHexString(f);
+ }
+
+ /**
+ * Returns a {@code Float} object holding the
+ * {@code float} value represented by the argument string
+ * {@code s}.
+ *
+ * <p>If {@code s} is {@code null}, then a
+ * {@code NullPointerException} is thrown.
+ *
+ * <p>Leading and trailing whitespace characters in {@code s}
+ * are ignored. Whitespace is removed as if by the {@link
+ * String#trim} method; that is, both ASCII space and control
+ * characters are removed. The rest of {@code s} should
+ * constitute a <i>FloatValue</i> as described by the lexical
+ * syntax rules:
+ *
+ * <blockquote>
+ * <dl>
+ * <dt><i>FloatValue:</i>
+ * <dd><i>Sign<sub>opt</sub></i> {@code NaN}
+ * <dd><i>Sign<sub>opt</sub></i> {@code Infinity}
+ * <dd><i>Sign<sub>opt</sub> FloatingPointLiteral</i>
+ * <dd><i>Sign<sub>opt</sub> HexFloatingPointLiteral</i>
+ * <dd><i>SignedInteger</i>
+ * </dl>
+ *
+ * <p>
+ *
+ * <dl>
+ * <dt><i>HexFloatingPointLiteral</i>:
+ * <dd> <i>HexSignificand BinaryExponent FloatTypeSuffix<sub>opt</sub></i>
+ * </dl>
+ *
+ * <p>
+ *
+ * <dl>
+ * <dt><i>HexSignificand:</i>
+ * <dd><i>HexNumeral</i>
+ * <dd><i>HexNumeral</i> {@code .}
+ * <dd>{@code 0x} <i>HexDigits<sub>opt</sub>
+ * </i>{@code .}<i> HexDigits</i>
+ * <dd>{@code 0X}<i> HexDigits<sub>opt</sub>
+ * </i>{@code .} <i>HexDigits</i>
+ * </dl>
+ *
+ * <p>
+ *
+ * <dl>
+ * <dt><i>BinaryExponent:</i>
+ * <dd><i>BinaryExponentIndicator SignedInteger</i>
+ * </dl>
+ *
+ * <p>
+ *
+ * <dl>
+ * <dt><i>BinaryExponentIndicator:</i>
+ * <dd>{@code p}
+ * <dd>{@code P}
+ * </dl>
+ *
+ * </blockquote>
+ *
+ * where <i>Sign</i>, <i>FloatingPointLiteral</i>,
+ * <i>HexNumeral</i>, <i>HexDigits</i>, <i>SignedInteger</i> and
+ * <i>FloatTypeSuffix</i> are as defined in the lexical structure
+ * sections of the of the <a
+ * href="http://java.sun.com/docs/books/jls/html/">Java Language
+ * Specification</a>. If {@code s} does not have the form of
+ * a <i>FloatValue</i>, then a {@code NumberFormatException}
+ * is thrown. Otherwise, {@code s} is regarded as
+ * representing an exact decimal value in the usual
+ * "computerized scientific notation" or as an exact
+ * hexadecimal value; this exact numerical value is then
+ * conceptually converted to an "infinitely precise"
+ * binary value that is then rounded to type {@code float}
+ * by the usual round-to-nearest rule of IEEE 754 floating-point
+ * arithmetic, which includes preserving the sign of a zero
+ * value. Finally, a {@code Float} object representing this
+ * {@code float} value is returned.
+ *
+ * <p>To interpret localized string representations of a
+ * floating-point value, use subclasses of {@link
+ * java.text.NumberFormat}.
+ *
+ * <p>Note that trailing format specifiers, specifiers that
+ * determine the type of a floating-point literal
+ * ({@code 1.0f} is a {@code float} value;
+ * {@code 1.0d} is a {@code double} value), do
+ * <em>not</em> influence the results of this method. In other
+ * words, the numerical value of the input string is converted
+ * directly to the target floating-point type. In general, the
+ * two-step sequence of conversions, string to {@code double}
+ * followed by {@code double} to {@code float}, is
+ * <em>not</em> equivalent to converting a string directly to
+ * {@code float}. For example, if first converted to an
+ * intermediate {@code double} and then to
+ * {@code float}, the string<br>
+ * {@code "1.00000017881393421514957253748434595763683319091796875001d"}<br>
+ * results in the {@code float} value
+ * {@code 1.0000002f}; if the string is converted directly to
+ * {@code float}, <code>1.000000<b>1</b>f</code> results.
+ *
+ * <p>To avoid calling this method on an invalid string and having
+ * a {@code NumberFormatException} be thrown, the documentation
+ * for {@link Double#valueOf Double.valueOf} lists a regular
+ * expression which can be used to screen the input.
+ *
+ * @param s the string to be parsed.
+ * @return a {@code Float} object holding the value
+ * represented by the {@code String} argument.
+ * @throws NumberFormatException if the string does not contain a
+ * parsable number.
+ */
+ public static Float valueOf(String s) throws NumberFormatException {
+ return new Float(FloatingDecimal.readJavaFormatString(s).floatValue());
+ }
+
+ /**
+ * Returns a {@code Float} instance representing the specified
+ * {@code float} value.
+ * If a new {@code Float} instance is not required, this method
+ * should generally be used in preference to the constructor
+ * {@link #Float(float)}, as this method is likely to yield
+ * significantly better space and time performance by caching
+ * frequently requested values.
+ *
+ * @param f a float value.
+ * @return a {@code Float} instance representing {@code f}.
+ * @since 1.5
+ */
+ public static Float valueOf(float f) {
+ return new Float(f);
+ }
+
+ /**
+ * Returns a new {@code float} initialized to the value
+ * represented by the specified {@code String}, as performed
+ * by the {@code valueOf} method of class {@code Float}.
+ *
+ * @param s the string to be parsed.
+ * @return the {@code float} value represented by the string
+ * argument.
+ * @throws NumberFormatException if the string does not contain a
+ * parsable {@code float}.
+ * @see java.lang.Float#valueOf(String)
+ * @since 1.2
+ */
+ public static float parseFloat(String s) throws NumberFormatException {
+ return FloatingDecimal.readJavaFormatString(s).floatValue();
+ }
+
+ /**
+ * Returns {@code true} if the specified number is a
+ * Not-a-Number (NaN) value, {@code false} otherwise.
+ *
+ * @param v the value to be tested.
+ * @return {@code true} if the argument is NaN;
+ * {@code false} otherwise.
+ */
+ static public boolean isNaN(float v) {
+ return (v != v);
+ }
+
+ /**
+ * Returns {@code true} if the specified number is infinitely
+ * large in magnitude, {@code false} otherwise.
+ *
+ * @param v the value to be tested.
+ * @return {@code true} if the argument is positive infinity or
+ * negative infinity; {@code false} otherwise.
+ */
+ static public boolean isInfinite(float v) {
+ return (v == POSITIVE_INFINITY) || (v == NEGATIVE_INFINITY);
+ }
+
+ /**
+ * The value of the Float.
+ *
+ * @serial
+ */
+ private final float value;
+
+ /**
+ * Constructs a newly allocated {@code Float} object that
+ * represents the primitive {@code float} argument.
+ *
+ * @param value the value to be represented by the {@code Float}.
+ */
+ public Float(float value) {
+ this.value = value;
+ }
+
+ /**
+ * Constructs a newly allocated {@code Float} object that
+ * represents the argument converted to type {@code float}.
+ *
+ * @param value the value to be represented by the {@code Float}.
+ */
+ public Float(double value) {
+ this.value = (float)value;
+ }
+
+ /**
+ * Constructs a newly allocated {@code Float} object that
+ * represents the floating-point value of type {@code float}
+ * represented by the string. The string is converted to a
+ * {@code float} value as if by the {@code valueOf} method.
+ *
+ * @param s a string to be converted to a {@code Float}.
+ * @throws NumberFormatException if the string does not contain a
+ * parsable number.
+ * @see java.lang.Float#valueOf(java.lang.String)
+ */
+ public Float(String s) throws NumberFormatException {
+ // REMIND: this is inefficient
+ this(valueOf(s).floatValue());
+ }
+
+ /**
+ * Returns {@code true} if this {@code Float} value is a
+ * Not-a-Number (NaN), {@code false} otherwise.
+ *
+ * @return {@code true} if the value represented by this object is
+ * NaN; {@code false} otherwise.
+ */
+ public boolean isNaN() {
+ return isNaN(value);
+ }
+
+ /**
+ * Returns {@code true} if this {@code Float} value is
+ * infinitely large in magnitude, {@code false} otherwise.
+ *
+ * @return {@code true} if the value represented by this object is
+ * positive infinity or negative infinity;
+ * {@code false} otherwise.
+ */
+ public boolean isInfinite() {
+ return isInfinite(value);
+ }
+
+ /**
+ * Returns a string representation of this {@code Float} object.
+ * The primitive {@code float} value represented by this object
+ * is converted to a {@code String} exactly as if by the method
+ * {@code toString} of one argument.
+ *
+ * @return a {@code String} representation of this object.
+ * @see java.lang.Float#toString(float)
+ */
+ public String toString() {
+ return String.valueOf(value);
+ }
+
+ /**
+ * Returns the value of this {@code Float} as a {@code byte} (by
+ * casting to a {@code byte}).
+ *
+ * @return the {@code float} value represented by this object
+ * converted to type {@code byte}
+ */
+ public byte byteValue() {
+ return (byte)value;
+ }
+
+ /**
+ * Returns the value of this {@code Float} as a {@code short} (by
+ * casting to a {@code short}).
+ *
+ * @return the {@code float} value represented by this object
+ * converted to type {@code short}
+ * @since JDK1.1
+ */
+ public short shortValue() {
+ return (short)value;
+ }
+
+ /**
+ * Returns the value of this {@code Float} as an {@code int} (by
+ * casting to type {@code int}).
+ *
+ * @return the {@code float} value represented by this object
+ * converted to type {@code int}
+ */
+ public int intValue() {
+ return (int)value;
+ }
+
+ /**
+ * Returns value of this {@code Float} as a {@code long} (by
+ * casting to type {@code long}).
+ *
+ * @return the {@code float} value represented by this object
+ * converted to type {@code long}
+ */
+ public long longValue() {
+ return (long)value;
+ }
+
+ /**
+ * Returns the {@code float} value of this {@code Float} object.
+ *
+ * @return the {@code float} value represented by this object
+ */
+ public float floatValue() {
+ return value;
+ }
+
+ /**
+ * Returns the {@code double} value of this {@code Float} object.
+ *
+ * @return the {@code float} value represented by this
+ * object is converted to type {@code double} and the
+ * result of the conversion is returned.
+ */
+ public double doubleValue() {
+ return (double)value;
+ }
+
+ /**
+ * Returns a hash code for this {@code Float} object. The
+ * result is the integer bit representation, exactly as produced
+ * by the method {@link #floatToIntBits(float)}, of the primitive
+ * {@code float} value represented by this {@code Float}
+ * object.
+ *
+ * @return a hash code value for this object.
+ */
+ public int hashCode() {
+ return floatToIntBits(value);
+ }
+
+ /**
+
+ * Compares this object against the specified object. The result
+ * is {@code true} if and only if the argument is not
+ * {@code null} and is a {@code Float} object that
+ * represents a {@code float} with the same value as the
+ * {@code float} represented by this object. For this
+ * purpose, two {@code float} values are considered to be the
+ * same if and only if the method {@link #floatToIntBits(float)}
+ * returns the identical {@code int} value when applied to
+ * each.
+ *
+ * <p>Note that in most cases, for two instances of class
+ * {@code Float}, {@code f1} and {@code f2}, the value
+ * of {@code f1.equals(f2)} is {@code true} if and only if
+ *
+ * <blockquote><pre>
+ * f1.floatValue() == f2.floatValue()
+ * </pre></blockquote>
+ *
+ * <p>also has the value {@code true}. However, there are two exceptions:
+ * <ul>
+ * <li>If {@code f1} and {@code f2} both represent
+ * {@code Float.NaN}, then the {@code equals} method returns
+ * {@code true}, even though {@code Float.NaN==Float.NaN}
+ * has the value {@code false}.
+ * <li>If {@code f1} represents {@code +0.0f} while
+ * {@code f2} represents {@code -0.0f}, or vice
+ * versa, the {@code equal} test has the value
+ * {@code false}, even though {@code 0.0f==-0.0f}
+ * has the value {@code true}.
+ * </ul>
+ *
+ * This definition allows hash tables to operate properly.
+ *
+ * @param obj the object to be compared
+ * @return {@code true} if the objects are the same;
+ * {@code false} otherwise.
+ * @see java.lang.Float#floatToIntBits(float)
+ */
+ public boolean equals(Object obj) {
+ return (obj instanceof Float)
+ && (floatToIntBits(((Float)obj).value) == floatToIntBits(value));
+ }
+
+ /**
+ * Returns a representation of the specified floating-point value
+ * according to the IEEE 754 floating-point "single format" bit
+ * layout.
+ *
+ * <p>Bit 31 (the bit that is selected by the mask
+ * {@code 0x80000000}) represents the sign of the floating-point
+ * number.
+ * Bits 30-23 (the bits that are selected by the mask
+ * {@code 0x7f800000}) represent the exponent.
+ * Bits 22-0 (the bits that are selected by the mask
+ * {@code 0x007fffff}) represent the significand (sometimes called
+ * the mantissa) of the floating-point number.
+ *
+ * <p>If the argument is positive infinity, the result is
+ * {@code 0x7f800000}.
+ *
+ * <p>If the argument is negative infinity, the result is
+ * {@code 0xff800000}.
+ *
+ * <p>If the argument is NaN, the result is {@code 0x7fc00000}.
+ *
+ * <p>In all cases, the result is an integer that, when given to the
+ * {@link #intBitsToFloat(int)} method, will produce a floating-point
+ * value the same as the argument to {@code floatToIntBits}
+ * (except all NaN values are collapsed to a single
+ * "canonical" NaN value).
+ *
+ * @param value a floating-point number.
+ * @return the bits that represent the floating-point number.
+ */
+ public static int floatToIntBits(float value) {
+ int result = floatToRawIntBits(value);
+ // Check for NaN based on values of bit fields, maximum
+ // exponent and nonzero significand.
+ if ( ((result & FloatConsts.EXP_BIT_MASK) ==
+ FloatConsts.EXP_BIT_MASK) &&
+ (result & FloatConsts.SIGNIF_BIT_MASK) != 0)
+ result = 0x7fc00000;
+ return result;
+ }
+
+ /**
+ * Returns a representation of the specified floating-point value
+ * according to the IEEE 754 floating-point "single format" bit
+ * layout, preserving Not-a-Number (NaN) values.
+ *
+ * <p>Bit 31 (the bit that is selected by the mask
+ * {@code 0x80000000}) represents the sign of the floating-point
+ * number.
+ * Bits 30-23 (the bits that are selected by the mask
+ * {@code 0x7f800000}) represent the exponent.
+ * Bits 22-0 (the bits that are selected by the mask
+ * {@code 0x007fffff}) represent the significand (sometimes called
+ * the mantissa) of the floating-point number.
+ *
+ * <p>If the argument is positive infinity, the result is
+ * {@code 0x7f800000}.
+ *
+ * <p>If the argument is negative infinity, the result is
+ * {@code 0xff800000}.
+ *
+ * <p>If the argument is NaN, the result is the integer representing
+ * the actual NaN value. Unlike the {@code floatToIntBits}
+ * method, {@code floatToRawIntBits} does not collapse all the
+ * bit patterns encoding a NaN to a single "canonical"
+ * NaN value.
+ *
+ * <p>In all cases, the result is an integer that, when given to the
+ * {@link #intBitsToFloat(int)} method, will produce a
+ * floating-point value the same as the argument to
+ * {@code floatToRawIntBits}.
+ *
+ * @param value a floating-point number.
+ * @return the bits that represent the floating-point number.
+ * @since 1.3
+ */
+ public static native int floatToRawIntBits(float value);
+
+ /**
+ * Returns the {@code float} value corresponding to a given
+ * bit representation.
+ * The argument is considered to be a representation of a
+ * floating-point value according to the IEEE 754 floating-point
+ * "single format" bit layout.
+ *
+ * <p>If the argument is {@code 0x7f800000}, the result is positive
+ * infinity.
+ *
+ * <p>If the argument is {@code 0xff800000}, the result is negative
+ * infinity.
+ *
+ * <p>If the argument is any value in the range
+ * {@code 0x7f800001} through {@code 0x7fffffff} or in
+ * the range {@code 0xff800001} through
+ * {@code 0xffffffff}, the result is a NaN. No IEEE 754
+ * floating-point operation provided by Java can distinguish
+ * between two NaN values of the same type with different bit
+ * patterns. Distinct values of NaN are only distinguishable by
+ * use of the {@code Float.floatToRawIntBits} method.
+ *
+ * <p>In all other cases, let <i>s</i>, <i>e</i>, and <i>m</i> be three
+ * values that can be computed from the argument:
+ *
+ * <blockquote><pre>
+ * int s = ((bits >> 31) == 0) ? 1 : -1;
+ * int e = ((bits >> 23) & 0xff);
+ * int m = (e == 0) ?
+ * (bits & 0x7fffff) << 1 :
+ * (bits & 0x7fffff) | 0x800000;
+ * </pre></blockquote>
+ *
+ * Then the floating-point result equals the value of the mathematical
+ * expression <i>s</i>·<i>m</i>·2<sup><i>e</i>-150</sup>.
+ *
+ * <p>Note that this method may not be able to return a
+ * {@code float} NaN with exactly same bit pattern as the
+ * {@code int} argument. IEEE 754 distinguishes between two
+ * kinds of NaNs, quiet NaNs and <i>signaling NaNs</i>. The
+ * differences between the two kinds of NaN are generally not
+ * visible in Java. Arithmetic operations on signaling NaNs turn
+ * them into quiet NaNs with a different, but often similar, bit
+ * pattern. However, on some processors merely copying a
+ * signaling NaN also performs that conversion. In particular,
+ * copying a signaling NaN to return it to the calling method may
+ * perform this conversion. So {@code intBitsToFloat} may
+ * not be able to return a {@code float} with a signaling NaN
+ * bit pattern. Consequently, for some {@code int} values,
+ * {@code floatToRawIntBits(intBitsToFloat(start))} may
+ * <i>not</i> equal {@code start}. Moreover, which
+ * particular bit patterns represent signaling NaNs is platform
+ * dependent; although all NaN bit patterns, quiet or signaling,
+ * must be in the NaN range identified above.
+ *
+ * @param bits an integer.
+ * @return the {@code float} floating-point value with the same bit
+ * pattern.
+ */
+ public static native float intBitsToFloat(int bits);
+
+ /**
+ * Compares two {@code Float} objects numerically. There are
+ * two ways in which comparisons performed by this method differ
+ * from those performed by the Java language numerical comparison
+ * operators ({@code <, <=, ==, >=, >}) when
+ * applied to primitive {@code float} values:
+ *
+ * <ul><li>
+ * {@code Float.NaN} is considered by this method to
+ * be equal to itself and greater than all other
+ * {@code float} values
+ * (including {@code Float.POSITIVE_INFINITY}).
+ * <li>
+ * {@code 0.0f} is considered by this method to be greater
+ * than {@code -0.0f}.
+ * </ul>
+ *
+ * This ensures that the <i>natural ordering</i> of {@code Float}
+ * objects imposed by this method is <i>consistent with equals</i>.
+ *
+ * @param anotherFloat the {@code Float} to be compared.
+ * @return the value {@code 0} if {@code anotherFloat} is
+ * numerically equal to this {@code Float}; a value
+ * less than {@code 0} if this {@code Float}
+ * is numerically less than {@code anotherFloat};
+ * and a value greater than {@code 0} if this
+ * {@code Float} is numerically greater than
+ * {@code anotherFloat}.
+ *
+ * @since 1.2
+ * @see Comparable#compareTo(Object)
+ */
+ public int compareTo(Float anotherFloat) {
+ return Float.compare(value, anotherFloat.value);
+ }
+
+ /**
+ * Compares the two specified {@code float} values. The sign
+ * of the integer value returned is the same as that of the
+ * integer that would be returned by the call:
+ * <pre>
+ * new Float(f1).compareTo(new Float(f2))
+ * </pre>
+ *
+ * @param f1 the first {@code float} to compare.
+ * @param f2 the second {@code float} to compare.
+ * @return the value {@code 0} if {@code f1} is
+ * numerically equal to {@code f2}; a value less than
+ * {@code 0} if {@code f1} is numerically less than
+ * {@code f2}; and a value greater than {@code 0}
+ * if {@code f1} is numerically greater than
+ * {@code f2}.
+ * @since 1.4
+ */
+ public static int compare(float f1, float f2) {
+ if (f1 < f2)
+ return -1; // Neither val is NaN, thisVal is smaller
+ if (f1 > f2)
+ return 1; // Neither val is NaN, thisVal is larger
+
+ int thisBits = Float.floatToIntBits(f1);
+ int anotherBits = Float.floatToIntBits(f2);
+
+ return (thisBits == anotherBits ? 0 : // Values are equal
+ (thisBits < anotherBits ? -1 : // (-0.0, 0.0) or (!NaN, NaN)
+ 1)); // (0.0, -0.0) or (NaN, !NaN)
+ }
+
+ /** use serialVersionUID from JDK 1.0.2 for interoperability */
+ private static final long serialVersionUID = -2671257302660747028L;
+}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ls...@us...> - 2007-05-16 20:03:45
|
Revision: 3205
http://jnode.svn.sourceforge.net/jnode/?rev=3205&view=rev
Author: lsantha
Date: 2007-05-16 13:03:44 -0700 (Wed, 16 May 2007)
Log Message:
-----------
Openjdk patches.
Modified Paths:
--------------
trunk/core/src/classpath/vm/java/lang/NativeDouble.java
Added Paths:
-----------
trunk/core/src/classpath/vm/java/lang/NativeFloat.java
Modified: trunk/core/src/classpath/vm/java/lang/NativeDouble.java
===================================================================
--- trunk/core/src/classpath/vm/java/lang/NativeDouble.java 2007-05-16 20:02:30 UTC (rev 3204)
+++ trunk/core/src/classpath/vm/java/lang/NativeDouble.java 2007-05-16 20:03:44 UTC (rev 3205)
@@ -8,7 +8,7 @@
/**
* @author Levente S\xE1ntha
*/
-public class NativeDouble {
+class NativeDouble {
/**
* Convert the double to the IEEE 754 floating-point "double format" bit
* layout. Bit 63 (the most significant) is the sign bit, bits 62-52 (masked
@@ -23,7 +23,7 @@
* @return the bits of the <code>double</code>
* @see java.lang.Double#longBitsToDouble(long)
*/
- public static long doubleToRawLongBits(double value) {
+ static long doubleToRawLongBits(double value) {
return VmMagic.doubleToRawLongBits(value);
}
@@ -41,7 +41,7 @@
* @see java.lang.Double#doubleToLongBits(double)
* @see #doubleToRawLongBits(double)
*/
- public static double longBitsToDouble(long bits) {
+ static double longBitsToDouble(long bits) {
return VmMagic.longBitsToDouble(bits);
}
}
Added: trunk/core/src/classpath/vm/java/lang/NativeFloat.java
===================================================================
--- trunk/core/src/classpath/vm/java/lang/NativeFloat.java (rev 0)
+++ trunk/core/src/classpath/vm/java/lang/NativeFloat.java 2007-05-16 20:03:44 UTC (rev 3205)
@@ -0,0 +1,47 @@
+/*
+ * $Id$
+ */
+package java.lang;
+
+import org.jnode.vm.VmMagic;
+
+/**
+ * @author Levente S\xE1ntha
+ */
+class NativeFloat {
+ /**
+ * Convert the float to the IEEE 754 floating-point "single format" bit
+ * layout. Bit 31 (the most significant) is the sign bit, bits 30-23 (masked
+ * by 0x7f800000) represent the exponent, and bits 22-0 (masked by
+ * 0x007fffff) are the mantissa. This function leaves NaN alone, rather than
+ * collapsing to a canonical value. The result of this function can be used
+ * as the argument to <code>Float.intBitsToFloat(int)</code> to obtain the
+ * original <code>float</code> value.
+ *
+ * @param value
+ * the <code>float</code> to convert
+ * @return the bits of the <code>float</code>
+ * @see #intBitsToFloat(int)
+ */
+ static int floatToRawIntBits(float value) {
+ return VmMagic.floatToRawIntBits(value);
+ }
+
+ /**
+ * Convert the argument in IEEE 754 floating-point "single format" bit
+ * layout to the corresponding float. Bit 31 (the most significant) is the
+ * sign bit, bits 30-23 (masked by 0x7f800000) represent the exponent, and
+ * bits 22-0 (masked by 0x007fffff) are the mantissa. This function leaves
+ * NaN alone, so that you can recover the bit pattern with
+ * <code>Float.floatToRawIntBits(float)</code>.
+ *
+ * @param bits
+ * the bits to convert
+ * @return the <code>float</code> represented by the bits
+ * @see java.lang.Float#floatToIntBits(float)
+ * @see #floatToRawIntBits(float)
+ */
+ static float intBitsToFloat(int bits) {
+ return VmMagic.intBitsToFloat(bits);
+ }
+}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ls...@us...> - 2007-05-16 20:02:33
|
Revision: 3204
http://jnode.svn.sourceforge.net/jnode/?rev=3204&view=rev
Author: lsantha
Date: 2007-05-16 13:02:30 -0700 (Wed, 16 May 2007)
Log Message:
-----------
Openjdk patches.
Removed Paths:
-------------
trunk/core/src/classpath/java/java/lang/Float.java
Deleted: trunk/core/src/classpath/java/java/lang/Float.java
===================================================================
--- trunk/core/src/classpath/java/java/lang/Float.java 2007-05-16 19:09:15 UTC (rev 3203)
+++ trunk/core/src/classpath/java/java/lang/Float.java 2007-05-16 20:02:30 UTC (rev 3204)
@@ -1,611 +0,0 @@
-/* Float.java -- object wrapper for float
- Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
- Free Software Foundation, Inc.
-
-This file is part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; see the file COPYING. If not, write to the
-Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301 USA.
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-
-package java.lang;
-
-/**
- * Instances of class <code>Float</code> represent primitive
- * <code>float</code> values.
- *
- * Additionally, this class provides various helper functions and variables
- * related to floats.
- *
- * @author Paul Fisher
- * @author Andrew Haley (ap...@cy...)
- * @author Eric Blake (eb...@em...)
- * @author Tom Tromey (tr...@re...)
- * @author Andrew John Hughes (gnu...@me...)
- * @since 1.0
- * @status partly updated to 1.5
- */
-public final class Float extends Number implements Comparable<Float>
-{
- /**
- * Compatible with JDK 1.0+.
- */
- private static final long serialVersionUID = -2671257302660747028L;
-
- /**
- * The maximum positive value a <code>double</code> may represent
- * is 3.4028235e+38f.
- */
- public static final float MAX_VALUE = 3.4028235e+38f;
-
- /**
- * The minimum positive value a <code>float</code> may represent
- * is 1.4e-45.
- */
- public static final float MIN_VALUE = 1.4e-45f;
-
- /**
- * The value of a float representation -1.0/0.0, negative infinity.
- */
- public static final float NEGATIVE_INFINITY = -1.0f / 0.0f;
-
- /**
- * The value of a float representation 1.0/0.0, positive infinity.
- */
- public static final float POSITIVE_INFINITY = 1.0f / 0.0f;
-
- /**
- * All IEEE 754 values of NaN have the same value in Java.
- */
- public static final float NaN = 0.0f / 0.0f;
-
- /**
- * The primitive type <code>float</code> is represented by this
- * <code>Class</code> object.
- * @since 1.1
- */
- public static final Class<Float> TYPE = (Class<Float>) VMClassLoader.getPrimitiveClass('F');
-
- /**
- * The number of bits needed to represent a <code>float</code>.
- * @since 1.5
- */
- public static final int SIZE = 32;
-
- /**
- * The immutable value of this Float.
- *
- * @serial the wrapped float
- */
- private final float value;
-
- /**
- * Create a <code>Float</code> from the primitive <code>float</code>
- * specified.
- *
- * @param value the <code>float</code> argument
- */
- public Float(float value)
- {
- this.value = value;
- }
-
- /**
- * Create a <code>Float</code> from the primitive <code>double</code>
- * specified.
- *
- * @param value the <code>double</code> argument
- */
- public Float(double value)
- {
- this.value = (float) value;
- }
-
- /**
- * Create a <code>Float</code> from the specified <code>String</code>.
- * This method calls <code>Float.parseFloat()</code>.
- *
- * @param s the <code>String</code> to convert
- * @throws NumberFormatException if <code>s</code> cannot be parsed as a
- * <code>float</code>
- * @throws NullPointerException if <code>s</code> is null
- * @see #parseFloat(String)
- */
- public Float(String s)
- {
- value = parseFloat(s);
- }
-
- /**
- * Convert the <code>float</code> to a <code>String</code>.
- * Floating-point string representation is fairly complex: here is a
- * rundown of the possible values. "<code>[-]</code>" indicates that a
- * negative sign will be printed if the value (or exponent) is negative.
- * "<code><number></code>" means a string of digits ('0' to '9').
- * "<code><digit></code>" means a single digit ('0' to '9').<br>
- *
- * <table border=1>
- * <tr><th>Value of Float</th><th>String Representation</th></tr>
- * <tr><td>[+-] 0</td> <td><code>[-]0.0</code></td></tr>
- * <tr><td>Between [+-] 10<sup>-3</sup> and 10<sup>7</sup>, exclusive</td>
- * <td><code>[-]number.number</code></td></tr>
- * <tr><td>Other numeric value</td>
- * <td><code>[-]<digit>.<number>
- * E[-]<number></code></td></tr>
- * <tr><td>[+-] infinity</td> <td><code>[-]Infinity</code></td></tr>
- * <tr><td>NaN</td> <td><code>NaN</code></td></tr>
- * </table>
- *
- * Yes, negative zero <em>is</em> a possible value. Note that there is
- * <em>always</em> a <code>.</code> and at least one digit printed after
- * it: even if the number is 3, it will be printed as <code>3.0</code>.
- * After the ".", all digits will be printed except trailing zeros. The
- * result is rounded to the shortest decimal number which will parse back
- * to the same float.
- *
- * <p>To create other output formats, use {@link java.text.NumberFormat}.
- *
- * @XXX specify where we are not in accord with the spec.
- *
- * @param f the <code>float</code> to convert
- * @return the <code>String</code> representing the <code>float</code>
- */
- public static String toString(float f)
- {
- return VMDouble.toString(f, true);
- }
-
- /**
- * Convert a float value to a hexadecimal string. This converts as
- * follows:
- * <ul>
- * <li> A NaN value is converted to the string "NaN".
- * <li> Positive infinity is converted to the string "Infinity".
- * <li> Negative infinity is converted to the string "-Infinity".
- * <li> For all other values, the first character of the result is '-'
- * if the value is negative. This is followed by '0x1.' if the
- * value is normal, and '0x0.' if the value is denormal. This is
- * then followed by a (lower-case) hexadecimal representation of the
- * mantissa, with leading zeros as required for denormal values.
- * The next character is a 'p', and this is followed by a decimal
- * representation of the unbiased exponent.
- * </ul>
- * @param f the float value
- * @return the hexadecimal string representation
- * @since 1.5
- */
- public static String toHexString(float f)
- {
- if (isNaN(f))
- return "NaN";
- if (isInfinite(f))
- return f < 0 ? "-Infinity" : "Infinity";
-
- int bits = floatToIntBits(f);
- StringBuilder result = new StringBuilder();
-
- if (bits < 0)
- result.append('-');
- result.append("0x");
-
- final int mantissaBits = 23;
- final int exponentBits = 8;
- int mantMask = (1 << mantissaBits) - 1;
- int mantissa = bits & mantMask;
- int expMask = (1 << exponentBits) - 1;
- int exponent = (bits >>> mantissaBits) & expMask;
-
- result.append(exponent == 0 ? '0' : '1');
- result.append('.');
- // For Float only, we have to adjust the mantissa.
- mantissa <<= 1;
- result.append(Integer.toHexString(mantissa));
- if (exponent == 0 && mantissa != 0)
- {
- // Treat denormal specially by inserting '0's to make
- // the length come out right. The constants here are
- // to account for things like the '0x'.
- int offset = 4 + ((bits < 0) ? 1 : 0);
- // The silly +3 is here to keep the code the same between
- // the Float and Double cases. In Float the value is
- // not a multiple of 4.
- int desiredLength = offset + (mantissaBits + 3) / 4;
- while (result.length() < desiredLength)
- result.insert(offset, '0');
- }
- result.append('p');
- if (exponent == 0 && mantissa == 0)
- {
- // Zero, so do nothing special.
- }
- else
- {
- // Apply bias.
- boolean denormal = exponent == 0;
- exponent -= (1 << (exponentBits - 1)) - 1;
- // Handle denormal.
- if (denormal)
- ++exponent;
- }
-
- result.append(Integer.toString(exponent));
- return result.toString();
- }
-
- /**
- * Creates a new <code>Float</code> object using the <code>String</code>.
- *
- * @param s the <code>String</code> to convert
- * @return the new <code>Float</code>
- * @throws NumberFormatException if <code>s</code> cannot be parsed as a
- * <code>float</code>
- * @throws NullPointerException if <code>s</code> is null
- * @see #parseFloat(String)
- */
- public static Float valueOf(String s)
- {
- return new Float(parseFloat(s));
- }
-
- /**
- * Returns a <code>Float</code> object wrapping the value.
- * In contrast to the <code>Float</code> constructor, this method
- * may cache some values. It is used by boxing conversion.
- *
- * @param val the value to wrap
- * @return the <code>Float</code>
- * @since 1.5
- */
- public static Float valueOf(float val)
- {
- // We don't actually cache, but we could.
- return new Float(val);
- }
-
- /**
- * Parse the specified <code>String</code> as a <code>float</code>. The
- * extended BNF grammar is as follows:<br>
- * <pre>
- * <em>DecodableString</em>:
- * ( [ <code>-</code> | <code>+</code> ] <code>NaN</code> )
- * | ( [ <code>-</code> | <code>+</code> ] <code>Infinity</code> )
- * | ( [ <code>-</code> | <code>+</code> ] <em>FloatingPoint</em>
- * [ <code>f</code> | <code>F</code> | <code>d</code>
- * | <code>D</code>] )
- * <em>FloatingPoint</em>:
- * ( { <em>Digit</em> }+ [ <code>.</code> { <em>Digit</em> } ]
- * [ <em>Exponent</em> ] )
- * | ( <code>.</code> { <em>Digit</em> }+ [ <em>Exponent</em> ] )
- * <em>Exponent</em>:
- * ( ( <code>e</code> | <code>E</code> )
- * [ <code>-</code> | <code>+</code> ] { <em>Digit</em> }+ )
- * <em>Digit</em>: <em><code>'0'</code> through <code>'9'</code></em>
- * </pre>
- *
- * <p>NaN and infinity are special cases, to allow parsing of the output
- * of toString. Otherwise, the result is determined by calculating
- * <em>n * 10<sup>exponent</sup></em> to infinite precision, then rounding
- * to the nearest float. Remember that many numbers cannot be precisely
- * represented in floating point. In case of overflow, infinity is used,
- * and in case of underflow, signed zero is used. Unlike Integer.parseInt,
- * this does not accept Unicode digits outside the ASCII range.
- *
- * <p>If an unexpected character is found in the <code>String</code>, a
- * <code>NumberFormatException</code> will be thrown. Leading and trailing
- * 'whitespace' is ignored via <code>String.trim()</code>, but spaces
- * internal to the actual number are not allowed.
- *
- * <p>To parse numbers according to another format, consider using
- * {@link java.text.NumberFormat}.
- *
- * @XXX specify where/how we are not in accord with the spec.
- *
- * @param str the <code>String</code> to convert
- * @return the <code>float</code> value of <code>s</code>
- * @throws NumberFormatException if <code>s</code> cannot be parsed as a
- * <code>float</code>
- * @throws NullPointerException if <code>s</code> is null
- * @see #MIN_VALUE
- * @see #MAX_VALUE
- * @see #POSITIVE_INFINITY
- * @see #NEGATIVE_INFINITY
- * @since 1.2
- */
- public static float parseFloat(String str)
- {
- // XXX Rounding parseDouble() causes some errors greater than 1 ulp from
- // the infinitely precise decimal.
- return (float) Double.parseDouble(str);
- }
-
- /**
- * Return <code>true</code> if the <code>float</code> has the same
- * value as <code>NaN</code>, otherwise return <code>false</code>.
- *
- * @param v the <code>float</code> to compare
- * @return whether the argument is <code>NaN</code>
- */
- public static boolean isNaN(float v)
- {
- // This works since NaN != NaN is the only reflexive inequality
- // comparison which returns true.
- return v != v;
- }
-
- /**
- * Return <code>true</code> if the <code>float</code> has a value
- * equal to either <code>NEGATIVE_INFINITY</code> or
- * <code>POSITIVE_INFINITY</code>, otherwise return <code>false</code>.
- *
- * @param v the <code>float</code> to compare
- * @return whether the argument is (-/+) infinity
- */
- public static boolean isInfinite(float v)
- {
- return v == POSITIVE_INFINITY || v == NEGATIVE_INFINITY;
- }
-
- /**
- * Return <code>true</code> if the value of this <code>Float</code>
- * is the same as <code>NaN</code>, otherwise return <code>false</code>.
- *
- * @return whether this <code>Float</code> is <code>NaN</code>
- */
- public boolean isNaN()
- {
- return isNaN(value);
- }
-
- /**
- * Return <code>true</code> if the value of this <code>Float</code>
- * is the same as <code>NEGATIVE_INFINITY</code> or
- * <code>POSITIVE_INFINITY</code>, otherwise return <code>false</code>.
- *
- * @return whether this <code>Float</code> is (-/+) infinity
- */
- public boolean isInfinite()
- {
- return isInfinite(value);
- }
-
- /**
- * Convert the <code>float</code> value of this <code>Float</code>
- * to a <code>String</code>. This method calls
- * <code>Float.toString(float)</code> to do its dirty work.
- *
- * @return the <code>String</code> representation
- * @see #toString(float)
- */
- public String toString()
- {
- return toString(value);
- }
-
- /**
- * Return the value of this <code>Float</code> as a <code>byte</code>.
- *
- * @return the byte value
- * @since 1.1
- */
- public byte byteValue()
- {
- return (byte) value;
- }
-
- /**
- * Return the value of this <code>Float</code> as a <code>short</code>.
- *
- * @return the short value
- * @since 1.1
- */
- public short shortValue()
- {
- return (short) value;
- }
-
- /**
- * Return the value of this <code>Integer</code> as an <code>int</code>.
- *
- * @return the int value
- */
- public int intValue()
- {
- return (int) value;
- }
-
- /**
- * Return the value of this <code>Integer</code> as a <code>long</code>.
- *
- * @return the long value
- */
- public long longValue()
- {
- return (long) value;
- }
-
- /**
- * Return the value of this <code>Float</code>.
- *
- * @return the float value
- */
- public float floatValue()
- {
- return value;
- }
-
- /**
- * Return the value of this <code>Float</code> as a <code>double</code>
- *
- * @return the double value
- */
- public double doubleValue()
- {
- return value;
- }
-
- /**
- * Return a hashcode representing this Object. <code>Float</code>'s hash
- * code is calculated by calling <code>floatToIntBits(floatValue())</code>.
- *
- * @return this Object's hash code
- * @see #floatToIntBits(float)
- */
- public int hashCode()
- {
- return floatToIntBits(value);
- }
-
- /**
- * Returns <code>true</code> if <code>obj</code> is an instance of
- * <code>Float</code> and represents the same float value. Unlike comparing
- * two floats with <code>==</code>, this treats two instances of
- * <code>Float.NaN</code> as equal, but treats <code>0.0</code> and
- * <code>-0.0</code> as unequal.
- *
- * <p>Note that <code>f1.equals(f2)</code> is identical to
- * <code>floatToIntBits(f1.floatValue()) ==
- * floatToIntBits(f2.floatValue())</code>.
- *
- * @param obj the object to compare
- * @return whether the objects are semantically equal
- */
- public boolean equals(Object obj)
- {
- if (! (obj instanceof Float))
- return false;
-
- float f = ((Float) obj).value;
-
- // Avoid call to native method. However, some implementations, like gcj,
- // are better off using floatToIntBits(value) == floatToIntBits(f).
- // Check common case first, then check NaN and 0.
- if (value == f)
- return (value != 0) || (1 / value == 1 / f);
- return isNaN(value) && isNaN(f);
- }
-
- /**
- * Convert the float to the IEEE 754 floating-point "single format" bit
- * layout. Bit 31 (the most significant) is the sign bit, bits 30-23
- * (masked by 0x7f800000) represent the exponent, and bits 22-0
- * (masked by 0x007fffff) are the mantissa. This function collapses all
- * versions of NaN to 0x7fc00000. The result of this function can be used
- * as the argument to <code>Float.intBitsToFloat(int)</code> to obtain the
- * original <code>float</code> value.
- *
- * @param value the <code>float</code> to convert
- * @return the bits of the <code>float</code>
- * @see #intBitsToFloat(int)
- */
- public static int floatToIntBits(float value)
- {
- return VMFloat.floatToIntBits(value);
- }
-
- /**
- * Convert the float to the IEEE 754 floating-point "single format" bit
- * layout. Bit 31 (the most significant) is the sign bit, bits 30-23
- * (masked by 0x7f800000) represent the exponent, and bits 22-0
- * (masked by 0x007fffff) are the mantissa. This function leaves NaN alone,
- * rather than collapsing to a canonical value. The result of this function
- * can be used as the argument to <code>Float.intBitsToFloat(int)</code> to
- * obtain the original <code>float</code> value.
- *
- * @param value the <code>float</code> to convert
- * @return the bits of the <code>float</code>
- * @see #intBitsToFloat(int)
- */
- public static int floatToRawIntBits(float value)
- {
- return VMFloat.floatToRawIntBits(value);
- }
-
- /**
- * Convert the argument in IEEE 754 floating-point "single format" bit
- * layout to the corresponding float. Bit 31 (the most significant) is the
- * sign bit, bits 30-23 (masked by 0x7f800000) represent the exponent, and
- * bits 22-0 (masked by 0x007fffff) are the mantissa. This function leaves
- * NaN alone, so that you can recover the bit pattern with
- * <code>Float.floatToRawIntBits(float)</code>.
- *
- * @param bits the bits to convert
- * @return the <code>float</code> represented by the bits
- * @see #floatToIntBits(float)
- * @see #floatToRawIntBits(float)
- */
- public static float intBitsToFloat(int bits)
- {
- return VMFloat.intBitsToFloat(bits);
- }
-
- /**
- * Compare two Floats numerically by comparing their <code>float</code>
- * values. The result is positive if the first is greater, negative if the
- * second is greater, and 0 if the two are equal. However, this special
- * cases NaN and signed zero as follows: NaN is considered greater than
- * all other floats, including <code>POSITIVE_INFINITY</code>, and positive
- * zero is considered greater than negative zero.
- *
- * @param f the Float to compare
- * @return the comparison
- * @since 1.2
- */
- public int compareTo(Float f)
- {
- return compare(value, f.value);
- }
-
- /**
- * Behaves like <code>new Float(x).compareTo(new Float(y))</code>; in
- * other words this compares two floats, special casing NaN and zero,
- * without the overhead of objects.
- *
- * @param x the first float to compare
- * @param y the second float to compare
- * @return the comparison
- * @since 1.4
- */
- public static int compare(float x, float y)
- {
- if (isNaN(x))
- return isNaN(y) ? 0 : 1;
- if (isNaN(y))
- return -1;
- // recall that 0.0 == -0.0, so we convert to infinities and try again
- if (x == 0 && y == 0)
- return (int) (1 / x - 1 / y);
- if (x == y)
- return 0;
-
- return x > y ? 1 : -1;
- }
-}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ls...@us...> - 2007-05-16 19:09:21
|
Revision: 3203
http://jnode.svn.sourceforge.net/jnode/?rev=3203&view=rev
Author: lsantha
Date: 2007-05-16 12:09:15 -0700 (Wed, 16 May 2007)
Log Message:
-----------
Fixed getFields() and getDeclaredFields().
Modified Paths:
--------------
trunk/core/src/classpath/vm/java/lang/Class.java
Modified: trunk/core/src/classpath/vm/java/lang/Class.java
===================================================================
--- trunk/core/src/classpath/vm/java/lang/Class.java 2007-05-13 17:16:52 UTC (rev 3202)
+++ trunk/core/src/classpath/vm/java/lang/Class.java 2007-05-16 19:09:15 UTC (rev 3203)
@@ -61,6 +61,7 @@
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Arrays;
+import java.util.HashSet;
import org.jnode.security.JNodePermission;
import org.jnode.vm.SoftByteCodes;
@@ -455,28 +456,32 @@
throw new NoSuchFieldException(name);
}
}
-
/**
* Gets all fields declared in this class and all of its super-classes.
- *
+ *
* @return Field[]
*/
- public Field[] getFields() {
- if (fields == null) {
- ArrayList<Field> list = new ArrayList<Field>();
- Class< ? > cls = this;
- while (cls != null) {
- final Field[] dlist = cls.getDeclaredFields();
- for (int i = 0; i < dlist.length; i++) {
- list.add(dlist[i]);
- }
- cls = cls.getSuperclass();
- }
- fields = list;
- }
- return (Field[]) fields.toArray(new Field[fields.size()]);
- }
+ public Field[] getFields()
+ {
+ //todo enable this: memberAccessCheck(Member.PUBLIC);
+ return internalGetFields();
+ }
+ /**
+ * Like <code>getFields()</code> but without the security checks.
+ */
+ private Field[] internalGetFields()
+ {
+ HashSet<Field> set = new HashSet<Field>();
+ set.addAll(Arrays.asList(getDeclaredFields(true)));
+ Class[] interfaces = getInterfaces();
+ for (int i = 0; i < interfaces.length; i++)
+ set.addAll(Arrays.asList(interfaces[i].internalGetFields()));
+ Class superClass = getSuperclass();
+ if (superClass != null)
+ set.addAll(Arrays.asList(superClass.internalGetFields()));
+ return set.toArray(new Field[set.size()]);
+ }
/**
* Gets the field with the given name that is declared in this class.
*
@@ -494,24 +499,44 @@
throw new NoSuchFieldException(name);
}
}
-
/**
* Gets all fields declared in this class
- *
+ *
* @return Field[]
*/
- public Field[] getDeclaredFields() {
- if (declaredFields == null) {
- final VmType<T> vmClass = getLinkedVmClass();
- final int cnt = vmClass.getNoDeclaredFields();
- final Field[] list = new Field[cnt];
+ public Field[] getDeclaredFields()
+ {
+ //todo enable this memberAccessCheck(Member.DECLARED);
+ return getDeclaredFields(false);
+ }
+
+ Field[] getDeclaredFields (boolean publicOnly)
+ {
+ if (declaredFields == null) {
+ final VmType<T> vmClass = getLinkedVmClass();
+ final int cnt = vmClass.getNoDeclaredFields();
+ final ArrayList<Field> fields = new ArrayList<Field>();
for (int i = 0; i < cnt; i++) {
- list[i] = vmClass.getDeclaredField(i).asField();
+ Field field = vmClass.getDeclaredField(i).asField();
+ if(field.getDeclaringClass() == this) {//todo we need this check?
+ fields.add(field);
+ }
}
- declaredFields = list;
+ declaredFields = fields.toArray(new Field[fields.size()]);
+ }
+ if(publicOnly){
+ final ArrayList<Field> fields = new ArrayList<Field>();
+ for (Field field : declaredFields) {
+ if((field.getModifiers() & Modifier.PUBLIC) != 0) {
+ fields.add(field);
+ }
}
- return declaredFields;
- }
+ return fields.toArray(new Field[fields.size()]);
+ } else {
+ //todo fials! return Arrays.copyOf(declaredFields, declaredFields.length);
+ return declaredFields;
+ }
+ }
/**
* Is this class a primitive class?
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ls...@us...> - 2007-05-13 17:16:53
|
Revision: 3202
http://jnode.svn.sourceforge.net/jnode/?rev=3202&view=rev
Author: lsantha
Date: 2007-05-13 10:16:52 -0700 (Sun, 13 May 2007)
Log Message:
-----------
First merges of OpenJDK.
Modified Paths:
--------------
trunk/core/descriptors/org.classpath.core.xml
trunk/core/descriptors/org.classpath.ext.core.xml
Modified: trunk/core/descriptors/org.classpath.core.xml
===================================================================
--- trunk/core/descriptors/org.classpath.core.xml 2007-05-13 17:11:49 UTC (rev 3201)
+++ trunk/core/descriptors/org.classpath.core.xml 2007-05-13 17:16:52 UTC (rev 3202)
@@ -11,7 +11,9 @@
<runtime>
<library name="jnode-core.jar">
-
+
+ <export name="sun.misc.*"/>
+
<export name="gnu.classpath.Configuration"/>
<export name="gnu.classpath.Pointer"/>
<export name="gnu.classpath.SystemProperties"/>
Modified: trunk/core/descriptors/org.classpath.ext.core.xml
===================================================================
--- trunk/core/descriptors/org.classpath.ext.core.xml 2007-05-13 17:11:49 UTC (rev 3201)
+++ trunk/core/descriptors/org.classpath.ext.core.xml 2007-05-13 17:16:52 UTC (rev 3202)
@@ -77,8 +77,7 @@
<export name="javax.sound.sampled.*"/>
<export name="javax.sound.sampled.spi.*"/>
-
- <export name="sun.misc.*"/>
+
<export name="sun.reflect.*"/>
<export name="sun.reflect.annotation.*"/>
<export name="sun.reflect.misc.*"/>
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ls...@us...> - 2007-05-13 17:11:50
|
Revision: 3201
http://jnode.svn.sourceforge.net/jnode/?rev=3201&view=rev
Author: lsantha
Date: 2007-05-13 10:11:49 -0700 (Sun, 13 May 2007)
Log Message:
-----------
First merges of OpenJDK.
Added Paths:
-----------
trunk/core/src/openjdk/javax/
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ls...@us...> - 2007-05-13 17:11:30
|
Revision: 3200
http://jnode.svn.sourceforge.net/jnode/?rev=3200&view=rev
Author: lsantha
Date: 2007-05-13 10:11:27 -0700 (Sun, 13 May 2007)
Log Message:
-----------
First merges of OpenJDK.
Added Paths:
-----------
trunk/core/src/openjdk/sun/sun/misc/
trunk/core/src/openjdk/sun/sun/misc/DoubleConsts.java
trunk/core/src/openjdk/sun/sun/misc/FloatConsts.java
trunk/core/src/openjdk/sun/sun/misc/FloatingDecimal.java
trunk/core/src/openjdk/sun/sun/misc/FpUtils.java
trunk/core/src/openjdk/sun/sun/text/
trunk/core/src/openjdk/sun/sun/text/Normalizer.java
trunk/core/src/openjdk/sun/sun/text/normalizer/
trunk/core/src/openjdk/sun/sun/text/normalizer/CharTrie.java
trunk/core/src/openjdk/sun/sun/text/normalizer/CharacterIteratorWrapper.java
trunk/core/src/openjdk/sun/sun/text/normalizer/ICUBinary.java
trunk/core/src/openjdk/sun/sun/text/normalizer/ICUData.java
trunk/core/src/openjdk/sun/sun/text/normalizer/IntTrie.java
trunk/core/src/openjdk/sun/sun/text/normalizer/NormalizerBase.java
trunk/core/src/openjdk/sun/sun/text/normalizer/NormalizerDataReader.java
trunk/core/src/openjdk/sun/sun/text/normalizer/NormalizerImpl.java
trunk/core/src/openjdk/sun/sun/text/normalizer/RangeValueIterator.java
trunk/core/src/openjdk/sun/sun/text/normalizer/Replaceable.java
trunk/core/src/openjdk/sun/sun/text/normalizer/ReplaceableString.java
trunk/core/src/openjdk/sun/sun/text/normalizer/ReplaceableUCharacterIterator.java
trunk/core/src/openjdk/sun/sun/text/normalizer/RuleCharacterIterator.java
trunk/core/src/openjdk/sun/sun/text/normalizer/SymbolTable.java
trunk/core/src/openjdk/sun/sun/text/normalizer/Trie.java
trunk/core/src/openjdk/sun/sun/text/normalizer/TrieIterator.java
trunk/core/src/openjdk/sun/sun/text/normalizer/UCharacter.java
trunk/core/src/openjdk/sun/sun/text/normalizer/UCharacterIterator.java
trunk/core/src/openjdk/sun/sun/text/normalizer/UCharacterProperty.java
trunk/core/src/openjdk/sun/sun/text/normalizer/UCharacterPropertyReader.java
trunk/core/src/openjdk/sun/sun/text/normalizer/UProperty.java
trunk/core/src/openjdk/sun/sun/text/normalizer/UTF16.java
trunk/core/src/openjdk/sun/sun/text/normalizer/UnicodeMatcher.java
trunk/core/src/openjdk/sun/sun/text/normalizer/UnicodeSet.java
trunk/core/src/openjdk/sun/sun/text/normalizer/UnicodeSetIterator.java
trunk/core/src/openjdk/sun/sun/text/normalizer/Utility.java
trunk/core/src/openjdk/sun/sun/text/normalizer/VersionInfo.java
Added: trunk/core/src/openjdk/sun/sun/misc/DoubleConsts.java
===================================================================
--- trunk/core/src/openjdk/sun/sun/misc/DoubleConsts.java (rev 0)
+++ trunk/core/src/openjdk/sun/sun/misc/DoubleConsts.java 2007-05-13 17:11:27 UTC (rev 3200)
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.misc;
+
+/**
+ * This class contains additional constants documenting limits of the
+ * <code>double</code> type.
+ *
+ * @author Joseph D. Darcy
+ * @version 1.7, 05/05/07
+ */
+
+public class DoubleConsts {
+ /**
+ * Don't let anyone instantiate this class.
+ */
+ private DoubleConsts() {}
+
+ public static final double POSITIVE_INFINITY = java.lang.Double.POSITIVE_INFINITY;
+ public static final double NEGATIVE_INFINITY = java.lang.Double.NEGATIVE_INFINITY;
+ public static final double NaN = java.lang.Double.NaN;
+ public static final double MAX_VALUE = java.lang.Double.MAX_VALUE;
+ public static final double MIN_VALUE = java.lang.Double.MIN_VALUE;
+
+ /**
+ * A constant holding the smallest positive normal value of type
+ * <code>double</code>, 2<sup>-1022</sup>. It is equal to the
+ * value returned by
+ * <code>Double.longBitsToDouble(0x0010000000000000L)</code>.
+ *
+ * @since 1.5
+ */
+ public static final double MIN_NORMAL = 2.2250738585072014E-308;
+
+
+ /**
+ * The number of logical bits in the significand of a
+ * <code>double</code> number, including the implicit bit.
+ */
+ public static final int SIGNIFICAND_WIDTH = 53;
+
+ /**
+ * Maximum exponent a finite <code>double</code> number may have.
+ * It is equal to the value returned by
+ * <code>Math.ilogb(Double.MAX_VALUE)</code>.
+ */
+ public static final int MAX_EXPONENT = 1023;
+
+ /**
+ * Minimum exponent a normalized <code>double</code> number may
+ * have. It is equal to the value returned by
+ * <code>Math.ilogb(Double.MIN_NORMAL)</code>.
+ */
+ public static final int MIN_EXPONENT = -1022;
+
+ /**
+ * The exponent the smallest positive <code>double</code>
+ * subnormal value would have if it could be normalized. It is
+ * equal to the value returned by
+ * <code>FpUtils.ilogb(Double.MIN_VALUE)</code>.
+ */
+ public static final int MIN_SUB_EXPONENT = MIN_EXPONENT -
+ (SIGNIFICAND_WIDTH - 1);
+
+ /**
+ * Bias used in representing a <code>double</code> exponent.
+ */
+ public static final int EXP_BIAS = 1023;
+
+ /**
+ * Bit mask to isolate the sign bit of a <code>double</code>.
+ */
+ public static final long SIGN_BIT_MASK = 0x8000000000000000L;
+
+ /**
+ * Bit mask to isolate the exponent field of a
+ * <code>double</code>.
+ */
+ public static final long EXP_BIT_MASK = 0x7FF0000000000000L;
+
+ /**
+ * Bit mask to isolate the significand field of a
+ * <code>double</code>.
+ */
+ public static final long SIGNIF_BIT_MASK = 0x000FFFFFFFFFFFFFL;
+
+ static {
+ // verify bit masks cover all bit positions and that the bit
+ // masks are non-overlapping
+ assert(((SIGN_BIT_MASK | EXP_BIT_MASK | SIGNIF_BIT_MASK) == ~0L) &&
+ (((SIGN_BIT_MASK & EXP_BIT_MASK) == 0L) &&
+ ((SIGN_BIT_MASK & SIGNIF_BIT_MASK) == 0L) &&
+ ((EXP_BIT_MASK & SIGNIF_BIT_MASK) == 0L)));
+ }
+}
Added: trunk/core/src/openjdk/sun/sun/misc/FloatConsts.java
===================================================================
--- trunk/core/src/openjdk/sun/sun/misc/FloatConsts.java (rev 0)
+++ trunk/core/src/openjdk/sun/sun/misc/FloatConsts.java 2007-05-13 17:11:27 UTC (rev 3200)
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.misc;
+
+/**
+ * This class contains additional constants documenting limits of the
+ * <code>float</code> type.
+ *
+ * @author Joseph D. Darcy
+ * @version 1.7, 05/05/07
+ */
+
+public class FloatConsts {
+ /**
+ * Don't let anyone instantiate this class.
+ */
+ private FloatConsts() {}
+
+ public static final float POSITIVE_INFINITY = java.lang.Float.POSITIVE_INFINITY;
+ public static final float NEGATIVE_INFINITY = java.lang.Float.NEGATIVE_INFINITY;
+ public static final float NaN = java.lang.Float.NaN;
+ public static final float MAX_VALUE = java.lang.Float.MAX_VALUE;
+ public static final float MIN_VALUE = java.lang.Float.MIN_VALUE;
+
+ /**
+ * A constant holding the smallest positive normal value of type
+ * <code>float</code>, 2<sup>-126</sup>. It is equal to the value
+ * returned by <code>Float.intBitsToFloat(0x00800000)</code>.
+ */
+ public static final float MIN_NORMAL = 1.17549435E-38f;
+
+ /**
+ * The number of logical bits in the significand of a
+ * <code>float</code> number, including the implicit bit.
+ */
+ public static final int SIGNIFICAND_WIDTH = 24;
+
+ /**
+ * Maximum exponent a finite <code>float</code> number may have.
+ * It is equal to the value returned by
+ * <code>Math.ilogb(Float.MAX_VALUE)</code>.
+ */
+ public static final int MAX_EXPONENT = 127;
+
+ /**
+ * Minimum exponent a normalized <code>float</code> number may
+ * have. It is equal to the value returned by
+ * <code>Math.ilogb(Float.MIN_NORMAL)</code>.
+ */
+ public static final int MIN_EXPONENT = -126;
+
+ /**
+ * The exponent the smallest positive <code>float</code> subnormal
+ * value would have if it could be normalized. It is equal to the
+ * value returned by <code>FpUtils.ilogb(Float.MIN_VALUE)</code>.
+ */
+ public static final int MIN_SUB_EXPONENT = MIN_EXPONENT -
+ (SIGNIFICAND_WIDTH - 1);
+
+ /**
+ * Bias used in representing a <code>float</code> exponent.
+ */
+ public static final int EXP_BIAS = 127;
+
+ /**
+ * Bit mask to isolate the sign bit of a <code>float</code>.
+ */
+ public static final int SIGN_BIT_MASK = 0x80000000;
+
+ /**
+ * Bit mask to isolate the exponent field of a
+ * <code>float</code>.
+ */
+ public static final int EXP_BIT_MASK = 0x7F800000;
+
+ /**
+ * Bit mask to isolate the significand field of a
+ * <code>float</code>.
+ */
+ public static final int SIGNIF_BIT_MASK = 0x007FFFFF;
+
+ static {
+ // verify bit masks cover all bit positions and that the bit
+ // masks are non-overlapping
+ assert(((SIGN_BIT_MASK | EXP_BIT_MASK | SIGNIF_BIT_MASK) == ~0) &&
+ (((SIGN_BIT_MASK & EXP_BIT_MASK) == 0) &&
+ ((SIGN_BIT_MASK & SIGNIF_BIT_MASK) == 0) &&
+ ((EXP_BIT_MASK & SIGNIF_BIT_MASK) == 0)));
+ }
+}
Added: trunk/core/src/openjdk/sun/sun/misc/FloatingDecimal.java
===================================================================
--- trunk/core/src/openjdk/sun/sun/misc/FloatingDecimal.java (rev 0)
+++ trunk/core/src/openjdk/sun/sun/misc/FloatingDecimal.java 2007-05-13 17:11:27 UTC (rev 3200)
@@ -0,0 +1,2876 @@
+/*
+ * Copyright 1996-2004 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.misc;
+
+import sun.misc.FpUtils;
+import sun.misc.DoubleConsts;
+import sun.misc.FloatConsts;
+import java.util.regex.*;
+
+public class FloatingDecimal{
+ boolean isExceptional;
+ boolean isNegative;
+ int decExponent;
+ char digits[];
+ int nDigits;
+ int bigIntExp;
+ int bigIntNBits;
+ boolean mustSetRoundDir = false;
+ boolean fromHex = false;
+ int roundDir = 0; // set by doubleValue
+
+ private FloatingDecimal( boolean negSign, int decExponent, char []digits, int n, boolean e )
+ {
+ isNegative = negSign;
+ isExceptional = e;
+ this.decExponent = decExponent;
+ this.digits = digits;
+ this.nDigits = n;
+ }
+
+ /*
+ * Constants of the implementation
+ * Most are IEEE-754 related.
+ * (There are more really boring constants at the end.)
+ */
+ static final long signMask = 0x8000000000000000L;
+ static final long expMask = 0x7ff0000000000000L;
+ static final long fractMask= ~(signMask|expMask);
+ static final int expShift = 52;
+ static final int expBias = 1023;
+ static final long fractHOB = ( 1L<<expShift ); // assumed High-Order bit
+ static final long expOne = ((long)expBias)<<expShift; // exponent of 1.0
+ static final int maxSmallBinExp = 62;
+ static final int minSmallBinExp = -( 63 / 3 );
+ static final int maxDecimalDigits = 15;
+ static final int maxDecimalExponent = 308;
+ static final int minDecimalExponent = -324;
+ static final int bigDecimalExponent = 324; // i.e. abs(minDecimalExponent)
+
+ static final long highbyte = 0xff00000000000000L;
+ static final long highbit = 0x8000000000000000L;
+ static final long lowbytes = ~highbyte;
+
+ static final int singleSignMask = 0x80000000;
+ static final int singleExpMask = 0x7f800000;
+ static final int singleFractMask = ~(singleSignMask|singleExpMask);
+ static final int singleExpShift = 23;
+ static final int singleFractHOB = 1<<singleExpShift;
+ static final int singleExpBias = 127;
+ static final int singleMaxDecimalDigits = 7;
+ static final int singleMaxDecimalExponent = 38;
+ static final int singleMinDecimalExponent = -45;
+
+ static final int intDecimalDigits = 9;
+
+
+ /*
+ * count number of bits from high-order 1 bit to low-order 1 bit,
+ * inclusive.
+ */
+ private static int
+ countBits( long v ){
+ //
+ // the strategy is to shift until we get a non-zero sign bit
+ // then shift until we have no bits left, counting the difference.
+ // we do byte shifting as a hack. Hope it helps.
+ //
+ if ( v == 0L ) return 0;
+
+ while ( ( v & highbyte ) == 0L ){
+ v <<= 8;
+ }
+ while ( v > 0L ) { // i.e. while ((v&highbit) == 0L )
+ v <<= 1;
+ }
+
+ int n = 0;
+ while (( v & lowbytes ) != 0L ){
+ v <<= 8;
+ n += 8;
+ }
+ while ( v != 0L ){
+ v <<= 1;
+ n += 1;
+ }
+ return n;
+ }
+
+ /*
+ * Keep big powers of 5 handy for future reference.
+ */
+ private static FDBigInt b5p[];
+
+ private static synchronized FDBigInt
+ big5pow( int p ){
+ assert p >= 0 : p; // negative power of 5
+ if ( b5p == null ){
+ b5p = new FDBigInt[ p+1 ];
+ }else if (b5p.length <= p ){
+ FDBigInt t[] = new FDBigInt[ p+1 ];
+ System.arraycopy( b5p, 0, t, 0, b5p.length );
+ b5p = t;
+ }
+ if ( b5p[p] != null )
+ return b5p[p];
+ else if ( p < small5pow.length )
+ return b5p[p] = new FDBigInt( small5pow[p] );
+ else if ( p < long5pow.length )
+ return b5p[p] = new FDBigInt( long5pow[p] );
+ else {
+ // construct the value.
+ // recursively.
+ int q, r;
+ // in order to compute 5^p,
+ // compute its square root, 5^(p/2) and square.
+ // or, let q = p / 2, r = p -q, then
+ // 5^p = 5^(q+r) = 5^q * 5^r
+ q = p >> 1;
+ r = p - q;
+ FDBigInt bigq = b5p[q];
+ if ( bigq == null )
+ bigq = big5pow ( q );
+ if ( r < small5pow.length ){
+ return (b5p[p] = bigq.mult( small5pow[r] ) );
+ }else{
+ FDBigInt bigr = b5p[ r ];
+ if ( bigr == null )
+ bigr = big5pow( r );
+ return (b5p[p] = bigq.mult( bigr ) );
+ }
+ }
+ }
+
+ //
+ // a common operation
+ //
+ private static FDBigInt
+ multPow52( FDBigInt v, int p5, int p2 ){
+ if ( p5 != 0 ){
+ if ( p5 < small5pow.length ){
+ v = v.mult( small5pow[p5] );
+ } else {
+ v = v.mult( big5pow( p5 ) );
+ }
+ }
+ if ( p2 != 0 ){
+ v.lshiftMe( p2 );
+ }
+ return v;
+ }
+
+ //
+ // another common operation
+ //
+ private static FDBigInt
+ constructPow52( int p5, int p2 ){
+ FDBigInt v = new FDBigInt( big5pow( p5 ) );
+ if ( p2 != 0 ){
+ v.lshiftMe( p2 );
+ }
+ return v;
+ }
+
+ /*
+ * Make a floating double into a FDBigInt.
+ * This could also be structured as a FDBigInt
+ * constructor, but we'd have to build a lot of knowledge
+ * about floating-point representation into it, and we don't want to.
+ *
+ * AS A SIDE EFFECT, THIS METHOD WILL SET THE INSTANCE VARIABLES
+ * bigIntExp and bigIntNBits
+ *
+ */
+ private FDBigInt
+ doubleToBigInt( double dval ){
+ long lbits = Double.doubleToLongBits( dval ) & ~signMask;
+ int binexp = (int)(lbits >>> expShift);
+ lbits &= fractMask;
+ if ( binexp > 0 ){
+ lbits |= fractHOB;
+ } else {
+ assert lbits != 0L : lbits; // doubleToBigInt(0.0)
+ binexp +=1;
+ while ( (lbits & fractHOB ) == 0L){
+ lbits <<= 1;
+ binexp -= 1;
+ }
+ }
+ binexp -= expBias;
+ int nbits = countBits( lbits );
+ /*
+ * We now know where the high-order 1 bit is,
+ * and we know how many there are.
+ */
+ int lowOrderZeros = expShift+1-nbits;
+ lbits >>>= lowOrderZeros;
+
+ bigIntExp = binexp+1-nbits;
+ bigIntNBits = nbits;
+ return new FDBigInt( lbits );
+ }
+
+ /*
+ * Compute a number that is the ULP of the given value,
+ * for purposes of addition/subtraction. Generally easy.
+ * More difficult if subtracting and the argument
+ * is a normalized a power of 2, as the ULP changes at these points.
+ */
+ private static double
+ ulp( double dval, boolean subtracting ){
+ long lbits = Double.doubleToLongBits( dval ) & ~signMask;
+ int binexp = (int)(lbits >>> expShift);
+ double ulpval;
+ if ( subtracting && ( binexp >= expShift ) && ((lbits&fractMask) == 0L) ){
+ // for subtraction from normalized, powers of 2,
+ // use next-smaller exponent
+ binexp -= 1;
+ }
+ if ( binexp > expShift ){
+ ulpval = Double.longBitsToDouble( ((long)(binexp-expShift))<<expShift );
+ } else if ( binexp == 0 ){
+ ulpval = Double.MIN_VALUE;
+ } else {
+ ulpval = Double.longBitsToDouble( 1L<<(binexp-1) );
+ }
+ if ( subtracting ) ulpval = - ulpval;
+
+ return ulpval;
+ }
+
+ /*
+ * Round a double to a float.
+ * In addition to the fraction bits of the double,
+ * look at the class instance variable roundDir,
+ * which should help us avoid double-rounding error.
+ * roundDir was set in hardValueOf if the estimate was
+ * close enough, but not exact. It tells us which direction
+ * of rounding is preferred.
+ */
+ float
+ stickyRound( double dval ){
+ long lbits = Double.doubleToLongBits( dval );
+ long binexp = lbits & expMask;
+ if ( binexp == 0L || binexp == expMask ){
+ // what we have here is special.
+ // don't worry, the right thing will happen.
+ return (float) dval;
+ }
+ lbits += (long)roundDir; // hack-o-matic.
+ return (float)Double.longBitsToDouble( lbits );
+ }
+
+
+ /*
+ * This is the easy subcase --
+ * all the significant bits, after scaling, are held in lvalue.
+ * negSign and decExponent tell us what processing and scaling
+ * has already been done. Exceptional cases have already been
+ * stripped out.
+ * In particular:
+ * lvalue is a finite number (not Inf, nor NaN)
+ * lvalue > 0L (not zero, nor negative).
+ *
+ * The only reason that we develop the digits here, rather than
+ * calling on Long.toString() is that we can do it a little faster,
+ * and besides want to treat trailing 0s specially. If Long.toString
+ * changes, we should re-evaluate this strategy!
+ */
+ private void
+ developLongDigits( int decExponent, long lvalue, long insignificant ){
+ char digits[];
+ int ndigits;
+ int digitno;
+ int c;
+ //
+ // Discard non-significant low-order bits, while rounding,
+ // up to insignificant value.
+ int i;
+ for ( i = 0; insignificant >= 10L; i++ )
+ insignificant /= 10L;
+ if ( i != 0 ){
+ long pow10 = long5pow[i] << i; // 10^i == 5^i * 2^i;
+ long residue = lvalue % pow10;
+ lvalue /= pow10;
+ decExponent += i;
+ if ( residue >= (pow10>>1) ){
+ // round up based on the low-order bits we're discarding
+ lvalue++;
+ }
+ }
+ if ( lvalue <= Integer.MAX_VALUE ){
+ assert lvalue > 0L : lvalue; // lvalue <= 0
+ // even easier subcase!
+ // can do int arithmetic rather than long!
+ int ivalue = (int)lvalue;
+ ndigits = 10;
+ digits = (char[])(perThreadBuffer.get());
+ digitno = ndigits-1;
+ c = ivalue%10;
+ ivalue /= 10;
+ while ( c == 0 ){
+ decExponent++;
+ c = ivalue%10;
+ ivalue /= 10;
+ }
+ while ( ivalue != 0){
+ digits[digitno--] = (char)(c+'0');
+ decExponent++;
+ c = ivalue%10;
+ ivalue /= 10;
+ }
+ digits[digitno] = (char)(c+'0');
+ } else {
+ // same algorithm as above (same bugs, too )
+ // but using long arithmetic.
+ ndigits = 20;
+ digits = (char[])(perThreadBuffer.get());
+ digitno = ndigits-1;
+ c = (int)(lvalue%10L);
+ lvalue /= 10L;
+ while ( c == 0 ){
+ decExponent++;
+ c = (int)(lvalue%10L);
+ lvalue /= 10L;
+ }
+ while ( lvalue != 0L ){
+ digits[digitno--] = (char)(c+'0');
+ decExponent++;
+ c = (int)(lvalue%10L);
+ lvalue /= 10;
+ }
+ digits[digitno] = (char)(c+'0');
+ }
+ char result [];
+ ndigits -= digitno;
+ result = new char[ ndigits ];
+ System.arraycopy( digits, digitno, result, 0, ndigits );
+ this.digits = result;
+ this.decExponent = decExponent+1;
+ this.nDigits = ndigits;
+ }
+
+ //
+ // add one to the least significant digit.
+ // in the unlikely event there is a carry out,
+ // deal with it.
+ // assert that this will only happen where there
+ // is only one digit, e.g. (float)1e-44 seems to do it.
+ //
+ private void
+ roundup(){
+ int i;
+ int q = digits[ i = (nDigits-1)];
+ if ( q == '9' ){
+ while ( q == '9' && i > 0 ){
+ digits[i] = '0';
+ q = digits[--i];
+ }
+ if ( q == '9' ){
+ // carryout! High-order 1, rest 0s, larger exp.
+ decExponent += 1;
+ digits[0] = '1';
+ return;
+ }
+ // else fall through.
+ }
+ digits[i] = (char)(q+1);
+ }
+
+ /*
+ * FIRST IMPORTANT CONSTRUCTOR: DOUBLE
+ */
+ public FloatingDecimal( double d )
+ {
+ long dBits = Double.doubleToLongBits( d );
+ long fractBits;
+ int binExp;
+ int nSignificantBits;
+
+ // discover and delete sign
+ if ( (dBits&signMask) != 0 ){
+ isNegative = true;
+ dBits ^= signMask;
+ } else {
+ isNegative = false;
+ }
+ // Begin to unpack
+ // Discover obvious special cases of NaN and Infinity.
+ binExp = (int)( (dBits&expMask) >> expShift );
+ fractBits = dBits&fractMask;
+ if ( binExp == (int)(expMask>>expShift) ) {
+ isExceptional = true;
+ if ( fractBits == 0L ){
+ digits = infinity;
+ } else {
+ digits = notANumber;
+ isNegative = false; // NaN has no sign!
+ }
+ nDigits = digits.length;
+ return;
+ }
+ isExceptional = false;
+ // Finish unpacking
+ // Normalize denormalized numbers.
+ // Insert assumed high-order bit for normalized numbers.
+ // Subtract exponent bias.
+ if ( binExp == 0 ){
+ if ( fractBits == 0L ){
+ // not a denorm, just a 0!
+ decExponent = 0;
+ digits = zero;
+ nDigits = 1;
+ return;
+ }
+ while ( (fractBits&fractHOB) == 0L ){
+ fractBits <<= 1;
+ binExp -= 1;
+ }
+ nSignificantBits = expShift + binExp +1; // recall binExp is - shift count.
+ binExp += 1;
+ } else {
+ fractBits |= fractHOB;
+ nSignificantBits = expShift+1;
+ }
+ binExp -= expBias;
+ // call the routine that actually does all the hard work.
+ dtoa( binExp, fractBits, nSignificantBits );
+ }
+
+ /*
+ * SECOND IMPORTANT CONSTRUCTOR: SINGLE
+ */
+ public FloatingDecimal( float f )
+ {
+ int fBits = Float.floatToIntBits( f );
+ int fractBits;
+ int binExp;
+ int nSignificantBits;
+
+ // discover and delete sign
+ if ( (fBits&singleSignMask) != 0 ){
+ isNegative = true;
+ fBits ^= singleSignMask;
+ } else {
+ isNegative = false;
+ }
+ // Begin to unpack
+ // Discover obvious special cases of NaN and Infinity.
+ binExp = (int)( (fBits&singleExpMask) >> singleExpShift );
+ fractBits = fBits&singleFractMask;
+ if ( binExp == (int)(singleExpMask>>singleExpShift) ) {
+ isExceptional = true;
+ if ( fractBits == 0L ){
+ digits = infinity;
+ } else {
+ digits = notANumber;
+ isNegative = false; // NaN has no sign!
+ }
+ nDigits = digits.length;
+ return;
+ }
+ isExceptional = false;
+ // Finish unpacking
+ // Normalize denormalized numbers.
+ // Insert assumed high-order bit for normalized numbers.
+ // Subtract exponent bias.
+ if ( binExp == 0 ){
+ if ( fractBits == 0 ){
+ // not a denorm, just a 0!
+ decExponent = 0;
+ digits = zero;
+ nDigits = 1;
+ return;
+ }
+ while ( (fractBits&singleFractHOB) == 0 ){
+ fractBits <<= 1;
+ binExp -= 1;
+ }
+ nSignificantBits = singleExpShift + binExp +1; // recall binExp is - shift count.
+ binExp += 1;
+ } else {
+ fractBits |= singleFractHOB;
+ nSignificantBits = singleExpShift+1;
+ }
+ binExp -= singleExpBias;
+ // call the routine that actually does all the hard work.
+ dtoa( binExp, ((long)fractBits)<<(expShift-singleExpShift), nSignificantBits );
+ }
+
+ private void
+ dtoa( int binExp, long fractBits, int nSignificantBits )
+ {
+ int nFractBits; // number of significant bits of fractBits;
+ int nTinyBits; // number of these to the right of the point.
+ int decExp;
+
+ // Examine number. Determine if it is an easy case,
+ // which we can do pretty trivially using float/long conversion,
+ // or whether we must do real work.
+ nFractBits = countBits( fractBits );
+ nTinyBits = Math.max( 0, nFractBits - binExp - 1 );
+ if ( binExp <= maxSmallBinExp && binExp >= minSmallBinExp ){
+ // Look more closely at the number to decide if,
+ // with scaling by 10^nTinyBits, the result will fit in
+ // a long.
+ if ( (nTinyBits < long5pow.length) && ((nFractBits + n5bits[nTinyBits]) < 64 ) ){
+ /*
+ * We can do this:
+ * take the fraction bits, which are normalized.
+ * (a) nTinyBits == 0: Shift left or right appropriately
+ * to align the binary point at the extreme right, i.e.
+ * where a long int point is expected to be. The integer
+ * result is easily converted to a string.
+ * (b) nTinyBits > 0: Shift right by expShift-nFractBits,
+ * which effectively converts to long and scales by
+ * 2^nTinyBits. Then multiply by 5^nTinyBits to
+ * complete the scaling. We know this won't overflow
+ * because we just counted the number of bits necessary
+ * in the result. The integer you get from this can
+ * then be converted to a string pretty easily.
+ */
+ long halfULP;
+ if ( nTinyBits == 0 ) {
+ if ( binExp > nSignificantBits ){
+ halfULP = 1L << ( binExp-nSignificantBits-1);
+ } else {
+ halfULP = 0L;
+ }
+ if ( binExp >= expShift ){
+ fractBits <<= (binExp-expShift);
+ } else {
+ fractBits >>>= (expShift-binExp) ;
+ }
+ developLongDigits( 0, fractBits, halfULP );
+ return;
+ }
+ /*
+ * The following causes excess digits to be printed
+ * out in the single-float case. Our manipulation of
+ * halfULP here is apparently not correct. If we
+ * better understand how this works, perhaps we can
+ * use this special case again. But for the time being,
+ * we do not.
+ * else {
+ * fractBits >>>= expShift+1-nFractBits;
+ * fractBits *= long5pow[ nTinyBits ];
+ * halfULP = long5pow[ nTinyBits ] >> (1+nSignificantBits-nFractBits);
+ * developLongDigits( -nTinyBits, fractBits, halfULP );
+ * return;
+ * }
+ */
+ }
+ }
+ /*
+ * This is the hard case. We are going to compute large positive
+ * integers B and S and integer decExp, s.t.
+ * d = ( B / S ) * 10^decExp
+ * 1 <= B / S < 10
+ * Obvious choices are:
+ * decExp = floor( log10(d) )
+ * B = d * 2^nTinyBits * 10^max( 0, -decExp )
+ * S = 10^max( 0, decExp) * 2^nTinyBits
+ * (noting that nTinyBits has already been forced to non-negative)
+ * I am also going to compute a large positive integer
+ * M = (1/2^nSignificantBits) * 2^nTinyBits * 10^max( 0, -decExp )
+ * i.e. M is (1/2) of the ULP of d, scaled like B.
+ * When we iterate through dividing B/S and picking off the
+ * quotient bits, we will know when to stop when the remainder
+ * is <= M.
+ *
+ * We keep track of powers of 2 and powers of 5.
+ */
+
+ /*
+ * Estimate decimal exponent. (If it is small-ish,
+ * we could double-check.)
+ *
+ * First, scale the mantissa bits such that 1 <= d2 < 2.
+ * We are then going to estimate
+ * log10(d2) ~=~ (d2-1.5)/1.5 + log(1.5)
+ * and so we can estimate
+ * log10(d) ~=~ log10(d2) + binExp * log10(2)
+ * take the floor and call it decExp.
+ * FIXME -- use more precise constants here. It costs no more.
+ */
+ double d2 = Double.longBitsToDouble(
+ expOne | ( fractBits &~ fractHOB ) );
+ decExp = (int)Math.floor(
+ (d2-1.5D)*0.289529654D + 0.176091259 + (double)binExp * 0.301029995663981 );
+ int B2, B5; // powers of 2 and powers of 5, respectively, in B
+ int S2, S5; // powers of 2 and powers of 5, respectively, in S
+ int M2, M5; // powers of 2 and powers of 5, respectively, in M
+ int Bbits; // binary digits needed to represent B, approx.
+ int tenSbits; // binary digits needed to represent 10*S, approx.
+ FDBigInt Sval, Bval, Mval;
+
+ B5 = Math.max( 0, -decExp );
+ B2 = B5 + nTinyBits + binExp;
+
+ S5 = Math.max( 0, decExp );
+ S2 = S5 + nTinyBits;
+
+ M5 = B5;
+ M2 = B2 - nSignificantBits;
+
+ /*
+ * the long integer fractBits contains the (nFractBits) interesting
+ * bits from the mantissa of d ( hidden 1 added if necessary) followed
+ * by (expShift+1-nFractBits) zeros. In the interest of compactness,
+ * I will shift out those zeros before turning fractBits into a
+ * FDBigInt. The resulting whole number will be
+ * d * 2^(nFractBits-1-binExp).
+ */
+ fractBits >>>= (expShift+1-nFractBits);
+ B2 -= nFractBits-1;
+ int common2factor = Math.min( B2, S2 );
+ B2 -= common2factor;
+ S2 -= common2factor;
+ M2 -= common2factor;
+
+ /*
+ * HACK!! For exact powers of two, the next smallest number
+ * is only half as far away as we think (because the meaning of
+ * ULP changes at power-of-two bounds) for this reason, we
+ * hack M2. Hope this works.
+ */
+ if ( nFractBits == 1 )
+ M2 -= 1;
+
+ if ( M2 < 0 ){
+ // oops.
+ // since we cannot scale M down far enough,
+ // we must scale the other values up.
+ B2 -= M2;
+ S2 -= M2;
+ M2 = 0;
+ }
+ /*
+ * Construct, Scale, iterate.
+ * Some day, we'll write a stopping test that takes
+ * account of the asymmetry of the spacing of floating-point
+ * numbers below perfect powers of 2
+ * 26 Sept 96 is not that day.
+ * So we use a symmetric test.
+ */
+ char digits[] = this.digits = new char[18];
+ int ndigit = 0;
+ boolean low, high;
+ long lowDigitDifference;
+ int q;
+
+ /*
+ * Detect the special cases where all the numbers we are about
+ * to compute will fit in int or long integers.
+ * In these cases, we will avoid doing FDBigInt arithmetic.
+ * We use the same algorithms, except that we "normalize"
+ * our FDBigInts before iterating. This is to make division easier,
+ * as it makes our fist guess (quotient of high-order words)
+ * more accurate!
+ *
+ * Some day, we'll write a stopping test that takes
+ * account of the asymmetry of the spacing of floating-point
+ * numbers below perfect powers of 2
+ * 26 Sept 96 is not that day.
+ * So we use a symmetric test.
+ */
+ Bbits = nFractBits + B2 + (( B5 < n5bits.length )? n5bits[B5] : ( B5*3 ));
+ tenSbits = S2+1 + (( (S5+1) < n5bits.length )? n5bits[(S5+1)] : ( (S5+1)*3 ));
+ if ( Bbits < 64 && tenSbits < 64){
+ if ( Bbits < 32 && tenSbits < 32){
+ // wa-hoo! They're all ints!
+ int b = ((int)fractBits * small5pow[B5] ) << B2;
+ int s = small5pow[S5] << S2;
+ int m = small5pow[M5] << M2;
+ int tens = s * 10;
+ /*
+ * Unroll the first iteration. If our decExp estimate
+ * was too high, our first quotient will be zero. In this
+ * case, we discard it and decrement decExp.
+ */
+ ndigit = 0;
+ q = (int) ( b / s );
+ b = 10 * ( b % s );
+ m *= 10;
+ low = (b < m );
+ high = (b+m > tens );
+ assert q < 10 : q; // excessively large digit
+ if ( (q == 0) && ! high ){
+ // oops. Usually ignore leading zero.
+ decExp--;
+ } else {
+ digits[ndigit++] = (char)('0' + q);
+ }
+ /*
+ * HACK! Java spec sez that we always have at least
+ * one digit after the . in either F- or E-form output.
+ * Thus we will need more than one digit if we're using
+ * E-form
+ */
+ if ( decExp <= -3 || decExp >= 8 ){
+ high = low = false;
+ }
+ while( ! low && ! high ){
+ q = (int) ( b / s );
+ b = 10 * ( b % s );
+ m *= 10;
+ assert q < 10 : q; // excessively large digit
+ if ( m > 0L ){
+ low = (b < m );
+ high = (b+m > tens );
+ } else {
+ // hack -- m might overflow!
+ // in this case, it is certainly > b,
+ // which won't
+ // and b+m > tens, too, since that has overflowed
+ // either!
+ low = true;
+ high = true;
+ }
+ digits[ndigit++] = (char)('0' + q);
+ }
+ lowDigitDifference = (b<<1) - tens;
+ } else {
+ // still good! they're all longs!
+ long b = (fractBits * long5pow[B5] ) << B2;
+ long s = long5pow[S5] << S2;
+ long m = long5pow[M5] << M2;
+ long tens = s * 10L;
+ /*
+ * Unroll the first iteration. If our decExp estimate
+ * was too high, our first quotient will be zero. In this
+ * case, we discard it and decrement decExp.
+ */
+ ndigit = 0;
+ q = (int) ( b / s );
+ b = 10L * ( b % s );
+ m *= 10L;
+ low = (b < m );
+ high = (b+m > tens );
+ assert q < 10 : q; // excessively large digit
+ if ( (q == 0) && ! high ){
+ // oops. Usually ignore leading zero.
+ decExp--;
+ } else {
+ digits[ndigit++] = (char)('0' + q);
+ }
+ /*
+ * HACK! Java spec sez that we always have at least
+ * one digit after the . in either F- or E-form output.
+ * Thus we will need more than one digit if we're using
+ * E-form
+ */
+ if ( decExp <= -3 || decExp >= 8 ){
+ high = low = false;
+ }
+ while( ! low && ! high ){
+ q = (int) ( b / s );
+ b = 10 * ( b % s );
+ m *= 10;
+ assert q < 10 : q; // excessively large digit
+ if ( m > 0L ){
+ low = (b < m );
+ high = (b+m > tens );
+ } else {
+ // hack -- m might overflow!
+ // in this case, it is certainly > b,
+ // which won't
+ // and b+m > tens, too, since that has overflowed
+ // either!
+ low = true;
+ high = true;
+ }
+ digits[ndigit++] = (char)('0' + q);
+ }
+ lowDigitDifference = (b<<1) - tens;
+ }
+ } else {
+ FDBigInt tenSval;
+ int shiftBias;
+
+ /*
+ * We really must do FDBigInt arithmetic.
+ * Fist, construct our FDBigInt initial values.
+ */
+ Bval = multPow52( new FDBigInt( fractBits ), B5, B2 );
+ Sval = constructPow52( S5, S2 );
+ Mval = constructPow52( M5, M2 );
+
+
+ // normalize so that division works better
+ Bval.lshiftMe( shiftBias = Sval.normalizeMe() );
+ Mval.lshiftMe( shiftBias );
+ tenSval = Sval.mult( 10 );
+ /*
+ * Unroll the first iteration. If our decExp estimate
+ * was too high, our first quotient will be zero. In this
+ * case, we discard it and decrement decExp.
+ */
+ ndigit = 0;
+ q = Bval.quoRemIteration( Sval );
+ Mval = Mval.mult( 10 );
+ low = (Bval.cmp( Mval ) < 0);
+ high = (Bval.add( Mval ).cmp( tenSval ) > 0 );
+ assert q < 10 : q; // excessively large digit
+ if ( (q == 0) && ! high ){
+ // oops. Usually ignore leading zero.
+ decExp--;
+ } else {
+ digits[ndigit++] = (char)('0' + q);
+ }
+ /*
+ * HACK! Java spec sez that we always have at least
+ * one digit after the . in either F- or E-form output.
+ * Thus we will need more than one digit if we're using
+ * E-form
+ */
+ if ( decExp <= -3 || decExp >= 8 ){
+ high = low = false;
+ }
+ while( ! low && ! high ){
+ q = Bval.quoRemIteration( Sval );
+ Mval = Mval.mult( 10 );
+ assert q < 10 : q; // excessively large digit
+ low = (Bval.cmp( Mval ) < 0);
+ high = (Bval.add( Mval ).cmp( tenSval ) > 0 );
+ digits[ndigit++] = (char)('0' + q);
+ }
+ if ( high && low ){
+ Bval.lshiftMe(1);
+ lowDigitDifference = Bval.cmp(tenSval);
+ } else
+ lowDigitDifference = 0L; // this here only for flow analysis!
+ }
+ this.decExponent = decExp+1;
+ this.digits = digits;
+ this.nDigits = ndigit;
+ /*
+ * Last digit gets rounded based on stopping condition.
+ */
+ if ( high ){
+ if ( low ){
+ if ( lowDigitDifference == 0L ){
+ // it's a tie!
+ // choose based on which digits we like.
+ if ( (digits[nDigits-1]&1) != 0 ) roundup();
+ } else if ( lowDigitDifference > 0 ){
+ roundup();
+ }
+ } else {
+ roundup();
+ }
+ }
+ }
+
+ public String
+ toString(){
+ // most brain-dead version
+ StringBuffer result = new StringBuffer( nDigits+8 );
+ if ( isNegative ){ result.append( '-' ); }
+ if ( isExceptional ){
+ result.append( digits, 0, nDigits );
+ } else {
+ result.append( "0.");
+ result.append( digits, 0, nDigits );
+ result.append('e');
+ result.append( decExponent );
+ }
+ return new String(result);
+ }
+
+ public String toJavaFormatString() {
+ char result[] = (char[])(perThreadBuffer.get());
+ int i = getChars(result);
+ return new String(result, 0, i);
+ }
+
+ private int getChars(char[] result) {
+ assert nDigits <= 19 : nDigits; // generous bound on size of nDigits
+ int i = 0;
+ if (isNegative) { result[0] = '-'; i = 1; }
+ if (isExceptional) {
+ System.arraycopy(digits, 0, result, i, nDigits);
+ i += nDigits;
+ } else {
+ if (decExponent > 0 && decExponent < 8) {
+ // print digits.digits.
+ int charLength = Math.min(nDigits, decExponent);
+ System.arraycopy(digits, 0, result, i, charLength);
+ i += charLength;
+ if (charLength < decExponent) {
+ charLength = decExponent-charLength;
+ System.arraycopy(zero, 0, result, i, charLength);
+ i += charLength;
+ result[i++] = '.';
+ result[i++] = '0';
+ } else {
+ result[i++] = '.';
+ if (charLength < nDigits) {
+ int t = nDigits - charLength;
+ System.arraycopy(digits, charLength, result, i, t);
+ i += t;
+ } else {
+ result[i++] = '0';
+ }
+ }
+ } else if (decExponent <=0 && decExponent > -3) {
+ result[i++] = '0';
+ result[i++] = '.';
+ if (decExponent != 0) {
+ System.arraycopy(zero, 0, result, i, -decExponent);
+ i -= decExponent;
+ }
+ System.arraycopy(digits, 0, result, i, nDigits);
+ i += nDigits;
+ } else {
+ result[i++] = digits[0];
+ result[i++] = '.';
+ if (nDigits > 1) {
+ System.arraycopy(digits, 1, result, i, nDigits-1);
+ i += nDigits-1;
+ } else {
+ result[i++] = '0';
+ }
+ result[i++] = 'E';
+ int e;
+ if (decExponent <= 0) {
+ result[i++] = '-';
+ e = -decExponent+1;
+ } else {
+ e = decExponent-1;
+ }
+ // decExponent has 1, 2, or 3, digits
+ if (e <= 9) {
+ result[i++] = (char)(e+'0');
+ } else if (e <= 99) {
+ result[i++] = (char)(e/10 +'0');
+ result[i++] = (char)(e%10 + '0');
+ } else {
+ result[i++] = (char)(e/100+'0');
+ e %= 100;
+ result[i++] = (char)(e/10+'0');
+ result[i++] = (char)(e%10 + '0');
+ }
+ }
+ }
+ return i;
+ }
+
+ // Per-thread buffer for string/stringbuffer conversion
+ private static ThreadLocal perThreadBuffer = new ThreadLocal() {
+ protected synchronized Object initialValue() {
+ return new char[26];
+ }
+ };
+
+ public void appendTo(Appendable buf) {
+ char result[] = (char[])(perThreadBuffer.get());
+ int i = getChars(result);
+ if (buf instanceof StringBuilder)
+ ((StringBuilder) buf).append(result, 0, i);
+ else if (buf instanceof StringBuffer)
+ ((StringBuffer) buf).append(result, 0, i);
+ else
+ assert false;
+ }
+
+ public static FloatingDecimal
+ readJavaFormatString( String in ) throws NumberFormatException {
+ boolean isNegative = false;
+ boolean signSeen = false;
+ int decExp;
+ char c;
+
+ parseNumber:
+ try{
+ in = in.trim(); // don't fool around with white space.
+ // throws NullPointerException if null
+ int l = in.length();
+ if ( l == 0 ) throw new NumberFormatException("empty String");
+ int i = 0;
+ switch ( c = in.charAt( i ) ){
+ case '-':
+ isNegative = true;
+ //FALLTHROUGH
+ case '+':
+ i++;
+ signSeen = true;
+ }
+
+ // Check for NaN and Infinity strings
+ c = in.charAt(i);
+ if(c == 'N' || c == 'I') { // possible NaN or infinity
+ boolean potentialNaN = false;
+ char targetChars[] = null; // char array of "NaN" or "Infinity"
+
+ if(c == 'N') {
+ targetChars = notANumber;
+ potentialNaN = true;
+ } else {
+ targetChars = infinity;
+ }
+
+ // compare Input string to "NaN" or "Infinity"
+ int j = 0;
+ while(i < l && j < targetChars.length) {
+ if(in.charAt(i) == targetChars[j]) {
+ i++; j++;
+ }
+ else // something is amiss, throw exception
+ break parseNumber;
+ }
+
+ // For the candidate string to be a NaN or infinity,
+ // all characters in input string and target char[]
+ // must be matched ==> j must equal targetChars.length
+ // and i must equal l
+ if( (j == targetChars.length) && (i == l) ) { // return NaN or infinity
+ return (potentialNaN ? new FloatingDecimal(Double.NaN) // NaN has no sign
+ : new FloatingDecimal(isNegative?
+ Double.NEGATIVE_INFINITY:
+ Double.POSITIVE_INFINITY)) ;
+ }
+ else { // something went wrong, throw exception
+ break parseNumber;
+ }
+
+ } else if (c == '0') { // check for hexadecimal floating-point number
+ if (l > i+1 ) {
+ char ch = in.charAt(i+1);
+ if (ch == 'x' || ch == 'X' ) // possible hex string
+ return parseHexString(in);
+ }
+ } // look for and process decimal floating-point string
+
+ char[] digits = new char[ l ];
+ int nDigits= 0;
+ boolean decSeen = false;
+ int decPt = 0;
+ int nLeadZero = 0;
+ int nTrailZero= 0;
+ digitLoop:
+ while ( i < l ){
+ switch ( c = in.charAt( i ) ){
+ case '0':
+ if ( nDigits > 0 ){
+ nTrailZero += 1;
+ } else {
+ nLeadZero += 1;
+ }
+ break; // out of switch.
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ while ( nTrailZero > 0 ){
+ digits[nDigits++] = '0';
+ nTrailZero -= 1;
+ }
+ digits[nDigits++] = c;
+ break; // out of switch.
+ case '.':
+ if ( decSeen ){
+ // already saw one ., this is the 2nd.
+ throw new NumberFormatException("multiple points");
+ }
+ decPt = i;
+ if ( signSeen ){
+ decPt -= 1;
+ }
+ decSeen = true;
+ break; // out of switch.
+ default:
+ break digitLoop;
+ }
+ i++;
+ }
+ /*
+ * At this point, we've scanned all the digits and decimal
+ * point we're going to see. Trim off leading and trailing
+ * zeros, which will just confuse us later, and adjust
+ * our initial decimal exponent accordingly.
+ * To review:
+ * we have seen i total characters.
+ * nLeadZero of them were zeros before any other digits.
+ * nTrailZero of them were zeros after any other digits.
+ * if ( decSeen ), then a . was seen after decPt characters
+ * ( including leading zeros which have been discarded )
+ * nDigits characters were neither lead nor trailing
+ * zeros, nor point
+ */
+ /*
+ * special hack: if we saw no non-zero digits, then the
+ * answer is zero!
+ * Unfortunately, we feel honor-bound to keep parsing!
+ */
+ if ( nDigits == 0 ){
+ digits = zero;
+ nDigits = 1;
+ if ( nLeadZero == 0 ){
+ // we saw NO DIGITS AT ALL,
+ // not even a crummy 0!
+ // this is not allowed.
+ break parseNumber; // go throw exception
+ }
+
+ }
+
+ /* Our initial exponent is decPt, adjusted by the number of
+ * discarded zeros. Or, if there was no decPt,
+ * then its just nDigits adjusted by discarded trailing zeros.
+ */
+ if ( decSeen ){
+ decExp = decPt - nLeadZero;
+ } else {
+ decExp = nDigits+nTrailZero;
+ }
+
+ /*
+ * Look for 'e' or 'E' and an optionally signed integer.
+ */
+ if ( (i < l) && (((c = in.charAt(i) )=='e') || (c == 'E') ) ){
+ int expSign = 1;
+ int expVal = 0;
+ int reallyBig = Integer.MAX_VALUE / 10;
+ boolean expOverflow = false;
+ switch( in.charAt(++i) ){
+ case '-':
+ expSign = -1;
+ //FALLTHROUGH
+ case '+':
+ i++;
+ }
+ int expAt = i;
+ expLoop:
+ while ( i < l ){
+ if ( expVal >= reallyBig ){
+ // the next character will cause integer
+ // overflow.
+ expOverflow = true;
+ }
+ switch ( c = in.charAt(i++) ){
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ expVal = expVal*10 + ( (int)c - (int)'0' );
+ continue;
+ default:
+ i--; // back up.
+ break expLoop; // stop parsing exponent.
+ }
+ }
+ int expLimit = bigDecimalExponent+nDigits+nTrailZero;
+ if ( expOverflow || ( expVal > expLimit ) ){
+ //
+ // The intent here is to end up with
+ // infinity or zero, as appropriate.
+ // The reason for yielding such a small decExponent,
+ // rather than something intuitive such as
+ // expSign*Integer.MAX_VALUE, is that this value
+ // is subject to further manipulation in
+ // doubleValue() and floatValue(), and I don't want
+ // it to be able to cause overflow there!
+ // (The only way we can get into trouble here is for
+ // really outrageous nDigits+nTrailZero, such as 2 billion. )
+ //
+ decExp = expSign*expLimit;
+ } else {
+ // this should not overflow, since we tested
+ // for expVal > (MAX+N), where N >= abs(decExp)
+ decExp = decExp + expSign*expVal;
+ }
+
+ // if we saw something not a digit ( or end of string )
+ // after the [Ee][+-], without seeing any digits at all
+ // this is certainly an error. If we saw some digits,
+ // but then some trailing garbage, that might be ok.
+ // so we just fall through in that case.
+ // HUMBUG
+ if ( i == expAt )
+ break parseNumber; // certainly bad
+ }
+ /*
+ * We parsed everything we could.
+ * If there are leftovers, then this is not good input!
+ */
+ if ( i < l &&
+ ((i != l - 1) ||
+ (in.charAt(i) != 'f' &&
+ in.charAt(i) != 'F' &&
+ in.charAt(i) != 'd' &&
+ in.charAt(i) != 'D'))) {
+ break parseNumber; // go throw exception
+ }
+
+ return new FloatingDecimal( isNegative, decExp, digits, nDigits, false );
+ } catch ( StringIndexOutOfBoundsException e ){ }
+ throw new NumberFormatException("For input string: \"" + in + "\"");
+ }
+
+ /*
+ * Take a FloatingDecimal, which we presumably just scanned in,
+ * and find out what its value is, as a double.
+ *
+ * AS A SIDE EFFECT, SET roundDir TO INDICATE PREFERRED
+ * ROUNDING DIRECTION in case the result is really destined
+ * for a single-precision float.
+ */
+
+ public double
+ doubleValue(){
+ int kDigits = Math.min( nDigits, maxDecimalDigits+1 );
+ long lValue;
+ double dValue;
+ double rValue, tValue;
+
+ // First, check for NaN and Infinity values
+ if(digits == infinity || digits == notANumber) {
+ if(digits == notANumber)
+ return Double.NaN;
+ else
+ return (isNegative?Double.NEGATIVE_INFINITY:Double.POSITIVE_INFINITY);
+ }
+ else {
+ if (mustSetRoundDir) {
+ roundDir = 0;
+ }
+ /*
+ * convert the lead kDigits to a long integer.
+ */
+ // (special performance hack: start to do it using int)
+ int iValue = (int)digits[0]-(int)'0';
+ int iDigits = Math.min( kDigits, intDecimalDigits );
+ for ( int i=1; i < iDigits; i++ ){
+ iValue = iValue*10 + (int)digits[i]-(int)'0';
+ }
+ lValue = (long)iValue;
+ for ( int i=iDigits; i < kDigits; i++ ){
+ lValue = lValue*10L + (long)((int)digits[i]-(int)'0');
+ }
+ dValue = (double)lValue;
+ int exp = decExponent-kDigits;
+ /*
+ * lValue now contains a long integer with the value of
+ * the first kDigits digits of the number.
+ * dValue contains the (double) of the same.
+ */
+
+ if ( nDigits <= maxDecimalDigits ){
+ /*
+ * possibly an easy case.
+ * We know that the digits can be represented
+ * exactly. And if the exponent isn't too outrageous,
+ * the whole thing can be done with one operation,
+ * thus one rounding error.
+ * Note that all our constructors trim all leading and
+ * trailing zeros, so simple values (including zero)
+ * will always end up here
+ */
+ if (exp == 0 || dValue == 0.0)
+ return (isNegative)? -dValue : dValue; // small floating integer
+ else if ( exp >= 0 ){
+ if ( exp <= maxSmallTen ){
+ /*
+ * Can get the answer with one operation,
+ * thus one roundoff.
+ */
+ rValue = dValue * small10pow[exp];
+ if ( mustSetRoundDir ){
+ tValue = rValue / small10pow[exp];
+ roundDir = ( tValue == dValue ) ? 0
+ :( tValue < dValue ) ? 1
+ : -1;
+ }
+ return (isNegative)? -rValue : rValue;
+ }
+ int slop = maxDecimalDigits - kDigits;
+ if ( exp <= maxSmallTen+slop ){
+ /*
+ * We can multiply dValue by 10^(slop)
+ * and it is still "small" and exact.
+ * Then we can multiply by 10^(exp-slop)
+ * with one rounding.
+ */
+ dValue *= small10pow[slop];
+ rValue = dValue * small10pow[exp-slop];
+
+ if ( mustSetRoundDir ){
+ tValue = rValue / small10pow[exp-slop];
+ roundDir = ( tValue == dValue ) ? 0
+ :( tValue < dValue ) ? 1
+ : -1;
+ }
+ return (isNegative)? -rValue : rValue;
+ }
+ /*
+ * Else we have a hard case with a positive exp.
+ */
+ } else {
+ if ( exp >= -maxSmallTen ){
+ /*
+ * Can get the answer in one division.
+ */
+ rValue = dValue / small10pow[-exp];
+ tValue = rValue * small10pow[-exp];
+ if ( mustSetRoundDir ){
+ roundDir = ( tValue == dValue ) ? 0
+ :( tValue < dValue ) ? 1
+ : -1;
+ }
+ return (isNegative)? -rValue : rValue;
+ }
+ /*
+ * Else we have a hard case with a negative exp.
+ */
+ }
+ }
+
+ /*
+ * Harder cases:
+ * The sum of digits plus exponent is greater than
+ * what we think we can do with one error.
+ *
+ * Start by approximating the right answer by,
+ * naively, scaling by powers of 10.
+ */
+ if ( exp > 0 ){
+ if ( decExponent > maxDecimalExponent+1 ){
+ /*
+ * Lets face it. This is going to be
+ * Infinity. Cut to the chase.
+ */
+ return (isNegative)? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
+ }
+ if ( (exp&15) != 0 ){
+ dValue *= small10pow[exp&15];
+ }
+ if ( (exp>>=4) != 0 ){
+ int j;
+ for( j = 0; exp > 1; j++, exp>>=1 ){
+ if ( (exp&1)!=0)
+ dValue *= big10pow[j];
+ }
+ /*
+ * The reason for the weird exp > 1 condition
+ * in the above loop was so that the last multiply
+ * would get unrolled. We handle it here.
+ * It could overflow.
+ */
+ double t = dValue * big10pow[j];
+ if ( Double.isInfinite( t ) ){
+ /*
+ * It did overflow.
+ * Look more closely at the result.
+ * If the exponent is just one too large,
+ * then use the maximum finite as our estimate
+ * value. Else call the result infinity
+ * and punt it.
+ * ( I presume this could happen because
+ * rounding forces the result here to be
+ * an ULP or two larger than
+ * Double.MAX_VALUE ).
+ */
+ t = dValue / 2.0;
+ t *= big10pow[j];
+ if ( Double.isInfinite( t ) ){
+ return (isNegative)? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
+ }
+ t = Double.MAX_VALUE;
+ }
+ dValue = t;
+ }
+ } else if ( exp < 0 ){
+ exp = -exp;
+ if ( decExponent < minDecimalExponent-1 ){
+ /*
+ * Lets face it. This is going to be
+ * zero. Cut to the chase.
+ */
+ return (isNegative)? -0.0 : 0.0;
+ }
+ if ( (exp&15) != 0 ){
+ dValue /= small10pow[exp&15];
+ }
+ if ( (exp>>=4) != 0 ){
+ int j;
+ for( j = 0; exp > 1; j++, exp>>=1 ){
+ if ( (exp&1)!=0)
+ dValue *= tiny10pow[j];
+ }
+ /*
+ * The reason for the weird exp > 1 condition
+ * in the above loop was so that the last multiply
+ * would get unrolled. We handle it here.
+ * It could underflow.
+ */
+ double t = dValue * tiny10pow[j];
+ if ( t == 0.0 ){
+ /*
+ * It did underflow.
+ * Look more closely at the result.
+ * If the exponent is just one too small,
+ * then use the minimum finite as our estimate
+ * value. Else call the result 0.0
+ * and punt it.
+ * ( I presume this could happen because
+ * rounding forces the result here to be
+ * an ULP or two less than
+ * Double.MIN_VALUE ).
+ */
+ t = dValue * 2.0;
+ t *= tiny10pow[j];
+ if ( t == 0.0 ){
+ return (isNegative)? -0.0 : 0.0;
+ }
+ t = Double.MIN_VALUE;
+ }
+ dValue = t;
+ }
+ }
+
+ /*
+ * dValue is now approximately the result.
+ * The hard part is adjusting it, by comparison
+ * with FDBigInt arithmetic.
+ * Formulate the EXACT big-number result as
+ * bigD0 * 10^exp
+ */
+ FDBigInt bigD0 = new FDBigInt( lValue, digits, kDigits, nDigits );
+ exp = decExponent - nDigits;
+
+ correctionLoop:
+ while(true){
+ /* AS A SIDE EFFECT, THIS METHOD WILL SET THE INSTANCE VARIABLES
+ * bigIntExp and bigIntNBits
+ */
+ FDBigInt bigB = doubleToBigInt( dValue );
+
+ /*
+ * Scale bigD, bigB appropriately for
+ * big-integer operations.
+ * Naively, we multiply by powers of ten
+ * and powers of two. What we actually do
+ * is keep track of the powers of 5 and
+ * powers of 2 we would use, then factor out
+ * common divisors before doing the work.
+ */
+ int B2, B5; // powers of 2, 5 in bigB
+ int D2, D5; // powers of 2, 5 in bigD
+ int Ulp2; // powers of 2 in halfUlp.
+ if ( exp >= 0 ){
+ B2 = B5 = 0;
+ D2 = D5 = exp;
+ } else {
+ B2 = B5 = -exp;
+ D2 = D5 = 0;
+ }
+ if ( bigIntExp >= 0 ){
+ B2 += bigIntExp;
+ } else {
+ D2 -= bigIntExp;
+ }
+ Ulp2 = B2;
+ // shift bigB and bigD left by a number s. t.
+ // halfUlp is still an integer.
+ int hulpbias;
+ if ( bigIntExp+bigIntNBits <= -expBias+1 ){
+ // This is going to be a denormalized number
+ // (if not actually zero).
+ // half an ULP is at 2^-(expBias+expShift+1)
+ hulpbias = bigIntExp+ expBias + expShift;
+ } else {
+ hulpbias = expShift + 2 - bigIntNBits;
+ }
+ B2 += hulpbias;
+ D2 += hulpbias;
+ // if there are common factors of 2, we might just as well
+ // factor them out, as they add nothing useful.
+ int common2 = Math.min( B2, Math.min( D2, Ulp2 ) );
+ B2 -= common2;
+ D2 -= common2;
+ Ulp2 -= common2;
+ // do multiplications by powers of 5 and 2
+ bigB = multPow52( bigB, B5, B2 );
+ FDBigInt bigD = multPow52( new FDBigInt( bigD0 ), D5, D2 );
+ //
+ // to recap:
+ // bigB is the scaled-big-int version of our floating-point
+ // candidate.
+ // bigD is the scaled-big-int version of the exact value
+ // as we understand it.
+ // halfUlp is 1/2 an ulp of bigB, except for special cases
+ // of exact powers of 2
+ //
+ // the plan is to compare bigB with bigD, and if the difference
+ // is less than halfUlp, then we're satisfied. Otherwise,
+ // use the ratio of difference to halfUlp to calculate a fudge
+ // factor to add to the floating value, then go 'round again.
+ //
+ FDBigInt diff;
+ int cmpResult;
+ boolean overvalue;
+ if ( (cmpResult = bigB.cmp( bigD ) ) > 0 ){
+ overvalue = true; // our candidate is too big.
+ diff = bigB.sub( bigD );
+ if ( (bigIntNBits == 1) && (bigIntExp > -expBias) ){
+ // candidate is a normalized exact power of 2 and
+ // is too big. We will be subtracting.
+ // For our purposes, ulp is the ulp of the
+ // next smaller range.
+ Ulp2 -= 1;
+ if ( Ulp2 < 0 ){
+ // rats. Cannot de-scale ulp this far.
+ // must scale diff in other direction.
+ Ulp2 = 0;
+ diff.lshiftMe( 1 );
+ }
+ }
+ } else if ( cmpResult < 0 ){
+ overvalue = false; // our candidate is too small.
+ diff = bigD.sub( bigB );
+ } else {
+ // the candidate is exactly right!
+ // this happens with surprising frequency
+ break correctionLoop;
+ }
+ FDBigInt halfUlp = constructPow52( B5, Ulp2 );
+ if ( (cmpResult = diff.cmp( halfUlp ) ) < 0 ){
+ // difference is small.
+ // this is close enough
+ if (mustSetRoundDir) {
+ roundDir = overvalue ? -1 : 1;
+ }
+ break correctionLoop;
+ } else if ( cmpResult == 0 ){
+ // difference is exactly half an ULP
+ // round to some other value maybe, then finish
+ dValue += 0.5*ulp( dValue, overvalue );
+ // should check for bigIntNBits == 1 here??
+ if (mustSetRoundDir) {
+ roundDir = overvalue ? -1 : 1;
+ }
+ break correctionLoop;
+ } else {
+ // difference is non-trivial.
+ // could scale addend by ratio of difference to
+ // halfUlp here, if we bothered to compute that difference.
+ // Most of the time ( I hope ) it is about 1 anyway.
+ dValue += ulp( dValue, overvalue );
+ if ( dValue == 0.0 || dValue == Double.POSITIVE_INFINITY )
+ break correctionLoop; // oops. Fell off end of range.
+ continue; // try again.
+ }
+
+ }
+ return (isNegative)? -dValue : dValue;
+ }
+ }
+
+ /*
+ * Take a FloatingDecimal, which we presumably just scanned in,
+ * and find out what its value i...
[truncated message content] |
|
From: <ls...@us...> - 2007-05-13 17:10:32
|
Revision: 3199
http://jnode.svn.sourceforge.net/jnode/?rev=3199&view=rev
Author: lsantha
Date: 2007-05-13 10:10:31 -0700 (Sun, 13 May 2007)
Log Message:
-----------
First merges of OpenJDK.
Added Paths:
-----------
trunk/core/src/openjdk/sun/
trunk/core/src/openjdk/sun/sun/
trunk/core/src/openjdk/sun/sun/security/
trunk/core/src/openjdk/sun/sun/security/action/
trunk/core/src/openjdk/sun/sun/security/action/GetPropertyAction.java
Added: trunk/core/src/openjdk/sun/sun/security/action/GetPropertyAction.java
===================================================================
--- trunk/core/src/openjdk/sun/sun/security/action/GetPropertyAction.java (rev 0)
+++ trunk/core/src/openjdk/sun/sun/security/action/GetPropertyAction.java 2007-05-13 17:10:31 UTC (rev 3199)
@@ -0,0 +1,88 @@
+/*
+ * Copyright 1998-2006 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.security.action;
+
+/**
+ * A convenience class for retrieving the string value of a system
+ * property as a privileged action.
+ *
+ * <p>An instance of this class can be used as the argument of
+ * <code>AccessController.doPrivileged</code>.
+ *
+ * <p>The following code retrieves the value of the system
+ * property named <code>"prop"</code> as a privileged action: <p>
+ *
+ * <pre>
+ * String s = java.security.AccessController.doPrivileged
+ * (new GetPropertyAction("prop"));
+ * </pre>
+ *
+ * @author Roland Schemers
+ * @version 1.18, 05/05/07
+ * @see java.security.PrivilegedAction
+ * @see java.security.AccessController
+ * @since 1.2
+ */
+
+public class GetPropertyAction
+ implements java.security.PrivilegedAction<String> {
+ private String theProp;
+ private String defaultVal;
+
+ /**
+ * Constructor that takes the name of the system property whose
+ * string value needs to be determined.
+ *
+ * @param theProp the name of the system property.
+ */
+ public GetPropertyAction(String theProp) {
+ this.theProp = theProp;
+ }
+
+ /**
+ * Constructor that takes the name of the system property and the default
+ * value of that property.
+ *
+ * @param theProp the name of the system property.
+ * @param defaulVal the default value.
+ */
+ public GetPropertyAction(String theProp, String defaultVal) {
+ this.theProp = theProp;
+ this.defaultVal = defaultVal;
+ }
+
+ /**
+ * Determines the string value of the system property whose
+ * name was specified in the constructor.
+ *
+ * @return the string value of the system property,
+ * or the default value if there is no property with that key.
+ */
+ public String run() {
+ String value = System.getProperty(theProp);
+ return (value == null) ? defaultVal : value;
+ }
+}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ls...@us...> - 2007-05-13 17:10:02
|
Revision: 3198
http://jnode.svn.sourceforge.net/jnode/?rev=3198&view=rev
Author: lsantha
Date: 2007-05-13 10:10:01 -0700 (Sun, 13 May 2007)
Log Message:
-----------
First merges of OpenJDK.
Added Paths:
-----------
trunk/core/src/openjdk/java/ustil/regex/Matcher.java
trunk/core/src/openjdk/java/ustil/regex/Pattern.java
trunk/core/src/openjdk/java/ustil/regex/PatternSyntaxException.java
Added: trunk/core/src/openjdk/java/ustil/regex/Matcher.java
===================================================================
--- trunk/core/src/openjdk/java/ustil/regex/Matcher.java (rev 0)
+++ trunk/core/src/openjdk/java/ustil/regex/Matcher.java 2007-05-13 17:10:01 UTC (rev 3198)
@@ -0,0 +1,1175 @@
+/*
+ * Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package java.util.regex;
+
+
+/**
+ * An engine that performs match operations on a {@link java.lang.CharSequence
+ * </code>character sequence<code>} by interpreting a {@link Pattern}.
+ *
+ * <p> A matcher is created from a pattern by invoking the pattern's {@link
+ * Pattern#matcher matcher} method. Once created, a matcher can be used to
+ * perform three different kinds of match operations:
+ *
+ * <ul>
+ *
+ * <li><p> The {@link #matches matches} method attempts to match the entire
+ * input sequence against the pattern. </p></li>
+ *
+ * <li><p> The {@link #lookingAt lookingAt} method attempts to match the
+ * input sequence, starting at the beginning, against the pattern. </p></li>
+ *
+ * <li><p> The {@link #find find} method scans the input sequence looking for
+ * the next subsequence that matches the pattern. </p></li>
+ *
+ * </ul>
+ *
+ * <p> Each of these methods returns a boolean indicating success or failure.
+ * More information about a successful match can be obtained by querying the
+ * state of the matcher.
+ *
+ * <p> A matcher finds matches in a subset of its input called the
+ * <i>region</i>. By default, the region contains all of the matcher's input.
+ * The region can be modified via the{@link #region region} method and queried
+ * via the {@link #regionStart regionStart} and {@link #regionEnd regionEnd}
+ * methods. The way that the region boundaries interact with some pattern
+ * constructs can be changed. See {@link #useAnchoringBounds
+ * useAnchoringBounds} and {@link #useTransparentBounds useTransparentBounds}
+ * for more details.
+ *
+ * <p> This class also defines methods for replacing matched subsequences with
+ * new strings whose contents can, if desired, be computed from the match
+ * result. The {@link #appendReplacement appendReplacement} and {@link
+ * #appendTail appendTail} methods can be used in tandem in order to collect
+ * the result into an existing string buffer, or the more convenient {@link
+ * #replaceAll replaceAll} method can be used to create a string in which every
+ * matching subsequence in the input sequence is replaced.
+ *
+ * <p> The explicit state of a matcher includes the start and end indices of
+ * the most recent successful match. It also includes the start and end
+ * indices of the input subsequence captured by each <a
+ * href="Pattern.html#cg">capturing group</a> in the pattern as well as a total
+ * count of such subsequences. As a convenience, methods are also provided for
+ * returning these captured subsequences in string form.
+ *
+ * <p> The explicit state of a matcher is initially undefined; attempting to
+ * query any part of it before a successful match will cause an {@link
+ * IllegalStateException} to be thrown. The explicit state of a matcher is
+ * recomputed by every match operation.
+ *
+ * <p> The implicit state of a matcher includes the input character sequence as
+ * well as the <i>append position</i>, which is initially zero and is updated
+ * by the {@link #appendReplacement appendReplacement} method.
+ *
+ * <p> A matcher may be reset explicitly by invoking its {@link #reset()}
+ * method or, if a new input sequence is desired, its {@link
+ * #reset(java.lang.CharSequence) reset(CharSequence)} method. Resetting a
+ * matcher discards its explicit state information and sets the append position
+ * to zero.
+ *
+ * <p> Instances of this class are not safe for use by multiple concurrent
+ * threads. </p>
+ *
+ *
+ * @author Mike McCloskey
+ * @author Mark Reinhold
+ * @author JSR-51 Expert Group
+ * @version 1.73, 07/05/05
+ * @since 1.4
+ * @spec JSR-51
+ */
+
+public final class Matcher implements MatchResult {
+
+ /**
+ * The Pattern object that created this Matcher.
+ */
+ Pattern parentPattern;
+
+ /**
+ * The storage used by groups. They may contain invalid values if
+ * a group was skipped during the matching.
+ */
+ int[] groups;
+
+ /**
+ * The range within the sequence that is to be matched. Anchors
+ * will match at these "hard" boundaries. Changing the region
+ * changes these values.
+ */
+ int from, to;
+
+ /**
+ * Lookbehind uses this value to ensure that the subexpression
+ * match ends at the point where the lookbehind was encountered.
+ */
+ int lookbehindTo;
+
+ /**
+ * The original string being matched.
+ */
+ CharSequence text;
+
+ /**
+ * Matcher state used by the last node. NOANCHOR is used when a
+ * match does not have to consume all of the input. ENDANCHOR is
+ * the mode used for matching all the input.
+ */
+ static final int ENDANCHOR = 1;
+ static final int NOANCHOR = 0;
+ int acceptMode = NOANCHOR;
+
+ /**
+ * The range of string that last matched the pattern. If the last
+ * match failed then first is -1; last initially holds 0 then it
+ * holds the index of the end of the last match (which is where the
+ * next search starts).
+ */
+ int first = -1, last = 0;
+
+ /**
+ * The end index of what matched in the last match operation.
+ */
+ int oldLast = -1;
+
+ /**
+ * The index of the last position appended in a substitution.
+ */
+ int lastAppendPosition = 0;
+
+ /**
+ * Storage used by nodes to tell what repetition they are on in
+ * a pattern, and where groups begin. The nodes themselves are stateless,
+ * so they rely on this field to hold state during a match.
+ */
+ int[] locals;
+
+ /**
+ * Boolean indicating whether or not more input could change
+ * the results of the last match.
+ *
+ * If hitEnd is true, and a match was found, then more input
+ * might cause a different match to be found.
+ * If hitEnd is true and a match was not found, then more
+ * input could cause a match to be found.
+ * If hitEnd is false and a match was found, then more input
+ * will not change the match.
+ * If hitEnd is false and a match was not found, then more
+ * input will not cause a match to be found.
+ */
+ boolean hitEnd;
+
+ /**
+ * Boolean indicating whether or not more input could change
+ * a positive match into a negative one.
+ *
+ * If requireEnd is true, and a match was found, then more
+ * input could cause the match to be lost.
+ * If requireEnd is false and a match was found, then more
+ * input might change the match but the match won't be lost.
+ * If a match was not found, then requireEnd has no meaning.
+ */
+ boolean requireEnd;
+
+ /**
+ * If transparentBounds is true then the boundaries of this
+ * matcher's region are transparent to lookahead, lookbehind,
+ * and boundary matching constructs that try to see beyond them.
+ */
+ boolean transparentBounds = false;
+
+ /**
+ * If anchoringBounds is true then the boundaries of this
+ * matcher's region match anchors such as ^ and $.
+ */
+ boolean anchoringBounds = true;
+
+ /**
+ * No default constructor.
+ */
+ Matcher() {
+ }
+
+ /**
+ * All matchers have the state used by Pattern during a match.
+ */
+ Matcher(Pattern parent, CharSequence text) {
+ this.parentPattern = parent;
+ this.text = text;
+
+ // Allocate state storage
+ int parentGroupCount = Math.max(parent.capturingGroupCount, 10);
+ groups = new int[parentGroupCount * 2];
+ locals = new int[parent.localCount];
+
+ // Put fields into initial states
+ reset();
+ }
+
+ /**
+ * Returns the pattern that is interpreted by this matcher.
+ *
+ * @return The pattern for which this matcher was created
+ */
+ public Pattern pattern() {
+ return parentPattern;
+ }
+
+ /**
+ * Returns the match state of this matcher as a {@link MatchResult}.
+ * The result is unaffected by subsequent operations performed upon this
+ * matcher.
+ *
+ * @return a <code>MatchResult</code> with the state of this matcher
+ * @since 1.5
+ */
+ public MatchResult toMatchResult() {
+ Matcher result = new Matcher(this.parentPattern, text.toString());
+ result.first = this.first;
+ result.last = this.last;
+ result.groups = (int[])(this.groups.clone());
+ return result;
+ }
+
+ /**
+ * Changes the <tt>Pattern</tt> that this <tt>Matcher</tt> uses to
+ * find matches with.
+ *
+ * <p> This method causes this matcher to lose information
+ * about the groups of the last match that occurred. The
+ * matcher's position in the input is maintained and its
+ * last append position is unaffected.</p>
+ *
+ * @param newPattern
+ * The new pattern used by this matcher
+ * @return This matcher
+ * @throws IllegalArgumentException
+ * If newPattern is <tt>null</tt>
+ * @since 1.5
+ */
+ public Matcher usePattern(Pattern newPattern) {
+ if (newPattern == null)
+ throw new IllegalArgumentException("Pattern cannot be null");
+ parentPattern = newPattern;
+
+ // Reallocate state storage
+ int parentGroupCount = Math.max(newPattern.capturingGroupCount, 10);
+ groups = new int[parentGroupCount * 2];
+ locals = new int[newPattern.localCount];
+ for (int i = 0; i < groups.length; i++)
+ groups[i] = -1;
+ for (int i = 0; i < locals.length; i++)
+ locals[i] = -1;
+ return this;
+ }
+
+ /**
+ * Resets this matcher.
+ *
+ * <p> Resetting a matcher discards all of its explicit state information
+ * and sets its append position to zero. The matcher's region is set to the
+ * default region, which is its entire character sequence. The anchoring
+ * and transparency of this matcher's region boundaries are unaffected.
+ *
+ * @return This matcher
+ */
+ public Matcher reset() {
+ first = -1;
+ last = 0;
+ oldLast = -1;
+ for(int i=0; i<groups.length; i++)
+ groups[i] = -1;
+ for(int i=0; i<locals.length; i++)
+ locals[i] = -1;
+ lastAppendPosition = 0;
+ from = 0;
+ to = getTextLength();
+ return this;
+ }
+
+ /**
+ * Resets this matcher with a new input sequence.
+ *
+ * <p> Resetting a matcher discards all of its explicit state information
+ * and sets its append position to zero. The matcher's region is set to
+ * the default region, which is its entire character sequence. The
+ * anchoring and transparency of this matcher's region boundaries are
+ * unaffected.
+ *
+ * @param input
+ * The new input character sequence
+ *
+ * @return This matcher
+ */
+ public Matcher reset(CharSequence input) {
+ text = input;
+ return reset();
+ }
+
+ /**
+ * Returns the start index of the previous match. </p>
+ *
+ * @return The index of the first character matched
+ *
+ * @throws IllegalStateException
+ * If no match has yet been attempted,
+ * or if the previous match operation failed
+ */
+ public int start() {
+ if (first < 0)
+ throw new IllegalStateException("No match available");
+ return first;
+ }
+
+ /**
+ * Returns the start index of the subsequence captured by the given group
+ * during the previous match operation.
+ *
+ * <p> <a href="Pattern.html#cg">Capturing groups</a> are indexed from left
+ * to right, starting at one. Group zero denotes the entire pattern, so
+ * the expression <i>m.</i><tt>start(0)</tt> is equivalent to
+ * <i>m.</i><tt>start()</tt>. </p>
+ *
+ * @param group
+ * The index of a capturing group in this matcher's pattern
+ *
+ * @return The index of the first character captured by the group,
+ * or <tt>-1</tt> if the match was successful but the group
+ * itself did not match anything
+ *
+ * @throws IllegalStateException
+ * If no match has yet been attempted,
+ * or if the previous match operation failed
+ *
+ * @throws IndexOutOfBoundsException
+ * If there is no capturing group in the pattern
+ * with the given index
+ */
+ public int start(int group) {
+ if (first < 0)
+ throw new IllegalStateException("No match available");
+ if (group > groupCount())
+ throw new IndexOutOfBoundsException("No group " + group);
+ return groups[group * 2];
+ }
+
+ /**
+ * Returns the offset after the last character matched. </p>
+ *
+ * @return The offset after the last character matched
+ *
+ * @throws IllegalStateException
+ * If no match has yet been attempted,
+ * or if the previous match operation failed
+ */
+ public int end() {
+ if (first < 0)
+ throw new IllegalStateException("No match available");
+ return last;
+ }
+
+ /**
+ * Returns the offset after the last character of the subsequence
+ * captured by the given group during the previous match operation.
+ *
+ * <p> <a href="Pattern.html#cg">Capturing groups</a> are indexed from left
+ * to right, starting at one. Group zero denotes the entire pattern, so
+ * the expression <i>m.</i><tt>end(0)</tt> is equivalent to
+ * <i>m.</i><tt>end()</tt>. </p>
+ *
+ * @param group
+ * The index of a capturing group in this matcher's pattern
+ *
+ * @return The offset after the last character captured by the group,
+ * or <tt>-1</tt> if the match was successful
+ * but the group itself did not match anything
+ *
+ * @throws IllegalStateException
+ * If no match has yet been attempted,
+ * or if the previous match operation failed
+ *
+ * @throws IndexOutOfBoundsException
+ * If there is no capturing group in the pattern
+ * with the given index
+ */
+ public int end(int group) {
+ if (first < 0)
+ throw new IllegalStateException("No match available");
+ if (group > groupCount())
+ throw new IndexOutOfBoundsException("No group " + group);
+ return groups[group * 2 + 1];
+ }
+
+ /**
+ * Returns the input subsequence matched by the previous match.
+ *
+ * <p> For a matcher <i>m</i> with input sequence <i>s</i>,
+ * the expressions <i>m.</i><tt>group()</tt> and
+ * <i>s.</i><tt>substring(</tt><i>m.</i><tt>start(),</tt> <i>m.</i><tt>end())</tt>
+ * are equivalent. </p>
+ *
+ * <p> Note that some patterns, for example <tt>a*</tt>, match the empty
+ * string. This method will return the empty string when the pattern
+ * successfully matches the empty string in the input. </p>
+ *
+ * @return The (possibly empty) subsequence matched by the previous match,
+ * in string form
+ *
+ * @throws IllegalStateException
+ * If no match has yet been attempted,
+ * or if the previous match operation failed
+ */
+ public String group() {
+ return group(0);
+ }
+
+ /**
+ * Returns the input subsequence captured by the given group during the
+ * previous match operation.
+ *
+ * <p> For a matcher <i>m</i>, input sequence <i>s</i>, and group index
+ * <i>g</i>, the expressions <i>m.</i><tt>group(</tt><i>g</i><tt>)</tt> and
+ * <i>s.</i><tt>substring(</tt><i>m.</i><tt>start(</tt><i>g</i><tt>),</tt> <i>m.</i><tt>end(</tt><i>g</i><tt>))</tt>
+ * are equivalent. </p>
+ *
+ * <p> <a href="Pattern.html#cg">Capturing groups</a> are indexed from left
+ * to right, starting at one. Group zero denotes the entire pattern, so
+ * the expression <tt>m.group(0)</tt> is equivalent to <tt>m.group()</tt>.
+ * </p>
+ *
+ * <p> If the match was successful but the group specified failed to match
+ * any part of the input sequence, then <tt>null</tt> is returned. Note
+ * that some groups, for example <tt>(a*)</tt>, match the empty string.
+ * This method will return the empty string when such a group successfully
+ * matches the empty string in the input. </p>
+ *
+ * @param group
+ * The index of a capturing group in this matcher's pattern
+ *
+ * @return The (possibly empty) subsequence captured by the group
+ * during the previous match, or <tt>null</tt> if the group
+ * failed to match part of the input
+ *
+ * @throws IllegalStateException
+ * If no match has yet been attempted,
+ * or if the previous match operation failed
+ *
+ * @throws IndexOutOfBoundsException
+ * If there is no capturing group in the pattern
+ * with the given index
+ */
+ public String group(int group) {
+ if (first < 0)
+ throw new IllegalStateException("No match found");
+ if (group < 0 || group > groupCount())
+ throw new IndexOutOfBoundsException("No group " + group);
+ if ((groups[group*2] == -1) || (groups[group*2+1] == -1))
+ return null;
+ return getSubSequence(groups[group * 2], groups[group * 2 + 1]).toString();
+ }
+
+ /**
+ * Returns the number of capturing groups in this matcher's pattern.
+ *
+ * <p> Group zero denotes the entire pattern by convention. It is not
+ * included in this count.
+ *
+ * <p> Any non-negative integer smaller than or equal to the value
+ * returned by this method is guaranteed to be a valid group index for
+ * this matcher. </p>
+ *
+ * @return The number of capturing groups in this matcher's pattern
+ */
+ public int groupCount() {
+ return parentPattern.capturingGroupCount - 1;
+ }
+
+ /**
+ * Attempts to match the entire region against the pattern.
+ *
+ * <p> If the match succeeds then more information can be obtained via the
+ * <tt>start</tt>, <tt>end</tt>, and <tt>group</tt> methods. </p>
+ *
+ * @return <tt>true</tt> if, and only if, the entire region sequence
+ * matches this matcher's pattern
+ */
+ public boolean matches() {
+ return match(from, ENDANCHOR);
+ }
+
+ /**
+ * Attempts to find the next subsequence of the input sequence that matches
+ * the pattern.
+ *
+ * <p> This method starts at the beginning of this matcher's region, or, if
+ * a previous invocation of the method was successful and the matcher has
+ * not since been reset, at the first character not matched by the previous
+ * match.
+ *
+ * <p> If the match succeeds then more information can be obtained via the
+ * <tt>start</tt>, <tt>end</tt>, and <tt>group</tt> methods. </p>
+ *
+ * @return <tt>true</tt> if, and only if, a subsequence of the input
+ * sequence matches this matcher's pattern
+ */
+ public boolean find() {
+ int nextSearchIndex = last;
+ if (nextSearchIndex == first)
+ nextSearchIndex++;
+
+ // If next search starts before region, start it at region
+ if (nextSearchIndex < from)
+ nextSearchIndex = from;
+
+ // If next search starts beyond region then it fails
+ if (nextSearchIndex > to) {
+ for (int i = 0; i < groups.length; i++)
+ groups[i] = -1;
+ return false;
+ }
+ return search(nextSearchIndex);
+ }
+
+ /**
+ * Resets this matcher and then attempts to find the next subsequence of
+ * the input sequence that matches the pattern, starting at the specified
+ * index.
+ *
+ * <p> If the match succeeds then more information can be obtained via the
+ * <tt>start</tt>, <tt>end</tt>, and <tt>group</tt> methods, and subsequent
+ * invocations of the {@link #find()} method will start at the first
+ * character not matched by this match. </p>
+ *
+ * @throws IndexOutOfBoundsException
+ * If start is less than zero or if start is greater than the
+ * length of the input sequence.
+ *
+ * @return <tt>true</tt> if, and only if, a subsequence of the input
+ * sequence starting at the given index matches this matcher's
+ * pattern
+ */
+ public boolean find(int start) {
+ int limit = getTextLength();
+ if ((start < 0) || (start > limit))
+ throw new IndexOutOfBoundsException("Illegal start index");
+ reset();
+ return search(start);
+ }
+
+ /**
+ * Attempts to match the input sequence, starting at the beginning of the
+ * region, against the pattern.
+ *
+ * <p> Like the {@link #matches matches} method, this method always starts
+ * at the beginning of the region; unlike that method, it does not
+ * require that the entire region be matched.
+ *
+ * <p> If the match succeeds then more information can be obtained via the
+ * <tt>start</tt>, <tt>end</tt>, and <tt>group</tt> methods. </p>
+ *
+ * @return <tt>true</tt> if, and only if, a prefix of the input
+ * sequence matches this matcher's pattern
+ */
+ public boolean lookingAt() {
+ return match(from, NOANCHOR);
+ }
+
+ /**
+ * Returns a literal replacement <code>String</code> for the specified
+ * <code>String</code>.
+ *
+ * This method produces a <code>String</code> that will work
+ * as a literal replacement <code>s</code> in the
+ * <code>appendReplacement</code> method of the {@link Matcher} class.
+ * The <code>String</code> produced will match the sequence of characters
+ * in <code>s</code> treated as a literal sequence. Slashes ('\') and
+ * dollar signs ('$') will be given no special meaning.
+ *
+ * @param s The string to be literalized
+ * @return A literal string replacement
+ * @since 1.5
+ */
+ public static String quoteReplacement(String s) {
+ if ((s.indexOf('\\') == -1) && (s.indexOf('$') == -1))
+ return s;
+ StringBuilder sb = new StringBuilder();
+ for (int i=0; i<s.length(); i++) {
+ char c = s.charAt(i);
+ if (c == '\\' || c == '$') {
+ sb.append('\\');
+ }
+ sb.append(c);
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Implements a non-terminal append-and-replace step.
+ *
+ * <p> This method performs the following actions: </p>
+ *
+ * <ol>
+ *
+ * <li><p> It reads characters from the input sequence, starting at the
+ * append position, and appends them to the given string buffer. It
+ * stops after reading the last character preceding the previous match,
+ * that is, the character at index {@link
+ * #start()} <tt>-</tt> <tt>1</tt>. </p></li>
+ *
+ * <li><p> It appends the given replacement string to the string buffer.
+ * </p></li>
+ *
+ * <li><p> It sets the append position of this matcher to the index of
+ * the last character matched, plus one, that is, to {@link #end()}.
+ * </p></li>
+ *
+ * </ol>
+ *
+ * <p> The replacement string may contain references to subsequences
+ * captured during the previous match: Each occurrence of
+ * <tt>$</tt><i>g</i><tt></tt> will be replaced by the result of
+ * evaluating {@link #group(int) group}<tt>(</tt><i>g</i><tt>)</tt>.
+ * The first number after the <tt>$</tt> is always treated as part of
+ * the group reference. Subsequent numbers are incorporated into g if
+ * they would form a legal group reference. Only the numerals '0'
+ * through '9' are considered as potential components of the group
+ * reference. If the second group matched the string <tt>"foo"</tt>, for
+ * example, then passing the replacement string <tt>"$2bar"</tt> would
+ * cause <tt>"foobar"</tt> to be appended to the string buffer. A dollar
+ * sign (<tt>$</tt>) may be included as a literal in the replacement
+ * string by preceding it with a backslash (<tt>\$</tt>).
+ *
+ * <p> Note that backslashes (<tt>\</tt>) and dollar signs (<tt>$</tt>) in
+ * the replacement string may cause the results to be different than if it
+ * were being treated as a literal replacement string. Dollar signs may be
+ * treated as references to captured subsequences as described above, and
+ * backslashes are used to escape literal characters in the replacement
+ * string.
+ *
+ * <p> This method is intended to be used in a loop together with the
+ * {@link #appendTail appendTail} and {@link #find find} methods. The
+ * following code, for example, writes <tt>one dog two dogs in the
+ * yard</tt> to the standard-output stream: </p>
+ *
+ * <blockquote><pre>
+ * Pattern p = Pattern.compile("cat");
+ * Matcher m = p.matcher("one cat two cats in the yard");
+ * StringBuffer sb = new StringBuffer();
+ * while (m.find()) {
+ * m.appendReplacement(sb, "dog");
+ * }
+ * m.appendTail(sb);
+ * System.out.println(sb.toString());</pre></blockquote>
+ *
+ * @param sb
+ * The target string buffer
+ *
+ * @param replacement
+ * The replacement string
+ *
+ * @return This matcher
+ *
+ * @throws IllegalStateException
+ * If no match has yet been attempted,
+ * or if the previous match operation failed
+ *
+ * @throws IndexOutOfBoundsException
+ * If the replacement string refers to a capturing group
+ * that does not exist in the pattern
+ */
+ public Matcher appendReplacement(StringBuffer sb, String replacement) {
+
+ // If no match, return error
+ if (first < 0)
+ throw new IllegalStateException("No match available");
+
+ // Process substitution string to replace group references with groups
+ int cursor = 0;
+ StringBuilder result = new StringBuilder();
+
+ while (cursor < replacement.length()) {
+ char nextChar = replacement.charAt(cursor);
+ if (nextChar == '\\') {
+ cursor++;
+ nextChar = replacement.charAt(cursor);
+ result.append(nextChar);
+ cursor++;
+ } else if (nextChar == '$') {
+ // Skip past $
+ cursor++;
+ // The first number is always a group
+ int refNum = (int)replacement.charAt(cursor) - '0';
+ if ((refNum < 0)||(refNum > 9))
+ throw new IllegalArgumentException(
+ "Illegal group reference");
+ cursor++;
+
+ // Capture the largest legal group string
+ boolean done = false;
+ while (!done) {
+ if (cursor >= replacement.length()) {
+ break;
+ }
+ int nextDigit = replacement.charAt(cursor) - '0';
+ if ((nextDigit < 0)||(nextDigit > 9)) { // not a number
+ break;
+ }
+ int newRefNum = (refNum * 10) + nextDigit;
+ if (groupCount() < newRefNum) {
+ done = true;
+ } else {
+ refNum = newRefNum;
+ cursor++;
+ }
+ }
+ // Append group
+ if (start(refNum) != -1 && end(refNum) != -1)
+ result.append(text, start(refNum), end(refNum));
+ } else {
+ result.append(nextChar);
+ cursor++;
+ }
+ }
+ // Append the intervening text
+ sb.append(text, lastAppendPosition, first);
+ // Append the match substitution
+ sb.append(result);
+
+ lastAppendPosition = last;
+ return this;
+ }
+
+ /**
+ * Implements a terminal append-and-replace step.
+ *
+ * <p> This method reads characters from the input sequence, starting at
+ * the append position, and appends them to the given string buffer. It is
+ * intended to be invoked after one or more invocations of the {@link
+ * #appendReplacement appendReplacement} method in order to copy the
+ * remainder of the input sequence. </p>
+ *
+ * @param sb
+ * The target string buffer
+ *
+ * @return The target string buffer
+ */
+ public StringBuffer appendTail(StringBuffer sb) {
+ sb.append(text, lastAppendPosition, getTextLength());
+ return sb;
+ }
+
+ /**
+ * Replaces every subsequence of the input sequence that matches the
+ * pattern with the given replacement string.
+ *
+ * <p> This method first resets this matcher. It then scans the input
+ * sequence looking for matches of the pattern. Characters that are not
+ * part of any match are appended directly to the result string; each match
+ * is replaced in the result by the replacement string. The replacement
+ * string may contain references to captured subsequences as in the {@link
+ * #appendReplacement appendReplacement} method.
+ *
+ * <p> Note that backslashes (<tt>\</tt>) and dollar signs (<tt>$</tt>) in
+ * the replacement string may cause the results to be different than if it
+ * were being treated as a literal replacement string. Dollar signs may be
+ * treated as references to captured subsequences as described above, and
+ * backslashes are used to escape literal characters in the replacement
+ * string.
+ *
+ * <p> Given the regular expression <tt>a*b</tt>, the input
+ * <tt>"aabfooaabfooabfoob"</tt>, and the replacement string
+ * <tt>"-"</tt>, an invocation of this method on a matcher for that
+ * expression would yield the string <tt>"-foo-foo-foo-"</tt>.
+ *
+ * <p> Invoking this method changes this matcher's state. If the matcher
+ * is to be used in further matching operations then it should first be
+ * reset. </p>
+ *
+ * @param replacement
+ * The replacement string
+ *
+ * @return The string constructed by replacing each matching subsequence
+ * by the replacement string, substituting captured subsequences
+ * as needed
+ */
+ public String replaceAll(String replacement) {
+ reset();
+ boolean result = find();
+ if (result) {
+ StringBuffer sb = new StringBuffer();
+ do {
+ appendReplacement(sb, replacement);
+ result = find();
+ } while (result);
+ appendTail(sb);
+ return sb.toString();
+ }
+ return text.toString();
+ }
+
+ /**
+ * Replaces the first subsequence of the input sequence that matches the
+ * pattern with the given replacement string.
+ *
+ * <p> This method first resets this matcher. It then scans the input
+ * sequence looking for a match of the pattern. Characters that are not
+ * part of the match are appended directly to the result string; the match
+ * is replaced in the result by the replacement string. The replacement
+ * string may contain references to captured subsequences as in the {@link
+ * #appendReplacement appendReplacement} method.
+ *
+ * <p>Note that backslashes (<tt>\</tt>) and dollar signs (<tt>$</tt>) in
+ * the replacement string may cause the results to be different than if it
+ * were being treated as a literal replacement string. Dollar signs may be
+ * treated as references to captured subsequences as described above, and
+ * backslashes are used to escape literal characters in the replacement
+ * string.
+ *
+ * <p> Given the regular expression <tt>dog</tt>, the input
+ * <tt>"zzzdogzzzdogzzz"</tt>, and the replacement string
+ * <tt>"cat"</tt>, an invocation of this method on a matcher for that
+ * expression would yield the string <tt>"zzzcatzzzdogzzz"</tt>. </p>
+ *
+ * <p> Invoking this method changes this matcher's state. If the matcher
+ * is to be used in further matching operations then it should first be
+ * reset. </p>
+ *
+ * @param replacement
+ * The replacement string
+ * @return The string constructed by replacing the first matching
+ * subsequence by the replacement string, substituting captured
+ * subsequences as needed
+ */
+ public String replaceFirst(String replacement) {
+ if (replacement == null)
+ throw new NullPointerException("replacement");
+ reset();
+ if (!find())
+ return text.toString();
+ StringBuffer sb = new StringBuffer();
+ appendReplacement(sb, replacement);
+ appendTail(sb);
+ return sb.toString();
+ }
+
+ /**
+ * Sets the limits of this matcher's region. The region is the part of the
+ * input sequence that will be searched to find a match. Invoking this
+ * method resets the matcher, and then sets the region to start at the
+ * index specified by the <code>start</code> parameter and end at the
+ * index specified by the <code>end</code> parameter.
+ *
+ * <p>Depending on the transparency and anchoring being used (see
+ * {@link #useTransparentBounds useTransparentBounds} and
+ * {@link #useAnchoringBounds useAnchoringBounds}), certain constructs such
+ * as anchors may behave differently at or around the boundaries of the
+ * region.
+ *
+ * @param start
+ * The index to start searching at (inclusive)
+ * @param end
+ * The index to end searching at (exclusive)
+ * @throws IndexOutOfBoundsException
+ * If start or end is less than zero, if
+ * start is greater than the length of the input sequence, if
+ * end is greater than the length of the input sequence, or if
+ * start is greater than end.
+ * @return this matcher
+ * @since 1.5
+ */
+ public Matcher region(int start, int end) {
+ if ((start < 0) || (start > getTextLength()))
+ throw new IndexOutOfBoundsException("start");
+ if ((end < 0) || (end > getTextLength()))
+ throw new IndexOutOfBoundsException("end");
+ if (start > end)
+ throw new IndexOutOfBoundsException("start > end");
+ reset();
+ from = start;
+ to = end;
+ return this;
+ }
+
+ /**
+ * Reports the start index of this matcher's region. The
+ * searches this matcher conducts are limited to finding matches
+ * within {@link #regionStart regionStart} (inclusive) and
+ * {@link #regionEnd regionEnd} (exclusive).
+ *
+ * @return The starting point of this matcher's region
+ * @since 1.5
+ */
+ public int regionStart() {
+ return from;
+ }
+
+ /**
+ * Reports the end index (exclusive) of this matcher's region.
+ * The searches this matcher conducts are limited to finding matches
+ * within {@link #regionStart regionStart} (inclusive) and
+ * {@link #regionEnd regionEnd} (exclusive).
+ *
+ * @return the ending point of this matcher's region
+ * @since 1.5
+ */
+ public int regionEnd() {
+ return to;
+ }
+
+ /**
+ * Queries the transparency of region bounds for this matcher.
+ *
+ * <p> This method returns <tt>true</tt> if this matcher uses
+ * <i>transparent</i> bounds, <tt>false</tt> if it uses <i>opaque</i>
+ * bounds.
+ *
+ * <p> See {@link #useTransparentBounds useTransparentBounds} for a
+ * description of transparent and opaque bounds.
+ *
+ * <p> By default, a matcher uses opaque region boundaries.
+ *
+ * @return <tt>true</tt> iff this matcher is using transparent bounds,
+ * <tt>false</tt> otherwise.
+ * @see java.util.regex.Matcher#useTransparentBounds(boolean)
+ * @since 1.5
+ */
+ public boolean hasTransparentBounds() {
+ return transparentBounds;
+ }
+
+ /**
+ * Sets the transparency of region bounds for this matcher.
+ *
+ * <p> Invoking this method with an argument of <tt>true</tt> will set this
+ * matcher to use <i>transparent</i> bounds. If the boolean
+ * argument is <tt>false</tt>, then <i>opaque</i> bounds will be used.
+ *
+ * <p> Using transparent bounds, the boundaries of this
+ * matcher's region are transparent to lookahead, lookbehind,
+ * and boundary matching constructs. Those constructs can see beyond the
+ * boundaries of the region to see if a match is appropriate.
+ *
+ * <p> Using opaque bounds, the boundaries of this matcher's
+ * region are opaque to lookahead, lookbehind, and boundary matching
+ * constructs that may try to see beyond them. Those constructs cannot
+ * look past the boundaries so they will fail to match anything outside
+ * of the region.
+ *
+ * <p> By default, a matcher uses opaque bounds.
+ *
+ * @param b a boolean indicating whether to use opaque or transparent
+ * regions
+ * @return this matcher
+ * @see java.util.regex.Matcher#hasTransparentBounds
+ * @since 1.5
+ */
+ public Matcher useTransparentBounds(boolean b) {
+ transparentBounds = b;
+ return this;
+ }
+
+ /**
+ * Queries the anchoring of region bounds for this matcher.
+ *
+ * <p> This method returns <tt>true</tt> if this matcher uses
+ * <i>anchoring</i> bounds, <tt>false</tt> otherwise.
+ *
+ * <p> See {@link #useAnchoringBounds useAnchoringBounds} for a
+ * description of anchoring bounds.
+ *
+ * <p> By default, a matcher uses anchoring region boundaries.
+ *
+ * @return <tt>true</tt> iff this matcher is using anchoring bounds,
+ * <tt>false</tt> otherwise.
+ * @see java.util.regex.Matcher#useAnchoringBounds(boolean)
+ * @since 1.5
+ */
+ public boolean hasAnchoringBounds() {
+ return anchoringBounds;
+ }
+
+ /**
+ * Sets the anchoring of region bounds for this matcher.
+ *
+ * <p> Invoking this method with an argument of <tt>true</tt> will set this
+ * matcher to use <i>anchoring</i> bounds. If the boolean
+ * argument is <tt>false</tt>, then <i>non-anchoring</i> bounds will be
+ * used.
+ *
+ * <p> Using anchoring bounds, the boundaries of this
+ * matcher's region match anchors such as ^ and $.
+ *
+ * <p> Without anchoring bounds, the boundaries of this
+ * matcher's region will not match anchors such as ^ and $.
+ *
+ * <p> By default, a matcher uses anchoring region boundaries.
+ *
+ * @param b a boolean indicating whether or not to use anchoring bounds.
+ * @return this matcher
+ * @see java.util.regex.Matcher#hasAnchoringBounds
+ * @since 1.5
+ */
+ public Matcher useAnchoringBounds(boolean b) {
+ anchoringBounds = b;
+ return this;
+ }
+
+ /**
+ * <p>Returns the string representation of this matcher. The
+ * string representation of a <code>Matcher</code> contains information
+ * that may be useful for debugging. The exact format is unspecified.
+ *
+ * @return The string representation of this matcher
+ * @since 1.5
+ */
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("java.util.regex.Matcher");
+ sb.append("[pattern=" + pattern());
+ sb.append(" region=");
+ sb.append(regionStart() + "," + regionEnd());
+ sb.append(" lastmatch=");
+ if ((first >= 0) && (group() != null)) {
+ sb.append(group());
+ }
+ sb.append("]");
+ return sb.toString();
+ }
+
+ /**
+ * <p>Returns true if the end of input was hit by the search engine in
+ * the last match operation performed by this matcher.
+ *
+ * <p>When this method returns true, then it is possible that more input
+ * would have changed the result of the last search.
+ *
+ * @return true iff the end of input was hit in the last match; false
+ * otherwise
+ * @since 1.5
+ */
+ public boolean hitEnd() {
+ return hitEnd;
+ }
+
+ /**
+ * <p>Returns true if more input could change a positive match into a
+ * negative one.
+ *
+ * <p>If this method returns true, and a match was found, then more
+ * input could cause the match to be lost. If this method returns false
+ * and a match was found, then more input might change the match but the
+ * match won't be lost. If a match was not found, then requireEnd has no
+ * meaning.
+ *
+ * @return true iff more input could change a positive match into a
+ * negative one.
+ * @since 1.5
+ */
+ public boolean requireEnd() {
+ return requireEnd;
+ }
+
+ /**
+ * Initiates a search to find a Pattern within the given bounds.
+ * The groups are filled with default values and the match of the root
+ * of the state machine is called. The state machine will hold the state
+ * of the match as it proceeds in this matcher.
+ *
+ * Matcher.from is not set here, because it is the "hard" boundary
+ * of the start of the search which anchors will set to. The from param
+ * is the "soft" boundary of the start of the search, meaning that the
+ * regex tries to match at that index but ^ won't match there. Subsequent
+ * calls to the search methods start at a new "soft" boundary which is
+ * the end of the previous match.
+ */
+ boolean search(int from) {
+ this.hitEnd = false;
+ this.requireEnd = false;
+ from = from < 0 ? 0 : from;
+ this.first = from;
+ this.oldLast = oldLast < 0 ? from : oldLast;
+ for (int i = 0; i < groups.length; i++)
+ groups[i] = -1;
+ acceptMode = NOANCHOR;
+ boolean result = parentPattern.root.match(this, from, text);
+ if (!result)
+ this.first = -1;
+ this.oldLast = this.last;
+ return result;
+ }
+
+ /**
+ * Initiates a search for an anchored match to a Pattern within the given
+ * bounds. The groups are filled with default values and the match of the
+ * root of the state machine is called. The state machine will hold the
+ * state of the match as it proceeds in this matcher.
+ */
+ boolean match(int from, int anchor) {
+ this.hitEnd = false;
+ this.requireEnd = false;
+ from = from < 0 ? 0 : from;
+ this.first = from;
+ this.oldLast = oldLast < 0 ? from : oldLast;
+ for (int i = 0; i < groups.length; i++)
+ groups[i] = -1;
+ acceptMode = anchor;
+ boolean result = parentPattern.matchRoot.match(this, from, text);
+ if (!result)
+ this.first = -1;
+ this.oldLast = this.last;
+ return result;
+ }
+
+ /**
+ * Returns the end index of the text.
+ *
+ * @return the index after the last character in the text
+ */
+ int getTextLength() {
+ return text.length();
+ }
+
+ /**
+ * Generates a String from this Matcher's input in the specified range.
+ *
+ * @param beginIndex the beginning index, inclusive
+ * @param endIndex the ending index, exclusive
+ * @return A String generated from this Matcher's input
+ */
+ CharSequence getSubSequence(int beginIndex, int endIndex) {
+ return text.subSequence(beginIndex, endIndex);
+ }
+
+ /**
+ * Returns this Matcher's input character at index i.
+ *
+ * @return A char from the specified index
+ */
+ char charAt(int i) {
+ return text.charAt(i);
+ }
+
+}
Added: trunk/core/src/openjdk/java/ustil/regex/Pattern.java
===================================================================
--- trunk/core/src/openjdk/java/ustil/regex/Pattern.java (rev 0)
+++ trunk/core/src/openjdk/java/ustil/regex/Pattern.java 2007-05-13 17:10:01 UTC (rev 3198)
@@ -0,0 +1,5264 @@
+/*
+ * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package java.util.regex;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.text.CharacterIterator;
+import java.text.Normalizer;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Arrays;
+
+
+/**
+ * A compiled representation of a regular expression.
+ *
+ * <p> A regular expression, specified as a string, must first be compiled into
+ * an instance of this class. The resulting pattern can then be used to create
+ * a {@link Matcher} object that can match arbitrary {@link
+ * java.lang.CharSequence </code>character sequences<code>} against the regular
+ * expression. All of the state involved in performing a match resides in the
+ * matcher, so many matchers can share the same pattern.
+ *
+ * <p> A typical invocation sequence is thus
+ *
+ * <blockquote><pre>
+ * Pattern p = Pattern.{@link #compile compile}("a*b");
+ * Matcher m = p.{@link #matcher matcher}("aaaaab");
+ * boolean b = m.{@link Matcher#matches matches}();</pre></blockquote>
+ *
+ * <p> A {@link #matches matches} method is defined by this class as a
+ * convenience for when a regular expression is used just once. This method
+ * compiles an expression and matches an input sequence against it in a single
+ * invocation. The statement
+ *
+ * <blockquote><pre>
+ * boolean b = Pattern.matches("a*b", "aaaaab");</pre></blockquote>
+ *
+ * is equivalent to the three statements above, though for repeated matches it
+ * is less efficient since it does not allow the compiled pattern to be reused.
+ *
+ * <p> Instances of this class are immutable and are safe for use by multiple
+ * concurrent threads. Instances of the {@link Matcher} class are not safe for
+ * such use.
+ *
+ *
+ * <a name="sum">
+ * <h4> Summary of regular-expression constructs </h4>
+ *
+ * <table border="0" cellpadding="1" cellspacing="0"
+ * summary="Regular expression constructs, and what they match">
+ *
+ * <tr align="left">
+ * <th bgcolor="#CCCCFF" align="left" id="construct">Construct</th>
+ * <th bgcolor="#CCCCFF" align="left" id="matches">Matches</th>
+ * </tr>
+ *
+ * <tr><th> </th></tr>
+ * <tr align="left"><th colspan="2" id="characters">Characters</th></tr>
+ *
+ * <tr><td valign="top" headers="construct characters"><i>x</i></td>
+ * <td headers="matches">The character <i>x</i></td></tr>
+ * <tr><td valign="top" headers="construct characters"><tt>\\</tt></td>
+ * <td headers="matches">The backslash character</td></tr>
+ * <tr><td valign="top" headers="construct characters"><tt>\0</tt><i>n</i></td>
+ * <td headers="matches">The character with octal value <tt>0</tt><i>n</i>
+ * (0 <tt><=</tt> <i>n</i> <tt><=</tt> 7)</td></tr>
+ * <tr><td valign="top" headers="construct characters"><tt>\0</tt><i>nn</i></td>
+ * <td headers="matches">The character with octal value <tt>0</tt><i>nn</i>
+ * (0 <tt><=</tt> <i>n</i> <tt><=</tt> 7)</td></tr>
+ * <tr><td valign="top" headers="construct characters"><tt>\0</tt><i>mnn</i></td>
+ * <td headers="matches">The character with octal value <tt>0</tt><i>mnn</i>
+ * (0 <tt><=</tt> <i>m</i> <tt><=</tt> 3,
+ * 0 <tt><=</tt> <i>n</i> <tt><=</tt> 7)</td></tr>
+ * <tr><td valign="top" headers="construct characters"><tt>\x</tt><i>hh</i></td>
+ * <td headers="matches">The character with hexadecimal value <tt>0x</tt><i>hh</i></td></tr>
+ * <tr><td valign="top" headers="construct characters"><tt>\u</tt><i>hhhh</i></td>
+ * <td headers="matches">The character with hexadecimal value <tt>0x</tt><i>hhhh</i></td></tr>
+ * <tr><td valign="top" headers="matches"><tt>\t</tt></td>
+ * <td headers="matches">The tab character (<tt>'\u0009'</tt>)</td></tr>
+ * <tr><td valign="top" headers="construct characters"><tt>\n</tt></td>
+ * <td headers="matches">The newline (line feed) character (<tt>'\u000A'</tt>)</td></tr>
+ * <tr><td valign="top" headers="construct characters"><tt>\r</tt></td>
+ * <td headers="matches">The carriage-return character (<tt>'\u000D'</tt>)</td></tr>
+ * <tr><td valign="top" headers="construct characters"><tt>\f</tt></td>
+ * <td headers="matches">The form-feed character (<tt>'\u000C'</tt>)</td></tr>
+ * <tr><td valign="top" headers="construct characters"><tt>\a</tt></td>
+ * <td headers="matches">The alert (bell) character (<tt>'\u0007'</tt>)</td></tr>
+ * <tr><td valign="top" headers="construct characters"><tt>\e</tt></td>
+ * <td headers="matches">The escape character (<tt>'\u001B'</tt>)</td></tr>
+ * <tr><td valign="top" headers="construct characters"><tt>\c</tt><i>x</i></td>
+ * <td headers="matches">The control character corresponding to <i>x</i></td></tr>
+ *
+ * <tr><th> </th></tr>
+ * <tr align="left"><th colspan="2" id="classes">Character classes</th></tr>
+ *
+ * <tr><td valign="top" headers="construct classes"><tt>[abc]</tt></td>
+ * <td headers="matches"><tt>a</tt>, <tt>b</tt>, or <tt>c</tt> (simple class)</td></tr>
+ * <tr><td valign="top" headers="construct classes"><tt>[^abc]</tt></td>
+ * <td headers="matches">Any character except <tt>a</tt>, <tt>b</tt>, or <tt>c</tt> (negation)</td></tr>
+ * <tr><td valign="top" headers="construct classes"><tt>[a-zA-Z]</tt></td>
+ * <td headers="matches"><tt>a</tt> through <tt>z</tt>
+ * or <tt>A</tt> through <tt>Z</tt>, inclusive (range)</td></tr>
+ * <tr><td valign="top" headers="construct classes"><tt>[a-d[m-p]]</tt></td>
+ * <td headers="matches"><tt>a</tt> through <tt>d</tt>,
+ * or <tt>m</tt> through <tt>p</tt>: <tt>[a-dm-p]</tt> (union)</td></tr>
+ * <tr><td valign="top" headers="construct classes"><tt>[a-z&&[def]]</tt></td>
+ * <td headers="matches"><tt>d</tt>, <tt>e</tt>, or <tt>f</tt> (intersection)</tr>
+ * <tr><td valign="top" headers="construct classes"><tt>[a-z&&[^bc]]</tt></td>
+ * <td headers="matches"><tt>a</tt> through <tt>z</tt>,
+ * except for <tt>b</tt> and <tt>c</tt>: <tt>[ad-z]</tt> (subtraction)</td></tr>
+ * <tr><td valign="top" headers="construct classes"><tt>[a-z&&[^m-p]]</tt></td>
+ * <td headers="matches"><tt>a</tt> through <tt>z</tt>,
+ * and not <tt>m</tt> through <tt>p</tt>: <tt>[a-lq-z]</tt>(subtraction)</td></tr>
+ * <tr><th> </th></tr>
+ *
+ * <tr align="left"><th colspan="2" id="predef">Predefined character classes</th></tr>
+ *
+ * <tr><td valign="top" headers="construct predef"><tt>.</tt></td>
+ * <td headers="matches">Any character (may or may not match <a href="#lt">line terminators</a>)</td></tr>
+ * <tr><td valign="top" headers="construct predef"><tt>\d</tt></td>
+ * <td headers="matches">A digit: <tt>[0-9]</tt></td></tr>
+ * <tr><td valign="top" headers="construct predef"><tt>\D</tt></td>
+ * <td headers="matches">A non-digit: <tt>[^0-9]</tt></td></tr>
+ * <tr><td valign="top" headers="construct predef"><tt>\s</tt></td>
+ * <td headers="matches">A whitespace character: <tt>[ \t\n\x0B\f\r]</tt></td></tr>
+ * <tr><td valign="top" headers="construct predef"><tt>\S</tt></td>
+ * <td headers="matches">A non-whitespace character: <tt>[^\s]</tt></td></tr>
+ * <tr><td valign="top" headers="construct predef"><tt>\w</tt></td>
+ * <td headers="matches">A word character: <tt>[a-zA-Z_0-9]</tt></td></tr>
+ * <tr><td valign="top" headers="construct predef"><tt>\W</tt></td>
+ * <td headers="matches">A non-word character: <tt>[^\w]</tt></td></tr>
+ *
+ * <tr><th> </th></tr>
+ * <tr align="left"><th colspan="2" id="posix">POSIX character classes</b> (US-ASCII only)<b></th></tr>
+ *
+ * <tr><td valign="top" headers="construct posix"><tt>\p{Lower}</tt></td>
+ * <td headers="matches">A lower-case alphabetic character: <tt>[a-z]</tt></td></tr>
+ * <tr><td valign="top" headers="construct posix"><tt>\p{Upper}</tt></td>
+ * <td headers="matches">An upper-case alphabetic character:<tt>[A-Z]</tt></td></tr>
+ * <tr><td valign="top" headers="construct posix"><tt>\p{ASCII}</tt></td>
+ * <td headers="matches">All ASCII:<tt>[\x00-\x7F]</tt></td></tr>
+ * <tr><td valign="top" headers="construct posix"><tt>\p{Alpha}</tt></td>
+ * <td headers="matches">An alphabetic character:<tt>[\p{Lower}\p{Upper}]</tt></td></tr>
+ * <tr><td valign="top" headers="construct posix"><tt>\p{Digit}</tt></td>
+ * <td headers="matches">A decimal digit: <tt>[0-9]</tt></td></tr>
+ * <tr><td valign="top" headers="construct posix"><tt>\p{Alnum}</tt></td>
+ * <td headers="matches">An alphanumeric character:<tt>[\p{Alpha}\p{Digit}]</tt></td></tr>
+ * <tr><td valign="top" headers="construct posix"><tt>\p{Punct}</tt></td>
+ * <td headers="matches">Punctuation: One of <tt>!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~</tt></td></tr>
+ * <!-- <tt>[\!"#\$%&'\(\)\*\+,\-\./:;\<=\>\?@\[\\\]\^_`\{\|\}~]</tt>
+ * <tt>[\X21-\X2F\X31-\X40\X5B-\X60\X7B-\X7E]</tt> -->
+ * <tr><td valign="top" headers="construct posix"><tt>\p{Graph}</tt></td>
+ * <td headers="matches">A visible character: <tt>[\p{Alnum}\p{Punct}]</tt></td></tr>
+ * <tr><td valign="top" headers="construct posix"><tt>\p{Print}</tt></td>
+ * <td headers="matches">A printable character: <tt>[\p{Graph}\x20]</tt></td></tr>
+ * <tr><td valign="top" headers="construct posix"><tt>\p{Blank}</tt></td>
+ * <td headers="matches">A space or a tab: <tt>[ \t]</tt></td></tr>
+ * <tr><td valign="top" headers="construct posix"><tt>\p{Cntrl}</tt></td>
+ * <td headers="matches">A control character: <tt>[\x00-\x1F\x7F]</tt></td></tr>
+ * <tr><td valign="top" headers="construct posix"><tt>\p{XDigit}</tt></td>
+ * <td headers="matches">A hexadecimal digit: <tt>[0-9a-fA-F]</tt></td></tr>
+ * <tr><td valign="top" headers="construct posix"><tt>\p{Space}</tt></td>
+ * <td headers="matches">A whitespace character: <tt>[ \t\n\x0B\f\r]</tt></td></tr>
+ *
+ * <tr><th> </th></tr>
+ * <tr align="left"><th colspan="2">java.lang.Character classes (simple <a href="#jcc">java character type</a>)</th></tr>
+ *
+ * <tr><td valign="top"><tt>\p{javaLowerCase}</tt></td>
+ * <td>Equivalent to java.lang.Character.isLowerCase()</td></tr>
+ * <tr><td valign="top"><tt>\p{javaUpperCase}</tt></td>
+ * <td>Equivalent to java.lang.Character.isUpperCase()</td></tr>
+ * <tr><td valign="top"><tt>\p{javaWhitespace}</tt></td>
+ * <td>Equivalent to java.lang.Character.isWhitespace()</td></tr>
+ * <tr><td valign="top"><tt>\p{javaMirrored}</tt></td>
+ * <td>Equivalent to java.lang.Character.isMirrored()</td></tr>
+ *
+ * <tr><th> </th></tr>
+ * <tr align="left"><th colspan="2" id="unicode">Classes for Unicode blocks and categories</th></tr>
+ *
+ * <tr><td valign="top" headers="construct unicode"><tt>\p{InGreek}</tt></td>
+ * <td headers="matches">A character in the Greek block (simple <a href="#ubc">block</a>)</td></tr>
+ * <tr><td valign="top" headers="construct unicode"><tt>\p{Lu}</tt></td>
+ * <td headers="matches">An uppercase letter (simple <a href="#ubc">category</a>)</td></tr>
+ * <tr><td valign="top" headers="construct unicode"><tt>\p{Sc}</tt></td>
+ * <td headers="matches">A currency symbol</td></tr>
+ * <tr><td valign="top" headers="construct unicode"><tt>\P{InGreek}</tt></td>
+ * <td headers="matches">Any character except one in the Greek block (negation)</td></tr>
+ * <tr><td valign="top" headers="construct unicode"><tt>[\p{L}&&[^\p{Lu}]] </tt></td>
+ * <td headers="matches">Any letter except an uppercase letter (subtraction)</td></tr>
+ *
+ * <tr><th> </th></tr>
+ * <tr align="left"><th colspan="2" id="bounds">Boundary matchers</th></tr>
+ *
+ * <tr><td valign="top" headers="construct bounds"><tt>^</tt></td>
+ * <td headers="matches">The beginning of a line</td></tr>
+ * <tr><td valign="top" headers="construct bounds"><tt>$</tt></td>
+ * <td headers="matches">The end of a line</td></tr>
+ * <tr><td valign="top" headers="construct bounds"><tt>\b</tt></td>
+ * <td headers="matches">A word boundary</td></tr>
+ * <tr><td valign="top" headers="construct bounds"><tt>\B</tt></td>
+ * <td headers="matches">A non-word boundary</td></tr>
+ * <tr><td valign="top" headers="construct bounds"><tt>\A</tt></td>
+ * <td headers="matches">The beginning of the input</td></tr>
+ * <tr><td valign="top" headers="construct bounds"><tt>\G</tt></td>
+ * <td headers="matches">The end of the previous match</td></tr>
+ * <tr><td valign="top" headers="construct bounds"><tt>\Z</tt></td>
+ * <td headers="matches">The end of the input but for the final
+ * <a href="#lt">terminator</a...
[truncated message content] |
|
From: <ls...@us...> - 2007-05-13 17:09:32
|
Revision: 3197
http://jnode.svn.sourceforge.net/jnode/?rev=3197&view=rev
Author: lsantha
Date: 2007-05-13 10:09:31 -0700 (Sun, 13 May 2007)
Log Message:
-----------
First merges of OpenJDK.
Added Paths:
-----------
trunk/core/src/openjdk/java/ustil/regex/MatchResult.java
Added: trunk/core/src/openjdk/java/ustil/regex/MatchResult.java
===================================================================
--- trunk/core/src/openjdk/java/ustil/regex/MatchResult.java (rev 0)
+++ trunk/core/src/openjdk/java/ustil/regex/MatchResult.java 2007-05-13 17:09:31 UTC (rev 3197)
@@ -0,0 +1,189 @@
+/*
+ * Copyright 2003-2004 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package java.util.regex;
+
+/**
+ * The result of a match operation.
+ *
+ * <p>This interface contains query methods used to determine the
+ * results of a match against a regular expression. The match boundaries,
+ * groups and group boundaries can be seen but not modified through
+ * a <code>MatchResult</code>.
+ *
+ * @author Michael McCloskey
+ * @version 1.12 05/05/07
+ * @see Matcher
+ * @since 1.5
+ */
+public interface MatchResult {
+
+ /**
+ * Returns the start index of the match.
+ *
+ * @return The index of the first character matched
+ *
+ * @throws IllegalStateException
+ * If no match has yet been attempted,
+ * or if the previous match operation failed
+ */
+ public int start();
+
+ /**
+ * Returns the start index of the subsequence captured by the given group
+ * during this match.
+ *
+ * <p> <a href="Pattern.html#cg">Capturing groups</a> are indexed from left
+ * to right, starting at one. Group zero denotes the entire pattern, so
+ * the expression <i>m.</i><tt>start(0)</tt> is equivalent to
+ * <i>m.</i><tt>start()</tt>. </p>
+ *
+ * @param group
+ * The index of a capturing group in this matcher's pattern
+ *
+ * @return The index of the first character captured by the group,
+ * or <tt>-1</tt> if the match was successful but the group
+ * itself did not match anything
+ *
+ * @throws IllegalStateException
+ * If no match has yet been attempted,
+ * or if the previous match operation failed
+ *
+ * @throws IndexOutOfBoundsException
+ * If there is no capturing group in the pattern
+ * with the given index
+ */
+ public int start(int group);
+
+ /**
+ * Returns the offset after the last character matched. </p>
+ *
+ * @return @return The offset after the last character matched
+ *
+ * @throws IllegalStateException
+ * If no match has yet been attempted,
+ * or if the previous match operation failed
+ */
+ public int end();
+
+ /**
+ * Returns the offset after the last character of the subsequence
+ * captured by the given group during this match.
+ *
+ * <p> <a href="Pattern.html#cg">Capturing groups</a> are indexed from left
+ * to right, starting at one. Group zero denotes the entire pattern, so
+ * the expression <i>m.</i><tt>end(0)</tt> is equivalent to
+ * <i>m.</i><tt>end()</tt>. </p>
+ *
+ * @param group
+ * The index of a capturing group in this matcher's pattern
+ *
+ * @return The offset after the last character captured by the group,
+ * or <tt>-1</tt> if the match was successful
+ * but the group itself did not match anything
+ *
+ * @throws IllegalStateException
+ * If no match has yet been attempted,
+ * or if the previous match operation failed
+ *
+ * @throws IndexOutOfBoundsException
+ * If there is no capturing group in the pattern
+ * with the given index
+ */
+ public int end(int group);
+
+ /**
+ * Returns the input subsequence matched by the previous match.
+ *
+ * <p> For a matcher <i>m</i> with input sequence <i>s</i>,
+ * the expressions <i>m.</i><tt>group()</tt> and
+ * <i>s.</i><tt>substring(</tt><i>m.</i><tt>start(),</tt> <i>m.</i><tt>end())</tt>
+ * are equivalent. </p>
+ *
+ * <p> Note that some patterns, for example <tt>a*</tt>, match the empty
+ * string. This method will return the empty string when the pattern
+ * successfully matches the empty string in the input. </p>
+ *
+ * @return The (possibly empty) subsequence matched by the previous match,
+ * in string form
+ *
+ * @throws IllegalStateException
+ * If no match has yet been attempted,
+ * or if the previous match operation failed
+ */
+ public String group();
+
+ /**
+ * Returns the input subsequence captured by the given group during the
+ * previous match operation.
+ *
+ * <p> For a matcher <i>m</i>, input sequence <i>s</i>, and group index
+ * <i>g</i>, the expressions <i>m.</i><tt>group(</tt><i>g</i><tt>)</tt> and
+ * <i>s.</i><tt>substring(</tt><i>m.</i><tt>start(</tt><i>g</i><tt>),</tt> <i>m.</i><tt>end(</tt><i>g</i><tt>))</tt>
+ * are equivalent. </p>
+ *
+ * <p> <a href="Pattern.html#cg">Capturing groups</a> are indexed from left
+ * to right, starting at one. Group zero denotes the entire pattern, so
+ * the expression <tt>m.group(0)</tt> is equivalent to <tt>m.group()</tt>.
+ * </p>
+ *
+ * <p> If the match was successful but the group specified failed to match
+ * any part of the input sequence, then <tt>null</tt> is returned. Note
+ * that some groups, for example <tt>(a*)</tt>, match the empty string.
+ * This method will return the empty string when such a group successfully
+ * matches the empty string in the input. </p>
+ *
+ * @param group
+ * The index of a capturing group in this matcher's pattern
+ *
+ * @return The (possibly empty) subsequence captured by the group
+ * during the previous match, or <tt>null</tt> if the group
+ * failed to match part of the input
+ *
+ * @throws IllegalStateException
+ * If no match has yet been attempted,
+ * or if the previous match operation failed
+ *
+ * @throws IndexOutOfBoundsException
+ * If there is no capturing group in the pattern
+ * with the given index
+ */
+ public String group(int group);
+
+ /**
+ * Returns the number of capturing groups in this match result's pattern.
+ *
+ * <p> Group zero denotes the entire pattern by convention. It is not
+ * included in this count.
+ *
+ * <p> Any non-negative integer smaller than or equal to the value
+ * returned by this method is guaranteed to be a valid group index for
+ * this matcher. </p>
+ *
+ * @return The number of capturing groups in this matcher's pattern
+ */
+ public int groupCount();
+
+}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ls...@us...> - 2007-05-13 17:07:12
|
Revision: 3196
http://jnode.svn.sourceforge.net/jnode/?rev=3196&view=rev
Author: lsantha
Date: 2007-05-13 10:07:07 -0700 (Sun, 13 May 2007)
Log Message:
-----------
First merges of OpenJDK.
Added Paths:
-----------
trunk/core/src/openjdk/java/ustil/regex/package.html
Added: trunk/core/src/openjdk/java/ustil/regex/package.html
===================================================================
--- trunk/core/src/openjdk/java/ustil/regex/package.html (rev 0)
+++ trunk/core/src/openjdk/java/ustil/regex/package.html 2007-05-13 17:07:07 UTC (rev 3196)
@@ -0,0 +1,67 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
+<!--
+Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation. Sun designates this
+particular file as subject to the "Classpath" exception as provided
+by Sun in the LICENSE file that accompanied this code.
+
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+CA 95054 USA or visit www.sun.com if you need additional information or
+have any questions.
+-->
+
+</head>
+<body bgcolor="white">
+
+Classes for matching character sequences against patterns specified by regular
+expressions.
+
+<p> An instance of the {@link java.util.regex.Pattern} class represents a
+regular expression that is specified in string form in a syntax similar to
+that used by Perl.
+
+<p> Instances of the {@link java.util.regex.Matcher} class are used to match
+character sequences against a given pattern. Input is provided to matchers via
+the {@link java.lang.CharSequence} interface in order to support matching
+against characters from a wide variety of input sources. </p>
+
+<p> Unless otherwise noted, passing a <tt>null</tt> argument to a method
+in any class or interface in this package will cause a
+{@link java.lang.NullPointerException NullPointerException} to be thrown.
+
+<h2>Related Documentation</h2>
+
+<p> An excellent tutorial and overview of regular expressions is <a
+href="http://www.oreilly.com/catalog/regex/"><i>Mastering Regular
+Expressions</i>, Jeffrey E. F. Friedl, O'Reilly and Associates, 1997.</a> </p>
+
+<!--
+For overviews, tutorials, examples, guides, and tool documentation, please see:
+<ul>
+ <li><a href="">##### REFER TO NON-SPEC DOCUMENTATION HERE #####</a>
+</ul>
+-->
+
+@since 1.4
+@version 1.12, 07/05/05
+@author Mike McCloskey
+@author Mark Reinhold
+
+</body>
+</html>
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <ls...@us...> - 2007-05-13 17:03:36
|
Revision: 3195
http://jnode.svn.sourceforge.net/jnode/?rev=3195&view=rev
Author: lsantha
Date: 2007-05-13 10:03:29 -0700 (Sun, 13 May 2007)
Log Message:
-----------
First merges of OpenJDK.
Added Paths:
-----------
trunk/core/src/openjdk/java/ustil/
trunk/core/src/openjdk/java/ustil/regex/
trunk/core/src/openjdk/java/ustil/regex/ASCII.java
Added: trunk/core/src/openjdk/java/ustil/regex/ASCII.java
===================================================================
--- trunk/core/src/openjdk/java/ustil/regex/ASCII.java (rev 0)
+++ trunk/core/src/openjdk/java/ustil/regex/ASCII.java 2007-05-13 17:03:29 UTC (rev 3195)
@@ -0,0 +1,274 @@
+/*
+ * Copyright 1999-2000 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package java.util.regex;
+
+
+/**
+ * Utility class that implements the standard C ctype functionality.
+ *
+ * @author Hong Zhang
+ */
+
+final class ASCII {
+
+ static final int UPPER = 0x00000100;
+
+ static final int LOWER = 0x00000200;
+
+ static final int DIGIT = 0x00000400;
+
+ static final int SPACE = 0x00000800;
+
+ static final int PUNCT = 0x00001000;
+
+ static final int CNTRL = 0x00002000;
+
+ static final int BLANK = 0x00004000;
+
+ static final int HEX = 0x00008000;
+
+ static final int UNDER = 0x00010000;
+
+ static final int ASCII = 0x0000FF00;
+
+ static final int ALPHA = (UPPER|LOWER);
+
+ static final int ALNUM = (UPPER|LOWER|DIGIT);
+
+ static final int GRAPH = (PUNCT|UPPER|LOWER|DIGIT);
+
+ static final int WORD = (UPPER|LOWER|UNDER|DIGIT);
+
+ static final int XDIGIT = (HEX);
+
+ private static final int[] ctype = new int[] {
+ CNTRL, /* 00 (NUL) */
+ CNTRL, /* 01 (SOH) */
+ CNTRL, /* 02 (STX) */
+ CNTRL, /* 03 (ETX) */
+ CNTRL, /* 04 (EOT) */
+ CNTRL, /* 05 (ENQ) */
+ CNTRL, /* 06 (ACK) */
+ CNTRL, /* 07 (BEL) */
+ CNTRL, /* 08 (BS) */
+ SPACE+CNTRL+BLANK, /* 09 (HT) */
+ SPACE+CNTRL, /* 0A (LF) */
+ SPACE+CNTRL, /* 0B (VT) */
+ SPACE+CNTRL, /* 0C (FF) */
+ SPACE+CNTRL, /* 0D (CR) */
+ CNTRL, /* 0E (SI) */
+ CNTRL, /* 0F (SO) */
+ CNTRL, /* 10 (DLE) */
+ CNTRL, /* 11 (DC1) */
+ CNTRL, /* 12 (DC2) */
+ CNTRL, /* 13 (DC3) */
+ CNTRL, /* 14 (DC4) */
+ CNTRL, /* 15 (NAK) */
+ CNTRL, /* 16 (SYN) */
+ CNTRL, /* 17 (ETB) */
+ CNTRL, /* 18 (CAN) */
+ CNTRL, /* 19 (EM) */
+ CNTRL, /* 1A (SUB) */
+ CNTRL, /* 1B (ESC) */
+ CNTRL, /* 1C (FS) */
+ CNTRL, /* 1D (GS) */
+ CNTRL, /* 1E (RS) */
+ CNTRL, /* 1F (US) */
+ SPACE+BLANK, /* 20 SPACE */
+ PUNCT, /* 21 ! */
+ PUNCT, /* 22 " */
+ PUNCT, /* 23 # */
+ PUNCT, /* 24 $ */
+ PUNCT, /* 25 % */
+ PUNCT, /* 26 & */
+ PUNCT, /* 27 ' */
+ PUNCT, /* 28 ( */
+ PUNCT, /* 29 ) */
+ PUNCT, /* 2A * */
+ PUNCT, /* 2B + */
+ PUNCT, /* 2C , */
+ PUNCT, /* 2D - */
+ PUNCT, /* 2E . */
+ PUNCT, /* 2F / */
+ DIGIT+HEX+0, /* 30 0 */
+ DIGIT+HEX+1, /* 31 1 */
+ DIGIT+HEX+2, /* 32 2 */
+ DIGIT+HEX+3, /* 33 3 */
+ DIGIT+HEX+4, /* 34 4 */
+ DIGIT+HEX+5, /* 35 5 */
+ DIGIT+HEX+6, /* 36 6 */
+ DIGIT+HEX+7, /* 37 7 */
+ DIGIT+HEX+8, /* 38 8 */
+ DIGIT+HEX+9, /* 39 9 */
+ PUNCT, /* 3A : */
+ PUNCT, /* 3B ; */
+ PUNCT, /* 3C < */
+ PUNCT, /* 3D = */
+ PUNCT, /* 3E > */
+ PUNCT, /* 3F ? */
+ PUNCT, /* 40 @ */
+ UPPER+HEX+10, /* 41 A */
+ UPPER+HEX+11, /* 42 B */
+ UPPER+HEX+12, /* 43 C */
+ UPPER+HEX+13, /* 44 D */
+ UPPER+HEX+14, /* 45 E */
+ UPPER+HEX+15, /* 46 F */
+ UPPER+16, /* 47 G */
+ UPPER+17, /* 48 H */
+ UPPER+18, /* 49 I */
+ UPPER+19, /* 4A J */
+ UPPER+20, /* 4B K */
+ UPPER+21, /* 4C L */
+ UPPER+22, /* 4D M */
+ UPPER+23, /* 4E N */
+ UPPER+24, /* 4F O */
+ UPPER+25, /* 50 P */
+ UPPER+26, /* 51 Q */
+ UPPER+27, /* 52 R */
+ UPPER+28, /* 53 S */
+ UPPER+29, /* 54 T */
+ UPPER+30, /* 55 U */
+ UPPER+31, /* 56 V */
+ UPPER+32, /* 57 W */
+ UPPER+33, /* 58 X */
+ UPPER+34, /* 59 Y */
+ UPPER+35, /* 5A Z */
+ PUNCT, /* 5B [ */
+ PUNCT, /* 5C \ */
+ PUNCT, /* 5D ] */
+ PUNCT, /* 5E ^ */
+ PUNCT|UNDER, /* 5F _ */
+ PUNCT, /* 60 ` */
+ LOWER+HEX+10, /* 61 a */
+ LOWER+HEX+11, /* 62 b */
+ LOWER+HEX+12, /* 63 c */
+ LOWER+HEX+13, /* 64 d */
+ LOWER+HEX+14, /* 65 e */
+ LOWER+HEX+15, /* 66 f */
+ LOWER+16, /* 67 g */
+ LOWER+17, /* 68 h */
+ LOWER+18, /* 69 i */
+ LOWER+19, /* 6A j */
+ LOWER+20, /* 6B k */
+ LOWER+21, /* 6C l */
+ LOWER+22, /* 6D m */
+ LOWER+23, /* 6E n */
+ LOWER+24, /* 6F o */
+ LOWER+25, /* 70 p */
+ LOWER+26, /* 71 q */
+ LOWER+27, /* 72 r */
+ LOWER+28, /* 73 s */
+ LOWER+29, /* 74 t */
+ LOWER+30, /* 75 u */
+ LOWER+31, /* 76 v */
+ LOWER+32, /* 77 w */
+ LOWER+33, /* 78 x */
+ LOWER+34, /* 79 y */
+ LOWER+35, /* 7A z */
+ PUNCT, /* 7B { */
+ PUNCT, /* 7C | */
+ PUNCT, /* 7D } */
+ PUNCT, /* 7E ~ */
+ CNTRL, /* 7F (DEL) */
+ };
+
+ static int getType(int ch) {
+ return ((ch & 0xFFFFFF80) == 0 ? ctype[ch] : 0);
+ }
+
+ static boolean isType(int ch, int type) {
+ return (getType(ch) & type) != 0;
+ }
+
+ static boolean isAscii(int ch) {
+ return ((ch & 0xFFFFFF80) == 0);
+ }
+
+ static boolean isAlpha(int ch) {
+ return isType(ch, ALPHA);
+ }
+
+ static boolean isDigit(int ch) {
+ return ((ch-'0')|('9'-ch)) >= 0;
+ }
+
+ static boolean isAlnum(int ch) {
+ return isType(ch, ALNUM);
+ }
+
+ static boolean isGraph(int ch) {
+ return isType(ch, GRAPH);
+ }
+
+ static boolean isPrint(int ch) {
+ return ((ch-0x20)|(0x7E-ch)) >= 0;
+ }
+
+ static boolean isPunct(int ch) {
+ return isType(ch, PUNCT);
+ }
+
+ static boolean isSpace(int ch) {
+ return isType(ch, SPACE);
+ }
+
+ static boolean isHexDigit(int ch) {
+ return isType(ch, HEX);
+ }
+
+ static boolean isOctDigit(int ch) {
+ return ((ch-'0')|('7'-ch)) >= 0;
+ }
+
+ static boolean isCntrl(int ch) {
+ return isType(ch, CNTRL);
+ }
+
+ static boolean isLower(int ch) {
+ return ((ch-'a')|('z'-ch)) >= 0;
+ }
+
+ static boolean isUpper(int ch) {
+ return ((ch-'A')|('Z'-ch)) >= 0;
+ }
+
+ static boolean isWord(int ch) {
+ return isType(ch, WORD);
+ }
+
+ static int toDigit(int ch) {
+ return (ctype[ch & 0x7F] & 0x3F);
+ }
+
+ static int toLower(int ch) {
+ return isUpper(ch) ? (ch + 0x20) : ch;
+ }
+
+ static int toUpper(int ch) {
+ return isLower(ch) ? (ch - 0x20) : ch;
+ }
+
+}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|