adds GWT code

This commit is contained in:
Timothy Prepscius 2013-07-21 12:49:20 -04:00
parent 25dcdeed44
commit 55b423621f
281 changed files with 15703 additions and 0 deletions

21
gwt/.classpath Normal file
View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry including="*.xml" kind="src" path="jre-gwt"/>
<classpathentry kind="src" path="jre"/>
<classpathentry kind="lib" path="/Applications/eclipse/plugins/com.google.gwt.eclipse.sdkbundle_2.5.1/gwt-2.5.1/gwt-user.jar">
<attributes>
<attribute name="javadoc_location" value="file:/Applications/eclipse/plugins/com.google.gwt.eclipse.sdkbundle_2.5.1/gwt-2.5.1/doc/javadoc/"/>
</attributes>
</classpathentry>
<classpathentry kind="lib" path="/Applications/eclipse/plugins/com.google.gwt.eclipse.sdkbundle_2.5.1/gwt-2.5.1/gwt-dev.jar">
<attributes>
<attribute name="javadoc_location" value="file:/Applications/eclipse/plugins/com.google.gwt.eclipse.sdkbundle_2.5.1/gwt-2.5.1/doc/javadoc/"/>
</attributes>
</classpathentry>
<classpathentry kind="lib" path="/Applications/eclipse/plugins/com.google.gwt.eclipse.sdkbundle_2.5.1/gwt-2.5.1/validation-api-1.0.0.GA-sources.jar"/>
<classpathentry kind="lib" path="/Applications/eclipse/plugins/com.google.gwt.eclipse.sdkbundle_2.5.1/gwt-2.5.1/validation-api-1.0.0.GA.jar" sourcepath="/Applications/eclipse/plugins/com.google.gwt.eclipse.sdkbundle_2.5.1/gwt-2.5.1/validation-api-1.0.0.GA-sources.jar"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="lib" path="lib/gwtexporter-2.5.0-SNAPSHOT.jar"/>
<classpathentry kind="output" path="war/WEB-INF/classes"/>
</classpath>

8
gwt/.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
.gwt
gwt-unitCache
war/WEB-INF
war/mailiverse_gwt
war/*.html
war/*.js
war/*.css
war/rev/

34
gwt/.project Normal file
View File

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>Mailiverse-GWT</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.wst.common.project.facet.core.builder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.google.gdt.eclipse.core.webAppProjectValidator</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>com.google.gwt.eclipse.core.gwtProjectValidator</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
<nature>com.google.gwt.eclipse.core.gwtNature</nature>
</natures>
</projectDescription>

View File

@ -0,0 +1,4 @@
eclipse.preferences.version=1
filesCopiedToWebInfLib=
googleCloudSqlEnabled=false
localDevMySqlEnabled=true

View File

@ -0,0 +1,5 @@
eclipse.preferences.version=1
jarsExcludedFromWebInfLib=
launchConfigExternalUrlPrefix=
warSrcDir=war
warSrcDirIsOutput=true

View File

@ -0,0 +1,4 @@
eclipse.preferences.version=1
entryPointModules=
filesCopiedToWebInfLib=gwt-servlet.jar
gwtCompileSettings=PGd3dC1jb21waWxlLXNldHRpbmdzPjxsb2ctbGV2ZWw+SU5GTzwvbG9nLWxldmVsPjxvdXRwdXQtc3R5bGU+T0JGVVNDQVRFRDwvb3V0cHV0LXN0eWxlPjxleHRyYS1hcmdzPjwhW0NEQVRBW11dPjwvZXh0cmEtYXJncz48dm0tYXJncz48IVtDREFUQVstWG14NTEybSAtRGd3dC51c2VhcmNoaXZlcz1mYWxzZV1dPjwvdm0tYXJncz48ZW50cnktcG9pbnQtbW9kdWxlPmNvbS5tYWlsaXZlcnNlLmd3dC5NYWlsaXZlcnNlX0dXVDwvZW50cnktcG9pbnQtbW9kdWxlPjwvZ3d0LWNvbXBpbGUtc2V0dGluZ3M+

View File

@ -0,0 +1,11 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.7
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.7

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<faceted-project>
<installed facet="java" version="1.7"/>
</faceted-project>

4
gwt/Notes.txt Normal file
View File

@ -0,0 +1,4 @@
Todo:
Make random come from javascript secure random.
Make login pages not be black.

5
gwt/clean Executable file
View File

@ -0,0 +1,5 @@
rm -rf gwt-unitCache
rm -rf war/WEB-INF/classes/
rm -rf war/WEB-INF/deploy/
rm war/mailiverse_gwt/*.cache.html

5
gwt/jre-gwt/JRE.gwt.xml Normal file
View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.4.0//EN" "http://google-web-toolkit.googlecode.com/svn/tags/2.4.0/distro-source/core/src/gwt-module.dtd">
<module>
<super-source path='jre'/>
</module>

1
gwt/jre-gwt/jre Symbolic link
View File

@ -0,0 +1 @@
../jre

View File

@ -0,0 +1,375 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package java.io;
/**
* <code>BufferedInputStream</code> is a class which takes an input stream and
* <em>buffers</em> the input. In this way, costly interaction with the
* original input stream can be minimized by reading buffered amounts of data
* infrequently. The drawback is that extra space is required to hold the buffer
* and that copying takes place when reading that buffer.
*
* @see BufferedOutputStream
*/
public class BufferedInputStream extends FilterInputStream {
/**
* The buffer containing the current bytes read from the target InputStream.
*/
protected byte[] buf;
/**
* The total number of bytes inside the byte array <code>buf</code>.
*/
protected int count;
/**
* The current limit, which when passed, invalidates the current mark.
*/
protected int marklimit;
/**
* The currently marked position. -1 indicates no mark has been set or the
* mark has been invalidated.
*/
protected int markpos = -1;
/**
* The current position within the byte array <code>buf</code>.
*/
protected int pos;
private boolean closed = false;
/**
* Constructs a new <code>BufferedInputStream</code> on the InputStream
* <code>in</code>. The default buffer size (8Kb) is allocated and all
* reads can now be filtered through this stream.
*
* @param in
* the InputStream to buffer reads on.
*/
public BufferedInputStream(InputStream in) {
super(in);
buf = new byte[8192];
}
/**
* Constructs a new BufferedInputStream on the InputStream <code>in</code>.
* The buffer size is specified by the parameter <code>size</code> and all
* reads can now be filtered through this BufferedInputStream.
*
* @param in
* the InputStream to buffer reads on.
* @param size
* the size of buffer to allocate.
*/
public BufferedInputStream(InputStream in, int size) {
super(in);
if (size <= 0) {
// K0058=size must be > 0
throw new IllegalArgumentException(Msg.getString("K0058")); //$NON-NLS-1$
}
buf = new byte[size];
}
/**
* Answers an int representing the number of bytes that are available before
* this BufferedInputStream will block. This method returns the number of
* bytes available in the buffer plus those available in the target stream.
*
* @return the number of bytes available before blocking.
*
* @throws IOException
* If an error occurs in this stream.
*/
@Override
public synchronized int available() throws IOException {
if (buf == null) {
// K0059=Stream is closed
throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$
}
return count - pos + in.available();
}
/**
* Close this BufferedInputStream. This implementation closes the target
* stream and releases any resources associated with it.
*
* @throws IOException
* If an error occurs attempting to close this stream.
*/
@Override
public synchronized void close() throws IOException {
if (null != in) {
super.close();
in = null;
}
buf = null;
closed = true;
}
private int fillbuf() throws IOException {
if (markpos == -1 || (pos - markpos >= marklimit)) {
/* Mark position not set or exceeded readlimit */
int result = in.read(buf);
if (result > 0) {
markpos = -1;
pos = 0;
count = result == -1 ? 0 : result;
}
return result;
}
if (markpos == 0 && marklimit > buf.length) {
/* Increase buffer size to accomodate the readlimit */
int newLength = buf.length * 2;
if (newLength > marklimit) {
newLength = marklimit;
}
byte[] newbuf = new byte[newLength];
System.arraycopy(buf, 0, newbuf, 0, buf.length);
buf = newbuf;
} else if (markpos > 0) {
System.arraycopy(buf, markpos, buf, 0, buf.length - markpos);
}
/* Set the new position and mark position */
pos -= markpos;
count = markpos = 0;
int bytesread = in.read(buf, pos, buf.length - pos);
count = bytesread <= 0 ? pos : pos + bytesread;
return bytesread;
}
/**
* Set a Mark position in this BufferedInputStream. The parameter
* <code>readLimit</code> indicates how many bytes can be read before a
* mark is invalidated. Sending reset() will reposition the Stream back to
* the marked position provided <code>readLimit</code> has not been
* surpassed. The underlying buffer may be increased in size to allow
* <code>readlimit</code> number of bytes to be supported.
*
* @param readlimit
* the number of bytes to be able to read before invalidating the
* mark.
*/
@Override
public synchronized void mark(int readlimit) {
marklimit = readlimit;
markpos = pos;
}
/**
* Answers a boolean indicating whether or not this BufferedInputStream
* supports mark() and reset(). This implementation answers
* <code>true</code>.
*
* @return <code>true</code> for BufferedInputStreams.
*/
@Override
public boolean markSupported() {
return true;
}
/**
* Reads a single byte from this BufferedInputStream and returns the result
* as an int. The low-order byte is returned or -1 of the end of stream was
* encountered. If the underlying buffer does not contain any available
* bytes then it is filled and the first byte is returned.
*
* @return the byte read or -1 if end of stream.
*
* @throws IOException
* If the stream is already closed or another IOException
* occurs.
*/
@Override
public synchronized int read() throws IOException {
if (in == null) {
// K0059=Stream is closed
throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$
}
/* Are there buffered bytes available? */
if (pos >= count && fillbuf() == -1) {
return -1; /* no, fill buffer */
}
/* Did filling the buffer fail with -1 (EOF)? */
if (count - pos > 0) {
return buf[pos++] & 0xFF;
}
return -1;
}
/**
* Reads at most <code>length</code> bytes from this BufferedInputStream
* and stores them in byte array <code>buffer</code> starting at offset
* <code>offset</code>. Answer the number of bytes actually read or -1 if
* no bytes were read and end of stream was encountered. If all the buffered
* bytes have been used, a mark has not been set, and the requested number
* of bytes is larger than the receiver's buffer size, this implementation
* bypasses the buffer and simply places the results directly into
* <code>buffer</code>.
*
* @param buffer
* the byte array in which to store the read bytes.
* @param offset
* the offset in <code>buffer</code> to store the read bytes.
* @param length
* the maximum number of bytes to store in <code>buffer</code>.
* @return the number of bytes actually read or -1 if end of stream.
*
* @throws IOException
* If the stream is already closed or another IOException
* occurs.
*/
@Override
public synchronized int read(byte[] buffer, int offset, int length)
throws IOException {
if (closed) {
// K0059=Stream is closed
throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$
}
// avoid int overflow
if (offset > buffer.length - length || offset < 0 || length < 0) {
throw new IndexOutOfBoundsException();
}
if (length == 0) {
return 0;
}
if (null == buf) {
throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$
}
int required;
if (pos < count) {
/* There are bytes available in the buffer. */
int copylength = count - pos >= length ? length : count - pos;
System.arraycopy(buf, pos, buffer, offset, copylength);
pos += copylength;
if (copylength == length || in.available() == 0) {
return copylength;
}
offset += copylength;
required = length - copylength;
} else {
required = length;
}
while (true) {
int read;
/*
* If we're not marked and the required size is greater than the
* buffer, simply read the bytes directly bypassing the buffer.
*/
if (markpos == -1 && required >= buf.length) {
read = in.read(buffer, offset, required);
if (read == -1) {
return required == length ? -1 : length - required;
}
} else {
if (fillbuf() == -1) {
return required == length ? -1 : length - required;
}
read = count - pos >= required ? required : count - pos;
System.arraycopy(buf, pos, buffer, offset, read);
pos += read;
}
required -= read;
if (required == 0) {
return length;
}
if (in.available() == 0) {
return length - required;
}
offset += read;
}
}
/**
* Reset this BufferedInputStream to the last marked location. If the
* <code>readlimit</code> has been passed or no <code>mark</code> has
* been set, throw IOException. This implementation resets the target
* stream.
*
* @throws IOException
* If the stream is already closed or another IOException
* occurs.
*/
@Override
public synchronized void reset() throws IOException {
if (closed) {
// K0059=Stream is closed
throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$
}
if (-1 == markpos) {
// K005a=Mark has been invalidated.
throw new IOException(Msg.getString("K005a")); //$NON-NLS-1$
}
pos = markpos;
}
/**
* Skips <code>amount</code> number of bytes in this BufferedInputStream.
* Subsequent <code>read()</code>'s will not return these bytes unless
* <code>reset()</code> is used.
*
* @param amount
* the number of bytes to skip.
* @return the number of bytes actually skipped.
*
* @throws IOException
* If the stream is already closed or another IOException
* occurs.
*/
@Override
public synchronized long skip(long amount) throws IOException {
if (null == in) {
// K0059=Stream is closed
throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$
}
if (amount < 1) {
return 0;
}
if (count - pos >= amount) {
pos += amount;
return amount;
}
long read = count - pos;
pos = count;
if (markpos != -1) {
if (amount <= marklimit) {
if (fillbuf() == -1) {
return read;
}
if (count - pos >= amount - read) {
pos += amount - read;
return amount;
}
// Couldn't get all the bytes, skip what we read
read += (count - pos);
pos = count;
return read;
}
markpos = -1;
}
return read + in.skip(amount - read);
}
}

View File

@ -0,0 +1,485 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package java.io;
/**
* BufferedReader is a buffered character input reader. Buffering allows reading
* from character streams more efficiently. If the default size of the buffer is
* not practical, another size may be specified. Reading a character from a
* Reader class usually involves reading a character from its Stream or
* subsequent Reader. It is advisable to wrap a BufferedReader around those
* Readers whose read operations may have high latency. For example, the
* following code
*
* <pre>
* BufferedReader inReader = new BufferedReader(new FileReader(&quot;file.java&quot;));
* </pre>
*
* will buffer input for the file <code>file.java</code>.
*
* @see BufferedWriter
* @since 1.1
*/
public class BufferedReader extends Reader {
private Reader in;
private char[] buf;
private int marklimit = -1;
private int count;
private int markpos = -1;
private int pos;
/**
* Constructs a new BufferedReader on the Reader <code>in</code>. The
* default buffer size (8K) is allocated and all reads can now be filtered
* through this BufferedReader.
*
* @param in
* the Reader to buffer reads on.
*/
public BufferedReader(Reader in) {
super(in);
this.in = in;
buf = new char[8192];
}
/**
* Constructs a new BufferedReader on the Reader <code>in</code>. The
* buffer size is specified by the parameter <code>size</code> and all
* reads can now be filtered through this BufferedReader.
*
* @param in
* the Reader to buffer reads on.
* @param size
* the size of buffer to allocate.
* @throws IllegalArgumentException
* if the size is <= 0
*/
public BufferedReader(Reader in, int size) {
super(in);
if (size <= 0) {
throw new IllegalArgumentException(Msg.getString("K0058")); //$NON-NLS-1$
}
this.in = in;
buf = new char[size];
}
/**
* Close the Reader. This implementation closes the Reader being filtered
* and releases the buffer used by this reader. If this BufferedReader has
* already been closed, nothing is done.
*
* @throws IOException
* If an error occurs attempting to close this BufferedReader.
*/
@Override
public void close() throws IOException {
synchronized (lock) {
if (!isClosed()) {
in.close();
buf = null;
}
}
}
private int fillbuf() throws IOException {
if (markpos == -1 || (pos - markpos >= marklimit)) {
/* Mark position not set or exceeded readlimit */
int result = in.read(buf, 0, buf.length);
if (result > 0) {
markpos = -1;
pos = 0;
count = result == -1 ? 0 : result;
}
return result;
}
if (markpos == 0 && marklimit > buf.length) {
/* Increase buffer size to accommodate the readlimit */
int newLength = buf.length * 2;
if (newLength > marklimit) {
newLength = marklimit;
}
char[] newbuf = new char[newLength];
System.arraycopy(buf, 0, newbuf, 0, buf.length);
buf = newbuf;
} else if (markpos > 0) {
System.arraycopy(buf, markpos, buf, 0, buf.length - markpos);
}
/* Set the new position and mark position */
pos -= markpos;
count = markpos = 0;
int charsread = in.read(buf, pos, buf.length - pos);
count = charsread == -1 ? pos : pos + charsread;
return charsread;
}
/**
* Answer a boolean indicating whether or not this BufferedReader is closed.
*
* @return <code>true</code> if this reader is closed, <code>false</code>
* otherwise
*/
private boolean isClosed() {
return buf == null;
}
/**
* Set a Mark position in this BufferedReader. The parameter
* <code>readLimit</code> indicates how many characters can be read before
* a mark is invalidated. Sending reset() will reposition the reader back to
* the marked position provided <code>readLimit</code> has not been
* surpassed.
*
* @param readlimit
* an int representing how many characters must be read before
* invalidating the mark.
*
* @throws IOException
* If an error occurs attempting mark this BufferedReader.
* @throws IllegalArgumentException
* If readlimit is < 0
*/
@Override
public void mark(int readlimit) throws IOException {
if (readlimit < 0) {
throw new IllegalArgumentException();
}
synchronized (lock) {
if (isClosed()) {
throw new IOException(Msg.getString("K005b")); //$NON-NLS-1$
}
marklimit = readlimit;
markpos = pos;
}
}
/**
* Answers a boolean indicating whether or not this Reader supports mark()
* and reset(). This implementation answers <code>true</code>.
*
* @return <code>true</code> if mark() and reset() are supported,
* <code>false</code> otherwise
*/
@Override
public boolean markSupported() {
return true;
}
/**
* Reads a single character from this reader and returns the result as an
* int. The 2 higher-order characters are set to 0. If the end of reader was
* encountered then return -1. This implementation either returns a
* character from the buffer or if there are no characters available, fill
* the buffer then return a character or -1.
*
* @return the character read or -1 if end of reader.
*
* @throws IOException
* If the BufferedReader is already closed or some other IO
* error occurs.
*/
@Override
public int read() throws IOException {
synchronized (lock) {
if (isClosed()) {
throw new IOException(Msg.getString("K005b")); //$NON-NLS-1$
}
/* Are there buffered characters available? */
if (pos < count || fillbuf() != -1) {
return buf[pos++];
}
return -1;
}
}
/**
* Reads at most <code>length</code> characters from this BufferedReader
* and stores them at <code>offset</code> in the character array
* <code>buffer</code>. Returns the number of characters actually read or
* -1 if the end of reader was encountered. If all the buffered characters
* have been used, a mark has not been set, and the requested number of
* characters is larger than this Readers buffer size, this implementation
* bypasses the buffer and simply places the results directly into
* <code>buffer</code>.
*
* @param buffer
* character array to store the read characters
* @param offset
* offset in buf to store the read characters
* @param length
* maximum number of characters to read
* @return number of characters read or -1 if end of reader.
*
* @throws IOException
* If the BufferedReader is already closed or some other IO
* error occurs.
*/
@Override
public int read(char[] buffer, int offset, int length) throws IOException {
synchronized (lock) {
if (isClosed()) {
throw new IOException(Msg.getString("K005b")); //$NON-NLS-1$
}
if (offset < 0 || offset > buffer.length - length || length < 0) {
throw new IndexOutOfBoundsException();
}
if (length == 0) {
return 0;
}
int required;
if (pos < count) {
/* There are bytes available in the buffer. */
int copylength = count - pos >= length ? length : count - pos;
System.arraycopy(buf, pos, buffer, offset, copylength);
pos += copylength;
if (copylength == length || !in.ready()) {
return copylength;
}
offset += copylength;
required = length - copylength;
} else {
required = length;
}
while (true) {
int read;
/*
* If we're not marked and the required size is greater than the
* buffer, simply read the bytes directly bypassing the buffer.
*/
if (markpos == -1 && required >= buf.length) {
read = in.read(buffer, offset, required);
if (read == -1) {
return required == length ? -1 : length - required;
}
} else {
if (fillbuf() == -1) {
return required == length ? -1 : length - required;
}
read = count - pos >= required ? required : count - pos;
System.arraycopy(buf, pos, buffer, offset, read);
pos += read;
}
required -= read;
if (required == 0) {
return length;
}
if (!in.ready()) {
return length - required;
}
offset += read;
}
}
}
/**
* Answers a <code>String</code> representing the next line of text
* available in this BufferedReader. A line is represented by 0 or more
* characters followed by <code>'\n'</code>, <code>'\r'</code>,
* <code>'\r\n'</code> or end of stream. The <code>String</code> does
* not include the newline sequence.
*
* @return the contents of the line or null if no characters were read
* before end of stream.
*
* @throws IOException
* If the BufferedReader is already closed or some other IO
* error occurs.
*/
public String readLine() throws IOException {
synchronized (lock) {
if (isClosed()) {
throw new IOException(Msg.getString("K005b")); //$NON-NLS-1$
}
/* Are there buffered characters available? */
if ((pos >= count) && (fillbuf() == -1)) {
return null;
}
for (int charPos = pos; charPos < count; charPos++) {
char ch = buf[charPos];
if (ch > '\r') {
continue;
}
if (ch == '\n') {
String res = new String(buf, pos, charPos - pos);
pos = charPos + 1;
return res;
} else if (ch == '\r') {
String res = new String(buf, pos, charPos - pos);
pos = charPos + 1;
if (((pos < count) || (fillbuf() != -1))
&& (buf[pos] == '\n')) {
pos++;
}
return res;
}
}
char eol = '\0';
StringBuilder result = new StringBuilder(80);
/* Typical Line Length */
result.append(buf, pos, count - pos);
pos = count;
while (true) {
/* Are there buffered characters available? */
if (pos >= count) {
if (eol == '\n') {
return result.toString();
}
// attempt to fill buffer
if (fillbuf() == -1) {
// characters or null.
return result.length() > 0 || eol != '\0' ? result
.toString() : null;
}
}
for (int charPos = pos; charPos < count; charPos++) {
if (eol == '\0') {
if ((buf[charPos] == '\n' || buf[charPos] == '\r')) {
eol = buf[charPos];
}
} else if (eol == '\r' && (buf[charPos] == '\n')) {
if (charPos > pos) {
result.append(buf, pos, charPos - pos - 1);
}
pos = charPos + 1;
return result.toString();
} else if (eol != '\0') {
if (charPos > pos) {
result.append(buf, pos, charPos - pos - 1);
}
pos = charPos;
return result.toString();
}
}
if (eol == '\0') {
result.append(buf, pos, count - pos);
} else {
result.append(buf, pos, count - pos - 1);
}
pos = count;
}
}
}
/**
* Answers a <code>boolean</code> indicating whether or not this Reader is
* ready to be read without blocking. If the result is <code>true</code>,
* the next <code>read()</code> will not block. If the result is
* <code>false</code> this Reader may or may not block when
* <code>read()</code> is sent.
*
* @return <code>true</code> if the receiver will not block when
* <code>read()</code> is called, <code>false</code> if unknown
* or blocking will occur.
*
* @throws IOException
* If the BufferedReader is already closed or some other IO
* error occurs.
*/
@Override
public boolean ready() throws IOException {
synchronized (lock) {
if (isClosed()) {
throw new IOException(Msg.getString("K005b")); //$NON-NLS-1$
}
return ((count - pos) > 0) || in.ready();
}
}
/**
* Reset this BufferedReader's position to the last <code>mark()</code>
* location. Invocations of <code>read()/skip()</code> will occur from
* this new location. If this Reader was not marked, throw IOException.
*
* @throws IOException
* If a problem occurred, the receiver does not support
* <code>mark()/reset()</code>, or no mark has been set.
*/
@Override
public void reset() throws IOException {
synchronized (lock) {
if (isClosed()) {
throw new IOException(Msg.getString("K005b")); //$NON-NLS-1$
}
if (markpos == -1) {
throw new IOException(Msg.getString("K005c")); //$NON-NLS-1$
}
pos = markpos;
}
}
/**
* Skips <code>amount</code> number of characters in this Reader.
* Subsequent <code>read()</code>'s will not return these characters
* unless <code>reset()</code> is used. Skipping characters may invalidate
* a mark if marklimit is surpassed.
*
* @param amount
* the maximum number of characters to skip.
* @return the number of characters actually skipped.
*
* @throws IOException
* If the BufferedReader is already closed or some other IO
* error occurs.
* @throws IllegalArgumentException
* If amount is negative
*/
@Override
public long skip(long amount) throws IOException {
if (amount < 0) {
throw new IllegalArgumentException();
}
synchronized (lock) {
if (isClosed()) {
throw new IOException(Msg.getString("K005b")); //$NON-NLS-1$
}
if (amount < 1) {
return 0;
}
if (count - pos >= amount) {
pos += amount;
return amount;
}
long read = count - pos;
pos = count;
while (read < amount) {
if (fillbuf() == -1) {
return read;
}
if (count - pos >= amount - read) {
pos += amount - read;
return amount;
}
// Couldn't get all the characters, skip what we read
read += (count - pos);
pos = count;
}
return amount;
}
}
}

View File

@ -0,0 +1,69 @@
/*
* Copyright 2010 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package java.io;
public class ByteArrayInputStream extends InputStream {
protected byte[] buf;
protected int pos = 0;
protected int start = 0;
protected int mark = 0;
protected int count;
public ByteArrayInputStream(byte[] data) {
this.buf = data;
this.count = data.length;
}
public ByteArrayInputStream(byte[] data, int offset, int len) {
this.buf = data;
count = offset + len;
this.mark = this.start = this.pos = offset;
}
@Override
public int read() {
return pos < count ? (buf[pos++] & 0xFF) : -1;
}
@Override
public int available() {
return count - pos;
}
@Override
public long skip(long n) throws IOException, IllegalArgumentException {
// TODO Auto-generated method stub
pos += n;
return pos;
}
@Override
public void reset() throws IOException {
pos = mark;
}
@Override
public void mark(int readAheadLimit) {
mark = pos;
}
@Override
public boolean markSupported() {
return true;
}
}

View File

@ -0,0 +1,67 @@
/*
* Copyright 2010 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package java.io;
import core.util.Arrays;
public class ByteArrayOutputStream extends OutputStream {
protected int count = 0;
protected byte[] buf;
public ByteArrayOutputStream() {
this(16);
}
public ByteArrayOutputStream(int initialSize) {
buf = new byte[initialSize];
}
public void write(int b) {
if (buf.length == count) {
byte[] newBuf = new byte[buf.length * 3 / 2];
Arrays.copyFromTo(buf, 0, newBuf, 0, count);
buf = newBuf;
}
buf[count++] = (byte)b;
}
public void write(byte[] ba, int start, int len) {
int end = start + len;
for (int i = start; i < end; i++) {
write(ba[i]);
}
}
public void write(byte[] ba)
{
write(ba,0, ba.length);
}
public byte[] toByteArray() {
return Arrays.copyOf(buf,count);
}
public int size() {
return count;
}
public void reset () {
count = 0;
}
}

View File

@ -0,0 +1,79 @@
package java.io;
public class DataInputStream extends FilterInputStream
{
public DataInputStream(InputStream in)
{
super(in);
}
/**
* Reads bytes from the source stream into the byte array
* <code>buffer</code>. The number of bytes actually read is returned.
*
* @param buffer
* the buffer to read bytes into
* @return the number of bytes actually read or -1 if end of stream.
*
* @throws IOException
* If a problem occurs reading from this DataInputStream.
*
* @see DataOutput#write(byte[])
* @see DataOutput#write(byte[], int, int)
*/
@Override
public final int read(byte[] buffer) throws IOException {
return in.read(buffer, 0, buffer.length);
}
/**
* Reads a 32-bit integer value from this stream.
*
* @return the next <code>int</code> value from the source stream.
*
* @throws IOException
* If a problem occurs reading from this DataInputStream.
*
* @see DataOutput#writeInt(int)
*/
public final int readInt() throws IOException {
int b1 = in.read();
int b2 = in.read();
int b3 = in.read();
int b4 = in.read();
if ((b1 | b2 | b3 | b4) < 0) {
throw new EOFException();
}
return ((b1 << 24) + (b2 << 16) + (b3 << 8) + b4);
}
/**
* Read at most <code>length</code> bytes from this DataInputStream and
* stores them in byte array <code>buffer</code> starting at
* <code>offset</code>. Answer the number of bytes actually read or -1 if
* no bytes were read and end of stream was encountered.
*
* @param buffer
* the byte array in which to store the read bytes.
* @param offset
* the offset in <code>buffer</code> to store the read bytes.
* @param length
* the maximum number of bytes to store in <code>buffer</code>.
* @return the number of bytes actually read or -1 if end of stream.
*
* @throws IOException
* If a problem occurs reading from this DataInputStream.
*
* @see DataOutput#write(byte[])
* @see DataOutput#write(byte[], int, int)
*/
@Override
public final int read(byte[] buffer, int offset, int length)
throws IOException {
return in.read(buffer, offset, length);
}
}

View File

@ -0,0 +1,49 @@
package java.io;
public class DataOutputStream extends FilterOutputStream {
protected int written;
public DataOutputStream(OutputStream out) {
super(out);
}
public void close() throws IOException
{
super.close();
}
public void write(byte buffer[], int offset, int count) throws IOException {
if (buffer == null) {
throw new NullPointerException(); //$NON-NLS-1$
}
out.write(buffer, offset, count);
written += count;
}
public void write(byte buffer[]) throws IOException
{
write(buffer, 0, buffer.length);
}
/**
* Writes a 32-bit int to this output stream. The resulting output is the 4
* bytes, highest order first, of val.
*
* @param val
* the int to be written.
*
* @throws IOException
* If an error occurs attempting to write to this
* DataOutputStream.
*
* @see DataInput#readInt()
*/
public final void writeInt(int val) throws IOException {
out.write((byte)(val >> 24));
out.write((byte)(val >> 16));
out.write((byte)(val >> 8));
out.write((byte)(val));
written += 4;
}
}

View File

@ -0,0 +1,46 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package java.io;
/**
* This End Of File (EOF) exception is thrown when a program encounters the end
* of a file or stream during an operation.
*/
public class EOFException extends IOException {
private static final long serialVersionUID = 6433858223774886977L;
/**
* Constructs a new instance of this class with its walkback filled in.
*
*/
public EOFException() {
super();
}
/**
* Constructs a new instance of this class with its walkback and message
* filled in.
*
* @param detailMessage
* The detail message for the exception.
*/
public EOFException(String detailMessage) {
super(detailMessage);
}
}

View File

@ -0,0 +1,197 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package java.io;
/**
* FilteredInputStream is a class which takes an input stream and
* <em>filters</em> the input in some way. The filtered view may be a buffered
* view or one which uncompresses data before returning bytes read.
* FilterInputStreams are meant for byte streams.
*
* @see FilterOutputStream
*/
public class FilterInputStream extends InputStream {
/**
* The target InputStream which is being filtered.
*/
protected InputStream in;
/**
* Constructs a new FilterInputStream on the InputStream <code>in</code>.
* All reads are now filtered through this stream.
*
* @param in
* The non-null InputStream to filter reads on.
*/
protected FilterInputStream(InputStream in) {
super();
this.in = in;
}
/**
* Answers a int representing the number of bytes that are available before
* this FilterInputStream will block. This method returns the number of
* bytes available in the target stream.
*
* @return the number of bytes available before blocking.
*
* @throws IOException
* If an error occurs in this stream.
*/
@Override
public int available() throws IOException {
return in.available();
}
/**
* Close this FilterInputStream. This implementation closes the target
* stream.
*
* @throws IOException
* If an error occurs attempting to close this stream.
*/
@Override
public void close() throws IOException {
in.close();
}
/**
* Set a Mark position in this FilterInputStream. The parameter
* <code>readLimit</code> indicates how many bytes can be read before a
* mark is invalidated. Sending reset() will reposition the Stream back to
* the marked position provided <code>readLimit</code> has not been
* surpassed.
* <p>
* This implementation sets a mark in the target stream.
*
* @param readlimit
* the number of bytes to be able to read before invalidating the
* mark.
*/
@Override
public synchronized void mark(int readlimit) {
in.mark(readlimit);
}
/**
* Answers a boolean indicating whether or not this FilterInputStream
* supports mark() and reset(). This implementation answers whether or not
* the target stream supports marking.
*
* @return <code>true</code> if mark() and reset() are supported,
* <code>false</code> otherwise.
*/
@Override
public boolean markSupported() {
return in.markSupported();
}
/**
* Reads a single byte from this FilterInputStream and returns the result as
* an int. The low-order byte is returned or -1 of the end of stream was
* encountered. This implementation returns a byte from the target stream.
*
* @return the byte read or -1 if end of stream.
*
* @throws IOException
* If the stream is already closed or another IOException
* occurs.
*/
@Override
public int read() throws IOException {
return in.read();
}
/**
* Reads bytes from this FilterInputStream and stores them in byte array
* <code>buffer</code>. Answer the number of bytes actually read or -1 if
* no bytes were read and end of stream was encountered. This implementation
* reads bytes from the target stream.
*
* @param buffer
* the byte array in which to store the read bytes.
* @return the number of bytes actually read or -1 if end of stream.
*
* @throws IOException
* If the stream is already closed or another IOException
* occurs.
*/
@Override
public int read(byte[] buffer) throws IOException {
return read(buffer, 0, buffer.length);
}
/**
* Reads at most <code>count</code> bytes from this FilterInputStream and
* stores them in byte array <code>buffer</code> starting at
* <code>offset</code>. Answer the number of bytes actually read or -1 if
* no bytes were read and end of stream was encountered. This implementation
* reads bytes from the target stream.
*
* @param buffer
* the byte array in which to store the read bytes.
* @param offset
* the offset in <code>buffer</code> to store the read bytes.
* @param count
* the maximum number of bytes to store in <code>buffer</code>.
* @return the number of bytes actually read or -1 if end of stream.
*
* @throws IOException
* If the stream is already closed or another IOException
* occurs.
*/
@Override
public int read(byte[] buffer, int offset, int count) throws IOException {
return in.read(buffer, offset, count);
}
/**
* Reset this FilterInputStream to the last marked location. If the
* <code>readlimit</code> has been passed or no <code>mark</code> has
* been set, throw IOException. This implementation resets the target
* stream.
*
* @throws IOException
* If the stream is already closed or another IOException
* occurs.
*/
@Override
public synchronized void reset() throws IOException {
in.reset();
}
/**
* Skips <code>count</code> number of bytes in this InputStream.
* Subsequent <code>read()</code>'s will not return these bytes unless
* <code>reset()</code> is used. This implementation skips
* <code>count</code> number of bytes in the target stream.
*
* @param count
* the number of bytes to skip.
* @return the number of bytes actually skipped.
*
* @throws IOException
* If the stream is already closed or another IOException
* occurs.
*/
@Override
public long skip(long count) throws IOException {
return in.skip(count);
}
}

View File

@ -0,0 +1,144 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package java.io;
/**
* FilteredOutputStream is a class which takes an output stream and
* <em>filters</em> the output in some way. The filtered view may be a
* buffered output or one which compresses data before actually writing the
* bytes. FilterOutputStreams are meant for byte streams.
*
* @see FilterInputStream
*/
public class FilterOutputStream extends OutputStream {
/**
* The target OutputStream for this filter.
*/
protected OutputStream out;
/**
* Constructs a new FilterOutputStream on the OutputStream <code>out</code>.
* All writes are now filtered through this stream.
*
* @param out
* the target OutputStream to filter writes on.
*/
public FilterOutputStream(OutputStream out) {
this.out = out;
}
/**
* Close this FilterOutputStream. This implementation closes the target
* stream.
*
* @throws IOException
* If an error occurs attempting to close this stream.
*/
@Override
public void close() throws IOException {
try {
flush();
} catch (IOException e) {
// Ignored
}
/* Make sure we clean up this stream if exception fires */
out.close();
}
/**
* Flush this FilterOutputStream to ensure all pending data is sent out to
* the target OutputStream. This implementation flushes the target
* OutputStream.
*
* @throws IOException
* If an error occurs attempting to flush this
* FilterOutputStream.
*/
@Override
public void flush() throws IOException {
out.flush();
}
/**
* Writes the entire contents of the byte array <code>buffer</code> to
* this FilterOutputStream. This implementation writes the
* <code>buffer</code> to the target stream.
*
* @param buffer
* the buffer to be written
*
* @throws IOException
* If an error occurs attempting to write to this
* FilterOutputStream.
*/
@Override
public void write(byte buffer[]) throws IOException {
write(buffer, 0, buffer.length);
}
/**
* Writes <code>count</code> <code>bytes</code> from the byte array
* <code>buffer</code> starting at <code>offset</code> to this
* FilterOutputStream. This implementation writes the <code>buffer</code>
* to the target OutputStream.
*
* @param buffer
* the buffer to be written
* @param offset
* offset in buffer to get bytes
* @param count
* number of bytes in buffer to write
*
* @throws IOException
* If an error occurs attempting to write to this
* FilterOutputStream.
* @throws IndexOutOfBoundsException
* If offset or count are outside of bounds.
*/
@Override
public void write(byte buffer[], int offset, int count) throws IOException {
// avoid int overflow, force null buffer check first
if (offset > buffer.length || offset < 0 || count < 0
|| count > buffer.length - offset) {
throw new ArrayIndexOutOfBoundsException(); //$NON-NLS-1$
}
for (int i = 0; i < count; i++) {
// Call write() instead of out.write() since subclasses could
// override the write() method.
write(buffer[offset + i]);
}
}
/**
* Writes the specified byte <code>oneByte</code> to this
* FilterOutputStream. Only the low order byte of <code>oneByte</code> is
* written. This implementation writes the byte to the target OutputStream.
*
* @param oneByte
* the byte to be written
*
* @throws IOException
* If an error occurs attempting to write to this
* FilterOutputStream.
*/
@Override
public void write(int oneByte) throws IOException {
out.write(oneByte);
}
}

View File

@ -0,0 +1,31 @@
/*
* Copyright 2010 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package java.io;
public class IOException extends Exception {
public IOException() {
super();
}
public IOException(String s) {
super(s);
}
public IOException(Exception e) {
super(e);
}
}

View File

@ -0,0 +1,57 @@
/*
* Copyright 2010 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package java.io;
public abstract class InputStream {
public abstract int read() throws IOException;
public int read(byte[]buf, int start, int len) throws IOException {
int end = start + len;
for (int i = start; i < end; i++) {
int r = read();
if (r == -1) {
return i == start ? -1 : i - start;
}
buf[i] = (byte) r;
}
return len;
}
public int read(byte[] buf) throws IOException {
return read(buf, 0, buf.length);
}
public void close() throws IOException {
}
public int available() throws IOException
{
return 0;
}
public void mark(int readAheadLimit){
}
public boolean markSupported() {
return false;
}
public long skip(long n) throws IOException, IllegalArgumentException { return 0; }
public void reset() throws IOException {}
}

View File

@ -0,0 +1,53 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package java.io;
import core.util.Streams;
/**
* InputStreamReader is class for turning a byte Stream into a character Stream.
* Data read from the source input stream is converted into characters by either
* a default or provided character converter. By default, the encoding is
* assumed to ISO8859_1. The InputStreamReader contains a buffer of bytes read
* from the source input stream and converts these into characters as needed.
* The buffer size is 8K.
*
* @see OutputStreamWriter
*/
public class InputStreamReader extends StringReader {
/**
* Constructs a new InputStreamReader on the InputStream <code>in</code>.
* Now character reading can be filtered through this InputStreamReader.
* This constructor assumes the default conversion of ISO8859_1
* (ISO-Latin-1).
*
* @param in
* the InputStream to convert to characters.
* @throws IOException
*/
public InputStreamReader(InputStream in) throws IOException {
super(Streams.readFullyString(in, "UTF-8"));
}
public InputStreamReader(InputStream in, String enc) throws IOException
{
super(Streams.readFullyString(in, enc));
}
}

15
gwt/jre/java/io/Msg.java Normal file
View File

@ -0,0 +1,15 @@
package java.io;
public class Msg {
public static String getString(String string) {
// TODO Auto-generated method stub
return null;
}
public static String getString(String string, int offset) {
// TODO Auto-generated method stub
return null;
}
};

View File

@ -0,0 +1,41 @@
/*
* Copyright 2010 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package java.io;
public abstract class OutputStream {
// not abstact because of some gwt strangeness
public abstract void write(int b) throws IOException;
public void write(byte[] ba) throws IOException {
write(ba, 0, ba.length);
}
public void write(byte[] ba, int start, int len) throws IOException {
int end = start + len;
for (int i = start; i < end; i++) {
write(ba[i]);
}
}
public void close() throws IOException {
}
public void flush() throws IOException {
}
}

View File

@ -0,0 +1,207 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package java.io;
import core.util.Strings;
/**
* OutputStreamWriter is a class for turning a character output stream into a
* byte output stream. The conversion of Unicode characters to their byte
* equivalents is determined by the converter used. By default, the encoding is
* ISO8859_1 (ISO-Latin-1) but can be changed by calling the constructor which
* takes an encoding.
*
* @see InputStreamReader
*/
public class OutputStreamWriter extends Writer {
private OutputStream out;
String enc;
/**
* Constructs a new OutputStreamWriter using <code>out</code> as the
* OutputStream to write converted characters to. The default character
* encoding is used (see class description).
*
* @param out
* the non-null OutputStream to write converted bytes to.
*/
public OutputStreamWriter(OutputStream out) {
super(out);
this.out = out;
}
/**
* Constructs a new OutputStreamWriter using <code>out</code> as the
* OutputStream to write converted characters to and <code>enc</code> as
* the character encoding. If the encoding cannot be found, an
* UnsupportedEncodingException error is thrown.
*
* @param out
* the non-null OutputStream to write converted bytes to.
* @param enc
* the non-null String describing the desired character encoding.
*
* @throws UnsupportedEncodingException
* if the encoding cannot be found.
*/
public OutputStreamWriter(OutputStream out, final String enc)
throws UnsupportedEncodingException {
super(out);
if (enc == null) {
throw new NullPointerException();
}
this.out = out;
this.enc = enc;
}
/**
* Close this OutputStreamWriter. This implementation first flushes the
* buffer and the target OutputStream. The OutputStream is then closed and
* the resources for the buffer and converter are freed.
* <p>
* Only the first invocation of this method has any effect. Subsequent calls
* do no work.
*
* @throws IOException
* If an error occurs attempting to close this
* OutputStreamWriter.
*/
@Override
public void close() throws IOException {
synchronized (lock) {
out.flush();
out.close();
}
}
/**
* Flush this OutputStreamWriter. This implementation ensures all buffered
* bytes are written to the target OutputStream. After writing the bytes,
* the target OutputStream is then flushed.
*
* @throws IOException
* If an error occurs attempting to flush this
* OutputStreamWriter.
*/
@Override
public void flush() throws IOException {
synchronized (lock) {
out.flush();
}
}
private void checkStatus() throws IOException {
}
/**
* Answer the String which identifies the encoding used to convert
* characters to bytes. The value <code>null</code> is returned if this
* Writer has been closed.
*
* @return the String describing the converter or null if this Writer is
* closed.
*/
public String getEncoding() {
return enc;
}
/**
* Writes <code>count</code> characters starting at <code>offset</code>
* in <code>buf</code> to this Writer. The characters are immediately
* converted to bytes by the character converter and stored in a local
* buffer. If the buffer becomes full as a result of this write, this Writer
* is flushed.
*
* @param buf
* the non-null array containing characters to write.
* @param offset
* offset in buf to retrieve characters
* @param count
* maximum number of characters to write
*
* @throws IOException
* If this OutputStreamWriter has already been closed or some
* other IOException occurs.
* @throws IndexOutOfBoundsException
* If offset or count is outside of bounds.
*/
@Override
public void write(char[] buf, int offset, int count) throws IOException {
char[] sb = new char[count];
for (int i=0; i<count; ++i)
sb[i] = buf[i+offset];
String s = Strings.toString(buf);
out.write(s.getBytes(enc));
}
/**
* Writes out the character <code>oneChar</code> to this Writer. The
* low-order 2 bytes are immediately converted to bytes by the character
* converter and stored in a local buffer. If the buffer becomes full as a
* result of this write, this Writer is flushed.
*
* @param oneChar
* the character to write
*
* @throws IOException
* If this OutputStreamWriter has already been closed or some
* other IOException occurs.
*/
@Override
public void write(int oneChar) throws IOException {
char[] cs = new char[] { (char)oneChar };
write(cs, 0, 1);
}
/**
* Writes <code>count</code> characters starting at <code>offset</code>
* in <code>str</code> to this Writer. The characters are immediately
* converted to bytes by the character converter and stored in a local
* buffer. If the buffer becomes full as a result of this write, this Writer
* is flushed.
*
* @param str
* the non-null String containing characters to write.
* @param offset
* offset in str to retrieve characters
* @param count
* maximum number of characters to write
*
* @throws IOException
* If this OutputStreamWriter has already been closed or some
* other IOException occurs.
* @throws IndexOutOfBoundsException
* If count is negative
* @throws StringIndexOutOfBoundsException
* If offset is negative or offset + count is outside of bounds
*/
@Override
public void write(String str, int offset, int count) throws IOException {
synchronized (lock) {
char[] chars = new char[count];
str.getChars(0, count, chars, 0);
write(chars);
}
}
}

View File

@ -0,0 +1,335 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package java.io;
/**
* PushbackInputStream is a filter class which allows bytes read to be pushed
* back into the stream so that they can be reread. Parsers may find this
* useful. There is a progammable limit to the number of bytes which may be
* pushed back. If the buffer of pushed back bytes is empty, bytes are read from
* the source input stream.
*/
public class PushbackInputStream extends FilterInputStream {
/**
* The <code>byte</code> array containing the bytes to read.
*/
protected byte[] buf;
/**
* The current position within the byte array <code>buf</code>. A value
* equal to buf.length indicates no bytes available. A value of 0 indicates
* the buffer is full.
*/
protected int pos;
/**
* Constructs a new PushbackInputStream on the InputStream <code>in</code>.
* The size of the pushback buffer is set to the default, or 1 byte.
*
* @param in
* the InputStream to allow pushback operations on.
*/
public PushbackInputStream(InputStream in) {
super(in);
buf = (in == null) ? null : new byte[1];
pos = 1;
}
/**
* Constructs a new PushbackInputStream on the InputStream <code>in</code>.
* The size of the pushback buffer is set to <code>size</code>.
*
* @param in
* the InputStream to allow pushback operations on.
* @param size
* the size of the pushback buffer (<code>size>=0</code>).
*/
public PushbackInputStream(InputStream in, int size) {
super(in);
if (size <= 0) {
throw new IllegalArgumentException(Msg.getString("K0058")); //$NON-NLS-1$
}
buf = (in == null) ? null : new byte[size];
pos = size;
}
/**
* Answers a int representing then number of bytes that are available before
* this PushbackInputStream will block. This method returns the number of
* bytes available in the pushback buffer plus those available in the target
* stream.
*
* @return int the number of bytes available before blocking.
*
* @throws java.io.IOException
* If an error occurs in this stream.
*/
@Override
public int available() throws IOException {
if (buf == null) {
throw new IOException();
}
return buf.length - pos + in.available();
}
/**
* Close this PushbackInputStream. This implementation closes the target
* stream.
*
* @throws IOException
* If an error occurs attempting to close this stream.
*/
@Override
public void close() throws IOException {
if (in != null) {
in.close();
in = null;
buf = null;
}
}
/**
* Answers a boolean indicating whether or not this PushbackInputStream
* supports mark() and reset(). This implementation always answers false
* since PushbackInputStreams do not support mark/reset.
*
* @return boolean indicates whether or not mark() and reset() are
* supported.
*/
@Override
public boolean markSupported() {
return false;
}
/**
* Reads a single byte from this PushbackInputStream and returns the result
* as an int. The low-order byte is returned or -1 of the end of stream was
* encountered. If the pushback buffer does not contain any available bytes
* then a byte from the target input stream is returned.
*
* @return int The byte read or -1 if end of stream.
*
* @throws IOException
* If an IOException occurs.
*/
@Override
public int read() throws IOException {
if (buf == null) {
throw new IOException();
}
// Is there a pushback byte available?
if (pos < buf.length) {
return (buf[pos++] & 0xFF);
}
// Assume read() in the InputStream will return low-order byte or -1
// if end of stream.
return in.read();
}
/**
* Reads at most <code>length</code> bytes from this PushbackInputStream
* and stores them in byte array <code>buffer</code> starting at
* <code>offset</code>. Answer the number of bytes actually read or -1 if
* no bytes were read and end of stream was encountered. This implementation
* reads bytes from the pushback buffer first, then the target stream if
* more bytes are required to satisfy <code>count</code>.
*
* @param buffer
* the byte array in which to store the read bytes.
* @param offset
* the offset in <code>buffer</code> to store the read bytes.
* @param length
* the maximum number of bytes to store in <code>buffer</code>.
* @return the number of bytes actually read or -1 if end of stream.
*
* @throws IOException
* If an IOException occurs.
*/
@Override
public int read(byte[] buffer, int offset, int length) throws IOException {
if (buf == null) {
throw new IOException();
}
if (buffer == null) {
throw new NullPointerException();
}
// avoid int overflow
if (offset < 0 || offset > buffer.length || length < 0
|| length > buffer.length - offset) {
throw new ArrayIndexOutOfBoundsException();
}
int copiedBytes = 0, copyLength = 0, newOffset = offset;
// Are there pushback bytes available?
if (pos < buf.length) {
copyLength = (buf.length - pos >= length) ? length : buf.length
- pos;
System.arraycopy(buf, pos, buffer, newOffset, copyLength);
newOffset += copyLength;
copiedBytes += copyLength;
// Use up the bytes in the local buffer
pos += copyLength;
}
// Have we copied enough?
if (copyLength == length) {
return length;
}
int inCopied = in.read(buffer, newOffset, length - copiedBytes);
if (inCopied > 0) {
return inCopied + copiedBytes;
}
if (copiedBytes == 0) {
return inCopied;
}
return copiedBytes;
}
/**
* Skips <code>count</code> number of bytes in this PushbackInputStream.
* Subsequent <code>read()</code>'s will not return these bytes unless
* <code>reset()</code> is used. This implementation skips
* <code>count</code> number of bytes in the buffer and/or the target
* stream.
*
* @param count
* the number of bytes to skip.
* @return the number of bytes actually skipped.
*
* @throws IOException
* If the stream is already closed or another IOException
* occurs.
*/
@Override
public long skip(long count) throws IOException {
if (in == null) {
throw new IOException(Msg.getString("K0059")); //$NON-NLS-1$
}
if (count <= 0) {
return 0;
}
int numSkipped = 0;
if (pos < buf.length) {
numSkipped += (count < buf.length - pos) ? count : buf.length - pos;
pos += numSkipped;
}
if (numSkipped < count) {
numSkipped += in.skip(count - numSkipped);
}
return numSkipped;
}
/**
* Push back all the bytes in <code>buffer</code>. The bytes are pushed
* so that they would be read back buffer[0], buffer[1], etc. If the push
* back buffer cannot handle the entire contents of <code>buffer</code>,
* an IOException will be thrown. Some of the buffer may already be in the
* buffer after the exception is thrown.
*
* @param buffer
* the byte array containing bytes to push back into the stream.
*
* @throws IOException
* If the pushback buffer becomes, or is, full.
*/
public void unread(byte[] buffer) throws IOException {
unread(buffer, 0, buffer.length);
}
/**
* Push back <code>length</code> number of bytes in <code>buffer</code>
* starting at <code>offset</code>. The bytes are pushed so that they
* would be read back buffer[offset], buffer[offset+1], etc. If the push
* back buffer cannot handle the bytes copied from <code>buffer</code>,
* an IOException will be thrown. Some of the bytes may already be in the
* buffer after the exception is thrown.
*
* @param buffer
* the byte array containing bytes to push back into the stream.
* @param offset
* the location to start taking bytes to push back.
* @param length
* the number of bytes to push back.
*
* @throws IOException
* If the pushback buffer becomes, or is, full.
*/
public void unread(byte[] buffer, int offset, int length)
throws IOException {
if (length > pos) {
// Pushback buffer full
throw new IOException(Msg.getString("K007e")); //$NON-NLS-1$
}
// avoid int overflow
if (offset < 0 || offset > buffer.length || length < 0
|| length > buffer.length - offset) {
throw new ArrayIndexOutOfBoundsException();
}
for (int i = offset + length - 1; i >= offset; i--) {
unread(buffer[i]);
}
}
/**
* Push back one <code>byte</code>. Takes the byte <code>oneByte</code>
* and puts in in the local buffer of bytes to read back before accessing
* the target input stream.
*
* @param oneByte
* the byte to push back into the stream.
*
* @throws IOException
* If the pushback buffer is already full.
*/
public void unread(int oneByte) throws IOException {
if (buf == null) {
throw new IOException();
}
if (pos == 0) {
throw new IOException(Msg.getString("K007e")); //$NON-NLS-1$
}
buf[--pos] = (byte) oneByte;
}
/**
* Make a mark of the current position in the stream but the mark method
* does nothing.
*
* @param readlimit
* the maximum number of bytes that are able to be read before
* the mark becomes invalid
* @override the method mark in FilterInputStream
*/
@Override
public void mark(int readlimit) {
return;
}
/**
* Reset current position to the mark made previously int the stream, but
* the reset method will throw IOException and do nothing else if called.
*
* @override the method reset in FilterInputStream
* @throws IOException
* If the method is called
*/
@Override
public void reset() throws IOException {
throw new IOException();
}
}

234
gwt/jre/java/io/Reader.java Normal file
View File

@ -0,0 +1,234 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package java.io;
/**
* Reader is an Abstract class for reading Character Streams. Subclasses of
* Reader must implement the methods <code>read(char[], int, int)</code> and
* <code>close()</code>.
*
* @see Writer
*/
public abstract class Reader {
/**
* The object used to synchronize access to the reader.
*/
protected Object lock;
/**
* Constructs a new character stream Reader using <code>this</code> as the
* Object to synchronize critical regions around.
*/
protected Reader() {
super();
lock = this;
}
/**
* Constructs a new character stream Reader using <code>lock</code> as the
* Object to synchronize critical regions around.
*
* @param lock
* the <code>Object</code> to synchronize critical regions
* around.
*/
protected Reader(Object lock) {
if (lock == null) {
throw new NullPointerException();
}
this.lock = lock;
}
/**
* Close this Reader. This must be implemented by any concrete subclasses.
* The implementation should free any resources associated with the Reader.
*
* @throws IOException
* If an error occurs attempting to close this Reader.
*/
public abstract void close() throws IOException;
/**
* Set a Mark position in this Reader. The parameter <code>readLimit</code>
* indicates how many characters can be read before a mark is invalidated.
* Sending reset() will reposition the reader back to the marked position
* provided <code>readLimit</code> has not been surpassed.
* <p>
* This default implementation simply throws IOException and concrete
* subclasses must provide their own implementations.
*
* @param readLimit
* an int representing how many characters must be read before
* invalidating the mark.
*
* @throws IOException
* If an error occurs attempting mark this Reader.
*/
public void mark(int readLimit) throws IOException {
throw new IOException();
}
/**
* Answers a boolean indicating whether or not this Reader supports mark()
* and reset(). This class a default implementation which answers false.
*
* @return <code>true</code> if mark() and reset() are supported,
* <code>false</code> otherwise. This implementation returns
* <code>false</code>.
*/
public boolean markSupported() {
return false;
}
/**
* Reads a single character from this reader and returns the result as an
* int. The 2 higher-order characters are set to 0. If the end of reader was
* encountered then return -1.
*
* @return the character read or -1 if end of reader.
*
* @throws IOException
* If the Reader is already closed or some other IO error
* occurs.
*/
public int read() throws IOException {
synchronized (lock) {
char charArray[] = new char[1];
if (read(charArray, 0, 1) != -1) {
return charArray[0];
}
return -1;
}
}
/**
* Reads characters from this Reader and stores them in the character array
* <code>buf</code> starting at offset 0. Returns the number of characters
* actually read or -1 if the end of reader was encountered.
*
* @param buf
* character array to store the read characters
* @return how many characters were successfully read in or else -1 if the
* end of the reader was detected.
*
* @throws IOException
* If the Reader is already closed or some other IO error
* occurs.
*/
public int read(char buf[]) throws IOException {
return read(buf, 0, buf.length);
}
/**
* Reads at most <code>count</code> characters from this Reader and stores
* them at <code>offset</code> in the character array <code>buf</code>.
* Returns the number of characters actually read or -1 if the end of reader
* was encountered.
*
* @param buf
* character array to store the read characters
* @param offset
* offset in buf to store the read characters
* @param count
* how many characters should be read in
* @return how many characters were successfully read in or else -1 if the
* end of the reader was detected.
*
* @throws IOException
* If the Reader is already closed or some other IO error
* occurs.
*/
public abstract int read(char buf[], int offset, int count)
throws IOException;
/**
* Answers a <code>boolean</code> indicating whether or not this Reader is
* ready to be read without blocking. If the result is <code>true</code>,
* the next <code>read()</code> will not block. If the result is
* <code>false</code> this Reader may or may not block when
* <code>read()</code> is sent.
*
* @return <code>true</code> if the receiver will not block when
* <code>read()</code> is called, <code>false</code> if unknown
* or blocking will occur.
*
* @throws IOException
* If the Reader is already closed or some other IO error
* occurs.
*/
public boolean ready() throws IOException {
return false;
}
/**
* Reset this Readers position to the last <code>mark()</code> location.
* Invocations of <code>read()/skip()</code> will occur from this new
* location. If this Reader was not marked, the implementation of
* <code>reset()</code> is implementation specific. See the comment for
* the specific Reader subclass for implementation details. The default
* action is to throw <code>IOException</code>.
*
* @throws IOException
* If a problem occured or the receiver does not support
* <code>mark()/reset()</code>.
*/
public void reset() throws IOException {
throw new IOException();
}
/**
* Skips <code>count</code> number of characters in this Reader.
* Subsequent <code>read()</code>'s will not return these characters
* unless <code>reset()</code> is used. This method may perform multiple
* reads to read <code>count</code> characters.
*
* @param count
* how many characters should be passed over
* @return how many characters were successfully passed over
*
* @throws IOException
* If the Reader is closed when the call is made or if an IO
* error occurs during the operation.
*/
public long skip(long count) throws IOException {
if (count < 0) {
throw new IllegalArgumentException();
}
synchronized (lock) {
long skipped = 0;
int toRead = count < 512 ? (int) count : 512;
char charsSkipped[] = new char[toRead];
while (skipped < count) {
int read = read(charsSkipped, 0, toRead);
if (read == -1) {
return skipped;
}
skipped += read;
if (read < toRead) {
return skipped;
}
if (count - skipped < toRead) {
toRead = (int) (count - skipped);
}
}
return skipped;
}
}
}

View File

@ -0,0 +1,261 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package java.io;
/**
* A specialized {@link Reader} that reads characters from a {@code String} in
* a sequential manner.
*
* @see StringWriter
*/
public class StringReader extends Reader {
private String str;
private int markpos = -1;
private int pos;
private int count;
/**
* Construct a new {@code StringReader} with {@code str} as source. The size
* of the reader is set to the {@code length()} of the string and the Object
* to synchronize access through is set to {@code str}.
*
* @param str
* the source string for this reader.
*/
public StringReader(String str) {
super();
this.str = str;
this.count = str.length();
}
/**
* Closes this reader. Once it is closed, read operations on this reader
* will throw an {@code IOException}. Only the first invocation of this
* method has any effect.
*/
@Override
public void close() {
str = null;
}
/**
* Returns a boolean indicating whether this reader is closed.
*
* @return {@code true} if closed, otherwise {@code false}.
*/
private boolean isClosed() {
return str == null;
}
/**
* Sets a mark position in this reader. The parameter {@code readLimit} is
* ignored for this class. Calling {@code reset()} will reposition the
* reader back to the marked position.
*
* @param readLimit
* ignored for {@code StringReader} instances.
* @throws IllegalArgumentException
* if {@code readLimit < 0}.
* @throws IOException
* if this reader is closed.
* @see #markSupported()
* @see #reset()
*/
@Override
public void mark(int readLimit) throws IOException {
if (readLimit < 0) {
throw new IllegalArgumentException();
}
synchronized (lock) {
if (isClosed()) {
throw new IOException(Msg.getString("K0083")); //$NON-NLS-1$
}
markpos = pos;
}
}
/**
* Indicates whether this reader supports the {@code mark()} and {@code
* reset()} methods. This implementation returns {@code true}.
*
* @return always {@code true}.
*/
@Override
public boolean markSupported() {
return true;
}
/**
* Reads a single character from the source string and returns it as an
* integer with the two higher-order bytes set to 0. Returns -1 if the end
* of the source string has been reached.
*
* @return the character read or -1 if the end of the source string has been
* reached.
* @throws IOException
* if this reader is closed.
*/
@Override
public int read() throws IOException {
synchronized (lock) {
if (isClosed()) {
throw new IOException(Msg.getString("K0083")); //$NON-NLS-1$
}
if (pos != count) {
return str.charAt(pos++);
}
return -1;
}
}
/**
* Reads at most {@code len} characters from the source string and stores
* them at {@code offset} in the character array {@code buf}. Returns the
* number of characters actually read or -1 if the end of the source string
* has been reached.
*
* @param buf
* the character array to store the characters read.
* @param offset
* the initial position in {@code buffer} to store the characters
* read from this reader.
* @param len
* the maximum number of characters to read.
* @return the number of characters read or -1 if the end of the reader has
* been reached.
* @throws IndexOutOfBoundsException
* if {@code offset < 0} or {@code len < 0}, or if
* {@code offset + len} is greater than the size of {@code buf}.
* @throws IOException
* if this reader is closed.
*/
@Override
public int read(char buf[], int offset, int len) throws IOException {
synchronized (lock) {
if (isClosed()) {
// K0083=StringReader is closed.
throw new IOException(Msg.getString("K0083")); //$NON-NLS-1$
}
if (offset < 0 || offset > buf.length) {
// K002e=Offset out of bounds \: {0}
throw new ArrayIndexOutOfBoundsException(Msg.getString("K002e", offset)); //$NON-NLS-1$
}
if (len < 0 || len > buf.length - offset) {
// K0031=Length out of bounds \: {0}
throw new ArrayIndexOutOfBoundsException(Msg.getString("K0031", len)); //$NON-NLS-1$
}
if (len == 0) {
return 0;
}
if (pos == this.count) {
return -1;
}
int end = pos + len > this.count ? this.count : pos + len;
str.getChars(pos, end, buf, offset);
int read = end - pos;
pos = end;
return read;
}
}
/**
* Indicates whether this reader is ready to be read without blocking. This
* implementation always returns {@code true}.
*
* @return always {@code true}.
* @throws IOException
* if this reader is closed.
* @see #read()
* @see #read(char[], int, int)
*/
@Override
public boolean ready() throws IOException {
synchronized (lock) {
if (isClosed()) {
throw new IOException(Msg.getString("K0083")); //$NON-NLS-1$
}
return true;
}
}
/**
* Resets this reader's position to the last {@code mark()} location.
* Invocations of {@code read()} and {@code skip()} will occur from this new
* location. If this reader has not been marked, it is reset to the
* beginning of the source string.
*
* @throws IOException
* if this reader is closed.
* @see #mark(int)
* @see #markSupported()
*/
@Override
public void reset() throws IOException {
synchronized (lock) {
if (isClosed()) {
throw new IOException(Msg.getString("K0083")); //$NON-NLS-1$
}
pos = markpos != -1 ? markpos : 0;
}
}
/**
* Moves {@code ns} characters in the source string. Unlike the {@link
* Reader#skip(long) overridden method}, this method may skip negative skip
* distances: this rewinds the input so that characters may be read again.
* When the end of the source string has been reached, the input cannot be
* rewound.
*
* @param ns
* the maximum number of characters to skip. Positive values skip
* forward; negative values skip backward.
* @return the number of characters actually skipped. This is bounded below
* by the number of characters already read and above by the
* number of characters remaining:<br> {@code -(num chars already
* read) <= distance skipped <= num chars remaining}.
* @throws IOException
* if this reader is closed.
* @see #mark(int)
* @see #markSupported()
* @see #reset()
*/
@Override
public long skip(long ns) throws IOException {
synchronized (lock) {
if (isClosed()) {
throw new IOException(Msg.getString("K0083")); //$NON-NLS-1$
}
int minSkip = -pos;
int maxSkip = count - pos;
if (maxSkip == 0 || ns > maxSkip) {
ns = maxSkip; // no rewinding if we're at the end
} else if (ns < minSkip) {
ns = minSkip;
}
pos += ns;
return ns;
}
}
}

View File

@ -0,0 +1,250 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package java.io;
/**
* StringWriter is an class for writing Character Streams to a StringBuffer. The
* characters written can then be returned as a String. This is used for
* capturing output sent to a Writer by substituting a StringWriter.
*
* @see StringReader
*/
public class StringWriter extends Writer {
private StringBuffer buf;
/**
* Constructs a new StringWriter which has a StringBuffer allocated with the
* default size of 16 characters. The StringBuffer is also the
* <code>lock</code> used to synchronize access to this Writer.
*/
public StringWriter() {
super();
buf = new StringBuffer(16);
lock = buf;
}
/**
* Constructs a new StringWriter which has a StringBuffer allocated with the
* size of <code>initialSize</code> characters. The StringBuffer is also
* the <code>lock</code> used to synchronize access to this Writer.
*
* @param initialSize
* the intial number of characters
*/
public StringWriter(int initialSize) {
if (initialSize < 0) {
throw new IllegalArgumentException();
}
buf = new StringBuffer(initialSize);
lock = buf;
}
/**
* Close this Writer. This is the concrete implementation required. This
* particular implementation does nothing.
*
* @throws IOException
* If an IO error occurs closing this StringWriter.
*/
@Override
public void close() throws IOException {
/* empty */
}
/**
* Flush this Writer. This is the concrete implementation required. This
* particular implementation does nothing.
*/
@Override
public void flush() {
/* empty */
}
/**
* Answer the contents of this StringWriter as a StringBuffer. Any changes
* made to the StringBuffer by the receiver or the caller are reflected in
* this StringWriter.
*
* @return this StringWriters local StringBuffer.
*/
public StringBuffer getBuffer() {
synchronized (lock) {
return buf;
}
}
/**
* Answer the contents of this StringWriter as a String. Any changes made to
* the StringBuffer by the receiver after returning will not be reflected in
* the String returned to the caller.
*
* @return this StringWriters current contents as a String.
*/
@Override
public String toString() {
synchronized (lock) {
return buf.toString();
}
}
/**
* Writes <code>count</code> characters starting at <code>offset</code>
* in <code>cbuf</code> to this StringWriter.
*
* @param cbuf
* the non-null array containing characters to write.
* @param offset
* offset in buf to retrieve characters
* @param count
* maximum number of characters to write
*
* @throws ArrayIndexOutOfBoundsException
* If offset or count are outside of bounds.
*/
@Override
public void write(char[] cbuf, int offset, int count) {
// avoid int overflow
if (offset < 0 || offset > cbuf.length || count < 0
|| count > cbuf.length - offset) {
throw new IndexOutOfBoundsException();
}
synchronized (lock) {
this.buf.append(cbuf, offset, count);
}
}
/**
* Writes the specified character <code>oneChar</code> to this
* StringWriter. This implementation writes the low order two bytes to the
* Stream.
*
* @param oneChar
* The character to write
*/
@Override
public void write(int oneChar) {
synchronized (lock) {
buf.append((char) oneChar);
}
}
/**
* Writes the characters from the String <code>str</code> to this
* StringWriter.
*
* @param str
* the non-null String containing the characters to write.
*/
@Override
public void write(String str) {
synchronized (lock) {
buf.append(str);
}
}
/**
* Writes <code>count</code> number of characters starting at
* <code>offset</code> from the String <code>str</code> to this
* StringWriter.
*
* @param str
* the non-null String containing the characters to write.
* @param offset
* the starting point to retrieve characters.
* @param count
* the number of characters to retrieve and write.
*
* @throws ArrayIndexOutOfBoundsException
* If offset or count are outside of bounds.
*/
@Override
public void write(String str, int offset, int count) {
String sub = str.substring(offset, offset + count);
synchronized (lock) {
buf.append(sub);
}
}
/**
* Append a char <code>c</code>to the StringWriter. The
* StringWriter.append(<code>c</code>) works the same way as
* StringWriter.write(<code>c</code>).
*
* @param c
* The character appended to the StringWriter.
* @return The StringWriter.
*/
@Override
public StringWriter append(char c) {
write(c);
return this;
}
/**
* Append a CharSequence <code>csq</code> to the StringWriter. The
* StringWriter.append(<code>csq</code>) works the same way as
* StringWriter.write(<code>csq</code>.toString()). If <code>csq</code>
* is null, then "null" will be substituted for <code>csq</code>.
*
* @param csq
* The CharSequence appended to the StringWriter.
* @return The StringWriter
*/
@Override
public StringWriter append(CharSequence csq) {
if (null == csq) {
append(TOKEN_NULL, 0, TOKEN_NULL.length());
} else {
append(csq, 0, csq.length());
}
return this;
}
/**
* Append a subsequence of a CharSequence <code>csq</code> to the
* StringWriter. The first char and the last char of the subsequnce is
* specified by the parameter <code>start</code> and <code>end</code>.
* The StringWriter.append(<code>csq</code>) works the same way as
* StringWriter.write(<code>csq</code>.subSequence(<code>start</code>,<code>end</code>).toString).If
* <code>csq</code> is null, then "null" will be substituted for
* <code>csq</code>. s
*
* @param csq
* The CharSequence appended to the StringWriter.
* @param start
* The index of the first char in the CharSequence appended to
* the StringWriter.
* @param end
* The index of the char after the last one in the CharSequence
* appended to the StringWriter.
* @return The StringWriter.
* @throws IndexOutOfBoundsException
* If start is less than end, end is greater than the length of
* the CharSequence, or start or end is negative.
*/
@Override
public StringWriter append(CharSequence csq, int start, int end) {
if (null == csq) {
csq = TOKEN_NULL;
}
String output = csq.subSequence(start, end).toString();
write(output, 0, output.length());
return this;
}
}

241
gwt/jre/java/io/Writer.java Normal file
View File

@ -0,0 +1,241 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package java.io;
/**
* Writer is an Abstract class for writing Character Streams. Subclasses of
* writer must implement the methods <code>write(char[], int, int)</code>,
* <code>close()</code> and <code>flush()</code>.
*
* @see Reader
*/
public abstract class Writer {
static final String TOKEN_NULL = "null"; //$NON-NLS-1$
/**
* The object used to synchronize access to the writer.
*/
protected Object lock;
/**
* Constructs a new character stream Writer using <code>this</code> as the
* Object to synchronize critical regions around.
*/
protected Writer() {
super();
lock = this;
}
/**
* Constructs a new character stream Writer using <code>lock</code> as the
* Object to synchronize critical regions around.
*
* @param lock
* the Object to synchronize critical regions around.
*/
protected Writer(Object lock) {
if (lock == null) {
throw new NullPointerException();
}
this.lock = lock;
}
/**
* Close this Writer. This must be implemented by any concrete subclasses.
* The implementation should free any resources associated with the Writer.
*
* @throws IOException
* If an error occurs attempting to close this Writer.
*/
public abstract void close() throws IOException;
/**
* Flush this Writer. This must be implemented by any concrete subclasses.
* The implementation should ensure all buffered characters are written out.
*
* @throws IOException
* If an error occurs attempting to flush this Writer.
*/
public abstract void flush() throws IOException;
/**
* Writes the entire character buffer <code>buf</code> to this Writer.
*
* @param buf
* the non-null array containing characters to write.
*
* @throws IOException
* If this Writer has already been closed or some other
* IOException occurs.
*/
public void write(char buf[]) throws IOException {
write(buf, 0, buf.length);
}
/**
* Writes <code>count</code> characters starting at <code>offset<code> in
* <code>buf</code> to this Writer. This abstract method must be implemented
* by concrete subclasses.
*
* @param buf the non-null array containing characters to write.
* @param offset offset in buf to retrieve characters
* @param count maximum number of characters to write
*
* @throws IOException If this Writer has already been closed or some other IOException occurs.
* @throws ArrayIndexOutOfBoundsException If offset or count are outside of bounds.
*/
public abstract void write(char buf[], int offset, int count)
throws IOException;
/**
* Writes the specified character <code>oneChar</code> to this Writer.
* This implementation writes the low order two bytes of
* <code>oneChar</code> to the Stream.
*
* @param oneChar
* The character to write
*
* @throws IOException
* If this Writer has already been closed or some other
* IOException occurs.
*/
public void write(int oneChar) throws IOException {
synchronized (lock) {
char oneCharArray[] = new char[1];
oneCharArray[0] = (char) oneChar;
write(oneCharArray);
}
}
/**
* Writes the characters from the String <code>str</code> to this Writer.
*
* @param str
* the non-null String containing the characters to write.
*
* @throws IOException
* If this Writer has already been closed or some other
* IOException occurs.
*/
public void write(String str) throws IOException {
char buf[] = new char[str.length()];
str.getChars(0, buf.length, buf, 0);
synchronized (lock) {
write(buf);
}
}
/**
* Writes <code>count</code> number of characters starting at
* <code>offset</code> from the String <code>str</code> to this Writer.
*
* @param str
* the non-null String containing the characters to write.
* @param offset
* the starting point to retrieve characters.
* @param count
* the number of characters to retrieve and write.
*
* @throws IOException
* If this Writer has already been closed or some other
* IOException occurs.
* @throws ArrayIndexOutOfBoundsException
* If offset or count are outside of bounds.
*/
public void write(String str, int offset, int count) throws IOException {
if (count < 0) { // other cases tested by getChars()
throw new StringIndexOutOfBoundsException();
}
char buf[] = new char[count];
str.getChars(offset, offset + count, buf, 0);
synchronized (lock) {
write(buf);
}
}
/**
* Append a char <code>c</code>to the Writer. The Writer.append(<code>c</code>)
* works the same as Writer.write(<code>c</code>).
*
* @param c
* The character appended to the Writer.
* @return The Writer.
* @throws IOException
* If any IOException raises during the procedure.
*/
public Writer append(char c) throws IOException {
write(c);
return this;
}
/**
* Append a CharSequence <code>csq</code> to the Writer. The
* Writer.append(<code>csq</code>) works the same way as Writer.write(<code>csq</code>.toString()).
* If <code>csq</code> is null, then "null" will be substituted for
* <code>csq</code>.
*
* @param csq
* The CharSequence appended to the Writer.
* @return The Writer.
* @throws IOException
* If any IOException raises during the procedure.
*/
public Writer append(CharSequence csq) throws IOException {
if (null == csq) {
write(TOKEN_NULL);
} else {
write(csq.toString());
}
return this;
}
/**
* Append a subsequence of a CharSequence <code>csq</code> to the Writer.
* The first char and the last char of the subsequnce is specified by the
* parameter <code>start</code> and <code>end</code>. The
* Writer.append(<code>csq</code>) works the same way as Writer.write (<code>csq</code>csq.subSequence(<code>start</code>,<code>end</code>).toString).
* If <code>csq</code> is null, then "null" will be substituted for
* <code>csq</code>.
*
* @param csq
* The CharSequence appended to the Writaer.
* @param start
* The index of the first char in the CharSequence appended to
* the Writer.
* @param end
* The index of the char after the last one in the CharSequence
* appended to the Writer.
* @return The Writer.
* @throws IndexOutOfBoundsException
* If start is less than end, end is greater than the length of
* the CharSequence, or start or end is negative.
* @throws IOException
* If any IOException raises during the procedure.
*/
public Writer append(CharSequence csq, int start, int end)
throws IOException {
if (null == csq) {
write(TOKEN_NULL.substring(start, end));
} else {
write(csq.subSequence(start, end).toString());
}
return this;
}
}

View File

@ -0,0 +1,18 @@
package java.lang;
public class ClassNotFoundException extends Exception {
public ClassNotFoundException()
{
}
public ClassNotFoundException(String s)
{
super(s);
}
public ClassNotFoundException(String s, Throwable ex)
{
super(s,ex);
}
}

View File

@ -0,0 +1,48 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package java.lang;
/**
* This exception is thrown when a program attempts to clone an object which
* does not support the Cloneable interface.
*
* @see Cloneable
*/
public class CloneNotSupportedException extends Exception {
private static final long serialVersionUID = 5195511250079656443L;
/**
* Constructs a new instance of this class with its walkback filled in.
*/
public CloneNotSupportedException() {
super();
}
/**
* Constructs a new instance of this class with its walkback and message
* filled in.
*
* @param detailMessage
* String The detail message for the exception.
*/
public CloneNotSupportedException(String detailMessage) {
super(detailMessage);
}
}

View File

@ -0,0 +1,46 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package java.lang;
/**
* This error is thrown when the VM notices that it has gotten into a state
* which it does not understand.
*/
public class InternalError extends RuntimeException {
private static final long serialVersionUID = -9062593416125562365L;
/**
* Constructs a new instance of this class with its walkback filled in.
*/
public InternalError() {
super();
}
/**
* Constructs a new instance of this class with its walkback and message
* filled in.
*
* @param detailMessage
* String The detail message for the exception.
*/
public InternalError(String detailMessage) {
super(detailMessage);
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,379 @@
/*
* Copyright 2009 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with this
* work for additional information regarding copyright ownership. The ASF
* licenses this file to You under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*
* INCLUDES MODIFICATIONS BY RICHARD ZSCHECH AS WELL AS GOOGLE.
*/
package java.math;
/**
* Static library that provides all the <b>bit level</b> operations for
* {@link BigInteger}. The operations are: <ul type="circle"> <li>Left Shifting</li>
* <li>Right Shifting</li> <li>Bit clearing</li> <li>Bit setting</li> <li>Bit
* counting</li> <li>Bit testing</li> <li>Getting of the lowest bit set</li>
* </ul> All operations are provided in immutable way, and some in both mutable
* and immutable.
*/
class BitLevel {
/**
* @see BigInteger#bitCount()
* @param val
* @return
*/
static int bitCount(BigInteger val) {
int bCount = 0;
if (val.sign == 0) {
return 0;
}
int i = val.getFirstNonzeroDigit();
if (val.sign > 0) {
for (; i < val.numberLength; i++) {
bCount += Integer.bitCount(val.digits[i]);
}
} else {
// (sign < 0)
// this digit absorbs the carry
bCount += Integer.bitCount(-val.digits[i]);
for (i++; i < val.numberLength; i++) {
bCount += Integer.bitCount(~val.digits[i]);
}
// We take the complement sum:
bCount = (val.numberLength << 5) - bCount;
}
return bCount;
}
/**
* @see BigInteger#bitLength()
* @param val
* @return
*/
static int bitLength(BigInteger val) {
if (val.sign == 0) {
return 0;
}
int bLength = (val.numberLength << 5);
int highDigit = val.digits[val.numberLength - 1];
if (val.sign < 0) {
int i = val.getFirstNonzeroDigit();
// We reduce the problem to the positive case.
if (i == val.numberLength - 1) {
// ~~ is to handle int overflow
highDigit = ~~(highDigit - 1);
}
}
// Subtracting all sign bits
bLength -= Integer.numberOfLeadingZeros(highDigit);
return bLength;
}
/**
* Performs a flipBit on the BigInteger, returning a BigInteger with the the
* specified bit flipped.
*
* @param val BigInteger to operate on
* @param n the bit to flip
*/
static BigInteger flipBit(BigInteger val, int n) {
int resSign = (val.sign == 0) ? 1 : val.sign;
int intCount = n >> 5;
int bitN = n & 31;
int resLength = Math.max(intCount + 1, val.numberLength) + 1;
int resDigits[] = new int[resLength];
int i;
int bitNumber = 1 << bitN;
System.arraycopy(val.digits, 0, resDigits, 0, val.numberLength);
if (val.sign < 0) {
if (intCount >= val.numberLength) {
resDigits[intCount] = bitNumber;
} else {
// val.sign<0 y intCount < val.numberLength
int firstNonZeroDigit = val.getFirstNonzeroDigit();
if (intCount > firstNonZeroDigit) {
resDigits[intCount] ^= bitNumber;
} else if (intCount < firstNonZeroDigit) {
resDigits[intCount] = -bitNumber;
for (i = intCount + 1; i < firstNonZeroDigit; i++) {
resDigits[i] = -1;
}
resDigits[i] = resDigits[i]--;
} else {
i = intCount;
resDigits[i] = -((-resDigits[intCount]) ^ bitNumber);
if (resDigits[i] == 0) {
for (i++; resDigits[i] == -1; i++) {
resDigits[i] = 0;
}
resDigits[i]++;
}
}
}
} else {
// case where val is positive
resDigits[intCount] ^= bitNumber;
}
BigInteger result = new BigInteger(resSign, resLength, resDigits);
result.cutOffLeadingZeroes();
return result;
}
/**
* Performs {@code val <<= count}.
*/
// val should have enough place (and one digit more)
static void inplaceShiftLeft(BigInteger val, int count) {
int intCount = count >> 5; // count of integers
val.numberLength += intCount
+ (Integer.numberOfLeadingZeros(val.digits[val.numberLength - 1])
- (count & 31) >= 0 ? 0 : 1);
shiftLeft(val.digits, val.digits, intCount, count & 31);
val.cutOffLeadingZeroes();
val.unCache();
}
/**
* Performs {@code val >>= count} where {@code val} is a positive number.
*/
static void inplaceShiftRight(BigInteger val, int count) {
int sign = val.signum();
if (count == 0 || val.signum() == 0) {
return;
}
int intCount = count >> 5; // count of integers
val.numberLength -= intCount;
if (!shiftRight(val.digits, val.numberLength, val.digits, intCount,
count & 31)
&& sign < 0) {
// remainder not zero: add one to the result
int i;
for (i = 0; (i < val.numberLength) && (val.digits[i] == -1); i++) {
val.digits[i] = 0;
}
if (i == val.numberLength) {
val.numberLength++;
}
val.digits[i]++;
}
val.cutOffLeadingZeroes();
val.unCache();
}
/**
* Check if there are 1s in the lowest bits of this BigInteger.
*
* @param numberOfBits the number of the lowest bits to check
* @return false if all bits are 0s, true otherwise
*/
static boolean nonZeroDroppedBits(int numberOfBits, int digits[]) {
int intCount = numberOfBits >> 5;
int bitCount = numberOfBits & 31;
int i;
for (i = 0; (i < intCount) && (digits[i] == 0); i++) {
}
return ((i != intCount) || (digits[i] << (32 - bitCount) != 0));
}
/**
* @see BigInteger#shiftLeft(int)
* @param source
* @param count
* @return
*/
static BigInteger shiftLeft(BigInteger source, int count) {
int intCount = count >> 5;
count &= 31; // %= 32
int resLength = source.numberLength + intCount + ((count == 0) ? 0 : 1);
int resDigits[] = new int[resLength];
shiftLeft(resDigits, source.digits, intCount, count);
BigInteger result = new BigInteger(source.sign, resLength, resDigits);
result.cutOffLeadingZeroes();
return result;
}
/**
* Abstractly shifts left an array of integers in little endian (i.e.,
* shift it right). Total shift distance in bits is intCount * 32 + count
*
* @param result the destination array
* @param source the source array
* @param intCount the shift distance in integers
* @param count an additional shift distance in bits
*/
static void shiftLeft(int result[], int source[], int intCount, int count) {
if (count == 0) {
System.arraycopy(source, 0, result, intCount, result.length - intCount);
} else {
int rightShiftCount = 32 - count;
result[result.length - 1] = 0;
for (int i = result.length - 1; i > intCount; i--) {
result[i] |= source[i - intCount - 1] >>> rightShiftCount;
result[i - 1] = source[i - intCount - 1] << count;
}
}
for (int i = 0; i < intCount; i++) {
result[i] = 0;
}
}
static BigInteger shiftLeftOneBit(BigInteger source) {
int srcLen = source.numberLength;
int resLen = srcLen + 1;
int resDigits[] = new int[resLen];
shiftLeftOneBit(resDigits, source.digits, srcLen);
BigInteger result = new BigInteger(source.sign, resLen, resDigits);
result.cutOffLeadingZeroes();
return result;
}
/**
* Shifts the source digits left one bit, creating a value whose magnitude is
* doubled.
*
* @param result an array of digits that will hold the computed result when
* this method returns. The size of this array is {@code srcLen + 1},
* and the format is the same as {@link BigInteger#digits}.
* @param source the array of digits to shift left, in the same format as
* {@link BigInteger#digits}.
* @param srcLen the length of {@code source}; may be less than {@code
* source.length}
*/
static void shiftLeftOneBit(int result[], int source[], int srcLen) {
int carry = 0;
for (int i = 0; i < srcLen; i++) {
int val = source[i];
result[i] = (val << 1) | carry;
carry = val >>> 31;
}
if (carry != 0) {
result[srcLen] = carry;
}
}
/**
* @see BigInteger#shiftRight(int)
* @param source
* @param count
* @return
*/
static BigInteger shiftRight(BigInteger source, int count) {
int intCount = count >> 5; // count of integers
count &= 31; // count of remaining bits
if (intCount >= source.numberLength) {
return ((source.sign < 0) ? BigInteger.MINUS_ONE : BigInteger.ZERO);
}
int i;
int resLength = source.numberLength - intCount;
int resDigits[] = new int[resLength + 1];
shiftRight(resDigits, resLength, source.digits, intCount, count);
if (source.sign < 0) {
// Checking if the dropped bits are zeros (the remainder equals to
// 0)
for (i = 0; (i < intCount) && (source.digits[i] == 0); i++) {
}
// If the remainder is not zero, add 1 to the result
if ((i < intCount)
|| ((count > 0) && ((source.digits[i] << (32 - count)) != 0))) {
for (i = 0; (i < resLength) && (resDigits[i] == -1); i++) {
resDigits[i] = 0;
}
if (i == resLength) {
resLength++;
}
resDigits[i]++;
}
}
BigInteger result = new BigInteger(source.sign, resLength, resDigits);
result.cutOffLeadingZeroes();
return result;
}
/**
* Shifts right an array of integers. Total shift distance in bits is intCount
* * 32 + count.
*
* @param result the destination array
* @param resultLen the destination array's length
* @param source the source array
* @param intCount the number of elements to be shifted
* @param count the number of bits to be shifted
* @return dropped bit's are all zero (i.e. remaider is zero)
*/
static boolean shiftRight(int result[], int resultLen, int source[],
int intCount, int count) {
int i;
boolean allZero = true;
for (i = 0; i < intCount; i++) {
allZero &= source[i] == 0;
}
if (count == 0) {
System.arraycopy(source, intCount, result, 0, resultLen);
i = resultLen;
} else {
int leftShiftCount = 32 - count;
allZero &= (source[i] << leftShiftCount) == 0;
for (i = 0; i < resultLen - 1; i++) {
result[i] = (source[i + intCount] >>> count)
| (source[i + intCount + 1] << leftShiftCount);
}
result[i] = (source[i + intCount] >>> count);
i++;
}
return allZero;
}
/**
* Performs a fast bit testing for positive numbers. The bit to to be tested
* must be in the range {@code [0, val.bitLength()-1]}
*/
static boolean testBit(BigInteger val, int n) {
// PRE: 0 <= n < val.bitLength()
return ((val.digits[n >> 5] & (1 << (n & 31))) != 0);
}
/**
* Just to denote that this class can't be instantiated.
*/
private BitLevel() {
}
}

View File

@ -0,0 +1,488 @@
/*
* Copyright 2009 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with this
* work for additional information regarding copyright ownership. The ASF
* licenses this file to You under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*
* INCLUDES MODIFICATIONS BY RICHARD ZSCHECH AS WELL AS GOOGLE.
*/
package java.math;
/**
* Static library that provides {@link BigInteger} base conversion from/to any
* integer represented in a {@link java.lang.String} Object.
*/
class Conversion {
/**
* bigRadices values are precomputed maximal powers of radices (integer
* numbers from 2 to 36) that fit into unsigned int (32 bits). bigRadices[0] =
* 2 ^ 31, bigRadices[8] = 10 ^ 9, etc.
*/
static final int bigRadices[] = {
-2147483648, 1162261467, 1073741824, 1220703125, 362797056, 1977326743,
1073741824, 387420489, 1000000000, 214358881, 429981696, 815730721,
1475789056, 170859375, 268435456, 410338673, 612220032, 893871739,
1280000000, 1801088541, 113379904, 148035889, 191102976, 244140625,
308915776, 387420489, 481890304, 594823321, 729000000, 887503681,
1073741824, 1291467969, 1544804416, 1838265625, 60466176};
/**
* Holds the maximal exponent for each radix, so that
* radix<sup>digitFitInInt[radix]</sup> fit in an {@code int} (32 bits).
*/
static final int[] digitFitInInt = {
-1, -1, 31, 19, 15, 13, 11, 11, 10, 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7,
7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5};
/**
* @see BigInteger#toString(int)
* @param val
* @param radix
* @return
*/
static String bigInteger2String(BigInteger val, int radix) {
int sign = val.sign;
int numberLength = val.numberLength;
int digits[] = val.digits;
if (sign == 0) {
return "0"; //$NON-NLS-1$
}
if (numberLength == 1) {
int highDigit = digits[numberLength - 1];
long v = highDigit & 0xFFFFFFFFL;
if (sign < 0) {
v = -v;
}
return Long.toString(v, radix);
}
if ((radix == 10) || (radix < Character.MIN_RADIX)
|| (radix > Character.MAX_RADIX)) {
return val.toString();
}
double bitsForRadixDigit;
bitsForRadixDigit = Math.log(radix) / Math.log(2);
int resLengthInChars = (int) (val.abs().bitLength() / bitsForRadixDigit + ((sign < 0)
? 1 : 0)) + 1;
char result[] = new char[resLengthInChars];
int currentChar = resLengthInChars;
int resDigit;
if (radix != 16) {
int temp[] = new int[numberLength];
System.arraycopy(digits, 0, temp, 0, numberLength);
int tempLen = numberLength;
int charsPerInt = digitFitInInt[radix];
int i;
// get the maximal power of radix that fits in int
int bigRadix = bigRadices[radix - 2];
while (true) {
// divide the array of digits by bigRadix and convert remainders
// to characters collecting them in the char array
resDigit = Division.divideArrayByInt(temp, temp, tempLen, bigRadix);
int previous = currentChar;
do {
result[--currentChar] = Character.forDigit(resDigit % radix, radix);
} while (((resDigit /= radix) != 0) && (currentChar != 0));
int delta = charsPerInt - previous + currentChar;
for (i = 0; i < delta && currentChar > 0; i++) {
result[--currentChar] = '0';
}
for (i = tempLen - 1; (i > 0) && (temp[i] == 0); i--) {
// empty
}
tempLen = i + 1;
if ((tempLen == 1) && (temp[0] == 0)) { // the quotient is 0
break;
}
}
} else {
// radix == 16
for (int i = 0; i < numberLength; i++) {
for (int j = 0; (j < 8) && (currentChar > 0); j++) {
resDigit = digits[i] >> (j << 2) & 0xf;
result[--currentChar] = Character.forDigit(resDigit, 16);
}
}
}
while (result[currentChar] == '0') {
currentChar++;
}
if (sign == -1) {
result[--currentChar] = '-';
}
return new String(result, currentChar, resLengthInChars - currentChar);
}
static long divideLongByBillion(long a) {
long quot;
long rem;
if (a >= 0) {
long bLong = 1000000000L;
quot = (a / bLong);
rem = (a % bLong);
} else {
/*
* Make the dividend positive shifting it right by 1 bit then get the
* quotient an remainder and correct them properly
*/
long aPos = a >>> 1;
long bPos = 1000000000L >>> 1;
quot = aPos / bPos;
rem = aPos % bPos;
// double the remainder and add 1 if 'a' is odd
rem = (rem << 1) + (a & 1);
}
return ((rem << 32) | (quot & 0xFFFFFFFFL));
}
/**
* Builds the correspondent {@code String} representation of {@code val} being
* scaled by {@code scale}.
*
* @see BigInteger#toString()
* @see BigDecimal#toString()
*/
static String toDecimalScaledString(BigInteger val, int scale) {
int sign = val.sign;
int numberLength = val.numberLength;
int digits[] = val.digits;
int resLengthInChars;
int currentChar;
char result[];
if (sign == 0) {
switch (scale) {
case 0:
return "0"; //$NON-NLS-1$
case 1:
return "0.0"; //$NON-NLS-1$
case 2:
return "0.00"; //$NON-NLS-1$
case 3:
return "0.000"; //$NON-NLS-1$
case 4:
return "0.0000"; //$NON-NLS-1$
case 5:
return "0.00000"; //$NON-NLS-1$
case 6:
return "0.000000"; //$NON-NLS-1$
default:
StringBuilder result1 = new StringBuilder();
if (scale < 0) {
result1.append("0E+"); //$NON-NLS-1$
} else {
result1.append("0E"); //$NON-NLS-1$
}
result1.append(-scale);
return result1.toString();
}
}
// one 32-bit unsigned value may contains 10 decimal digits
resLengthInChars = numberLength * 10 + 1 + 7;
// Explanation why +1+7:
// +1 - one char for sign if needed.
// +7 - For "special case 2" (see below) we have 7 free chars for
// inserting necessary scaled digits.
result = new char[resLengthInChars + 1];
// allocated [resLengthInChars+1] characters.
// a free latest character may be used for "special case 1" (see
// below)
currentChar = resLengthInChars;
if (numberLength == 1) {
int highDigit = digits[0];
if (highDigit < 0) {
long v = highDigit & 0xFFFFFFFFL;
do {
long prev = v;
v /= 10;
result[--currentChar] = (char) (0x0030 + ((int) (prev - v * 10)));
} while (v != 0);
} else {
int v = highDigit;
do {
int prev = v;
v /= 10;
result[--currentChar] = (char) (0x0030 + (prev - v * 10));
} while (v != 0);
}
} else {
int temp[] = new int[numberLength];
int tempLen = numberLength;
System.arraycopy(digits, 0, temp, 0, tempLen);
BIG_LOOP : while (true) {
// divide the array of digits by bigRadix and convert
// remainders
// to characters collecting them in the char array
long result11 = 0;
for (int i1 = tempLen - 1; i1 >= 0; i1--) {
long temp1 = (result11 << 32) + (temp[i1] & 0xFFFFFFFFL);
long res = divideLongByBillion(temp1);
temp[i1] = (int) res;
result11 = (int) (res >> 32);
}
int resDigit = (int) result11;
int previous = currentChar;
do {
result[--currentChar] = (char) (0x0030 + (resDigit % 10));
} while (((resDigit /= 10) != 0) && (currentChar != 0));
int delta = 9 - previous + currentChar;
for (int i = 0; (i < delta) && (currentChar > 0); i++) {
result[--currentChar] = '0';
}
int j = tempLen - 1;
for (; temp[j] == 0; j--) {
if (j == 0) { // means temp[0] == 0
break BIG_LOOP;
}
}
tempLen = j + 1;
}
while (result[currentChar] == '0') {
currentChar++;
}
}
boolean negNumber = (sign < 0);
int exponent = resLengthInChars - currentChar - scale - 1;
if (scale == 0) {
if (negNumber) {
result[--currentChar] = '-';
}
return new String(result, currentChar, resLengthInChars - currentChar);
}
if ((scale > 0) && (exponent >= -6)) {
if (exponent >= 0) {
// special case 1
int insertPoint = currentChar + exponent;
for (int j = resLengthInChars - 1; j >= insertPoint; j--) {
result[j + 1] = result[j];
}
result[++insertPoint] = '.';
if (negNumber) {
result[--currentChar] = '-';
}
return new String(result, currentChar, resLengthInChars - currentChar
+ 1);
}
// special case 2
for (int j = 2; j < -exponent + 1; j++) {
result[--currentChar] = '0';
}
result[--currentChar] = '.';
result[--currentChar] = '0';
if (negNumber) {
result[--currentChar] = '-';
}
return new String(result, currentChar, resLengthInChars - currentChar);
}
int startPoint = currentChar + 1;
int endPoint = resLengthInChars;
StringBuilder result1 = new StringBuilder(16 + endPoint - startPoint);
if (negNumber) {
result1.append('-');
}
if (endPoint - startPoint >= 1) {
result1.append(result[currentChar]);
result1.append('.');
result1.append(result, currentChar + 1, resLengthInChars - currentChar
- 1);
} else {
result1.append(result, currentChar, resLengthInChars - currentChar);
}
result1.append('E');
if (exponent > 0) {
result1.append('+');
}
result1.append(Integer.toString(exponent));
return result1.toString();
}
/* can process only 32-bit numbers */
static String toDecimalScaledString(long value, int scale) {
int resLengthInChars;
int currentChar;
char result[];
boolean negNumber = value < 0;
if (negNumber) {
value = -value;
}
if (value == 0) {
switch (scale) {
case 0:
return "0"; //$NON-NLS-1$
case 1:
return "0.0"; //$NON-NLS-1$
case 2:
return "0.00"; //$NON-NLS-1$
case 3:
return "0.000"; //$NON-NLS-1$
case 4:
return "0.0000"; //$NON-NLS-1$
case 5:
return "0.00000"; //$NON-NLS-1$
case 6:
return "0.000000"; //$NON-NLS-1$
default:
StringBuilder result1 = new StringBuilder();
if (scale < 0) {
result1.append("0E+"); //$NON-NLS-1$
} else {
result1.append("0E"); //$NON-NLS-1$
}
result1.append((scale == Integer.MIN_VALUE)
? "2147483648" : Integer.toString(-scale)); //$NON-NLS-1$
return result1.toString();
}
}
// one 32-bit unsigned value may contains 10 decimal digits
resLengthInChars = 18;
// Explanation why +1+7:
// +1 - one char for sign if needed.
// +7 - For "special case 2" (see below) we have 7 free chars for
// inserting necessary scaled digits.
result = new char[resLengthInChars + 1];
// Allocated [resLengthInChars+1] characters.
// a free latest character may be used for "special case 1" (see below)
currentChar = resLengthInChars;
long v = value;
do {
long prev = v;
v /= 10;
result[--currentChar] = (char) (0x0030 + (prev - v * 10));
} while (v != 0);
long exponent = (long) resLengthInChars - (long) currentChar - scale - 1L;
if (scale == 0) {
if (negNumber) {
result[--currentChar] = '-';
}
return new String(result, currentChar, resLengthInChars - currentChar);
}
if (scale > 0 && exponent >= -6) {
if (exponent >= 0) {
// special case 1
int insertPoint = currentChar + (int) exponent;
for (int j = resLengthInChars - 1; j >= insertPoint; j--) {
result[j + 1] = result[j];
}
result[++insertPoint] = '.';
if (negNumber) {
result[--currentChar] = '-';
}
return new String(result, currentChar, resLengthInChars - currentChar
+ 1);
}
// special case 2
for (int j = 2; j < -exponent + 1; j++) {
result[--currentChar] = '0';
}
result[--currentChar] = '.';
result[--currentChar] = '0';
if (negNumber) {
result[--currentChar] = '-';
}
return new String(result, currentChar, resLengthInChars - currentChar);
}
int startPoint = currentChar + 1;
int endPoint = resLengthInChars;
StringBuilder result1 = new StringBuilder(16 + endPoint - startPoint);
if (negNumber) {
result1.append('-');
}
if (endPoint - startPoint >= 1) {
result1.append(result[currentChar]);
result1.append('.');
result1.append(result, currentChar + 1, resLengthInChars - currentChar
- 1);
} else {
result1.append(result, currentChar, resLengthInChars - currentChar);
}
result1.append('E');
if (exponent > 0) {
result1.append('+');
}
result1.append(Long.toString(exponent));
return result1.toString();
}
/**
* Just to denote that this class can't be instantiated.
*/
private Conversion() {
}
// /**
// * @see BigInteger#doubleValue()
// */
// static double bigInteger2Double(BigInteger val) {
// // val.bitLength() < 64
// if ((val.numberLength < 2)
// || ((val.numberLength == 2) && (val.digits[1] > 0))) {
// return val.longValue();
// }
// // val.bitLength() >= 33 * 32 > 1024
// if (val.numberLength > 32) {
// return ((val.sign > 0) ? Double.POSITIVE_INFINITY
// : Double.NEGATIVE_INFINITY);
// }
// int bitLen = val.abs().bitLength();
// long exponent = bitLen - 1;
// int delta = bitLen - 54;
// // We need 54 top bits from this, the 53th bit is always 1 in lVal.
// long lVal = val.abs().shiftRight(delta).longValue();
// /*
// * Take 53 bits from lVal to mantissa. The least significant bit is
// * needed for rounding.
// */
// long mantissa = lVal & 0x1FFFFFFFFFFFFFL;
// if (exponent == 1023) {
// if (mantissa == 0X1FFFFFFFFFFFFFL) {
// return ((val.sign > 0) ? Double.POSITIVE_INFINITY
// : Double.NEGATIVE_INFINITY);
// }
// if (mantissa == 0x1FFFFFFFFFFFFEL) {
// return ((val.sign > 0) ? Double.MAX_VALUE : -Double.MAX_VALUE);
// }
// }
// // Round the mantissa
// if (((mantissa & 1) == 1)
// && (((mantissa & 2) == 2) || BitLevel.nonZeroDroppedBits(delta,
// val.digits))) {
// mantissa += 2;
// }
// mantissa >>= 1; // drop the rounding bit
// long resSign = (val.sign < 0) ? 0x8000000000000000L : 0;
// exponent = ((1023 + exponent) << 52) & 0x7FF0000000000000L;
// long result = resSign | exponent | mantissa;
// return Double.longBitsToDouble(result);
// }
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,457 @@
/*
* Copyright 2009 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with this
* work for additional information regarding copyright ownership. The ASF
* licenses this file to You under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*
* INCLUDES MODIFICATIONS BY RICHARD ZSCHECH AS WELL AS GOOGLE.
*/
package java.math;
/**
* Static library that provides the basic arithmetic mutable operations for
* {@link BigInteger}. The operations provided are listed below. <ul
* type="circle"> <li>Addition.</li> <li>Subtraction.</li> <li>Comparison.</li>
* </ul> In addition to this, some <i><b>Inplace</b></i> (mutable) methods are
* provided.
*/
class Elementary {
/**
* @see BigInteger#add(BigInteger) .
* @param op1
* @param op2
* @return
*/
static BigInteger add(BigInteger op1, BigInteger op2) {
int resDigits[];
int resSign;
int op1Sign = op1.sign;
int op2Sign = op2.sign;
if (op1Sign == 0) {
return op2;
}
if (op2Sign == 0) {
return op1;
}
int op1Len = op1.numberLength;
int op2Len = op2.numberLength;
if (op1Len + op2Len == 2) {
long a = (op1.digits[0] & 0xFFFFFFFFL);
long b = (op2.digits[0] & 0xFFFFFFFFL);
long res;
int valueLo;
int valueHi;
if (op1Sign == op2Sign) {
res = a + b;
valueLo = (int) res;
valueHi = (int) (res >>> 32);
return ((valueHi == 0) ? new BigInteger(op1Sign, valueLo)
: new BigInteger(op1Sign, 2, new int[] {valueLo, valueHi}));
}
return BigInteger.valueOf((op1Sign < 0) ? (b - a) : (a - b));
} else if (op1Sign == op2Sign) {
resSign = op1Sign;
// an augend should not be shorter than addend
resDigits = (op1Len >= op2Len) ? add(op1.digits, op1Len, op2.digits,
op2Len) : add(op2.digits, op2Len, op1.digits, op1Len);
} else { // signs are different
int cmp = ((op1Len != op2Len) ? ((op1Len > op2Len) ? 1 : -1)
: compareArrays(op1.digits, op2.digits, op1Len));
if (cmp == BigInteger.EQUALS) {
return BigInteger.ZERO;
}
// a minuend should not be shorter than subtrahend
if (cmp == BigInteger.GREATER) {
resSign = op1Sign;
resDigits = subtract(op1.digits, op1Len, op2.digits, op2Len);
} else {
resSign = op2Sign;
resDigits = subtract(op2.digits, op2Len, op1.digits, op1Len);
}
}
BigInteger res = new BigInteger(resSign, resDigits.length, resDigits);
res.cutOffLeadingZeroes();
return res;
}
/**
* Compares two arrays. All elements are treated as unsigned integers. The
* magnitude is the bit chain of elements in big-endian order.
*
* @param a the first array
* @param b the second array
* @param size the size of arrays
* @return 1 if a > b, -1 if a < b, 0 if a == b
*/
static int compareArrays(final int[] a, final int[] b, final int size) {
int i;
for (i = size - 1; (i >= 0) && (a[i] == b[i]); i--) {
// empty
}
return ((i < 0) ? BigInteger.EQUALS
: (a[i] & 0xFFFFFFFFL) < (b[i] & 0xFFFFFFFFL) ? BigInteger.LESS
: BigInteger.GREATER);
}
/**
* Same as @link #inplaceAdd(BigInteger, BigInteger), but without the
* restriction of non-positive values.
*
* @param op1 any number
* @param op2 any number
*/
static void completeInPlaceAdd(BigInteger op1, BigInteger op2) {
if (op1.sign == 0) {
System.arraycopy(op2.digits, 0, op1.digits, 0, op2.numberLength);
} else if (op2.sign == 0) {
return;
} else if (op1.sign == op2.sign) {
add(op1.digits, op1.digits, op1.numberLength, op2.digits,
op2.numberLength);
} else {
int sign = unsignedArraysCompare(op1.digits, op2.digits,
op1.numberLength, op2.numberLength);
if (sign > 0) {
subtract(op1.digits, op1.digits, op1.numberLength, op2.digits,
op2.numberLength);
} else {
inverseSubtract(op1.digits, op1.digits, op1.numberLength, op2.digits,
op2.numberLength);
op1.sign = -op1.sign;
}
}
op1.numberLength = Math.max(op1.numberLength, op2.numberLength) + 1;
op1.cutOffLeadingZeroes();
op1.unCache();
}
/**
* Same as @link #inplaceSubtract(BigInteger, BigInteger), but without the
* restriction of non-positive values.
*
* @param op1 should have enough space to save the result
* @param op2
*/
static void completeInPlaceSubtract(BigInteger op1, BigInteger op2) {
int resultSign = op1.compareTo(op2);
if (op1.sign == 0) {
System.arraycopy(op2.digits, 0, op1.digits, 0, op2.numberLength);
op1.sign = -op2.sign;
} else if (op1.sign != op2.sign) {
add(op1.digits, op1.digits, op1.numberLength, op2.digits,
op2.numberLength);
op1.sign = resultSign;
} else {
int sign = unsignedArraysCompare(op1.digits, op2.digits,
op1.numberLength, op2.numberLength);
if (sign > 0) {
subtract(op1.digits, op1.digits, op1.numberLength, op2.digits,
op2.numberLength); // op1 = op1 - op2
// op1.sign remains equal
} else {
inverseSubtract(op1.digits, op1.digits, op1.numberLength, op2.digits,
op2.numberLength); // op1 = op2 - op1
op1.sign = -op1.sign;
}
}
op1.numberLength = Math.max(op1.numberLength, op2.numberLength) + 1;
op1.cutOffLeadingZeroes();
op1.unCache();
}
/**
* Performs {@code op1 += op2}. {@code op1} must have enough place to store
* the result (i.e. {@code op1.bitLength() >= op2.bitLength()}). Both should
* be positive (i.e. {@code op1 >= op2}).
*
* @param op1 the input minuend, and the output result.
* @param op2 the addend
*/
static void inplaceAdd(BigInteger op1, BigInteger op2) {
// PRE: op1 >= op2 > 0
add(op1.digits, op1.digits, op1.numberLength, op2.digits, op2.numberLength);
op1.numberLength = Math.min(
Math.max(op1.numberLength, op2.numberLength) + 1, op1.digits.length);
op1.cutOffLeadingZeroes();
op1.unCache();
}
/**
* Performs: {@code op1 += addend}. The number must to have place to hold a
* possible carry.
*/
static void inplaceAdd(BigInteger op1, final int addend) {
int carry = inplaceAdd(op1.digits, op1.numberLength, addend);
if (carry == 1) {
op1.digits[op1.numberLength] = 1;
op1.numberLength++;
}
op1.unCache();
}
/**
* Adds an integer value to the array of integers remembering carry.
*
* @return a possible generated carry (0 or 1)
*/
static int inplaceAdd(int a[], final int aSize, final int addend) {
long carry = addend & 0xFFFFFFFFL;
for (int i = 0; (carry != 0) && (i < aSize); i++) {
carry += a[i] & 0xFFFFFFFFL;
a[i] = (int) carry;
carry >>= 32;
}
return (int) carry;
}
/**
* Performs {@code op1 -= op2}. {@code op1} must have enough place to store
* the result (i.e. {@code op1.bitLength() >= op2.bitLength()}). Both should
* be positive (what implies that {@code op1 >= op2}).
*
* @param op1 the input minuend, and the output result.
* @param op2 the subtrahend
*/
static void inplaceSubtract(BigInteger op1, BigInteger op2) {
// PRE: op1 >= op2 > 0
subtract(op1.digits, op1.digits, op1.numberLength, op2.digits,
op2.numberLength);
op1.cutOffLeadingZeroes();
op1.unCache();
}
/**
* @see BigInteger#subtract(BigInteger) .
* @param op1
* @param op2
* @return
*/
static BigInteger subtract(BigInteger op1, BigInteger op2) {
int resSign;
int resDigits[];
int op1Sign = op1.sign;
int op2Sign = op2.sign;
if (op2Sign == 0) {
return op1;
}
if (op1Sign == 0) {
return op2.negate();
}
int op1Len = op1.numberLength;
int op2Len = op2.numberLength;
if (op1Len + op2Len == 2) {
long a = (op1.digits[0] & 0xFFFFFFFFL);
long b = (op2.digits[0] & 0xFFFFFFFFL);
if (op1Sign < 0) {
a = -a;
}
if (op2Sign < 0) {
b = -b;
}
return BigInteger.valueOf(a - b);
}
int cmp = ((op1Len != op2Len) ? ((op1Len > op2Len) ? 1 : -1)
: Elementary.compareArrays(op1.digits, op2.digits, op1Len));
if (cmp == BigInteger.LESS) {
resSign = -op2Sign;
resDigits = (op1Sign == op2Sign) ? subtract(op2.digits, op2Len,
op1.digits, op1Len) : add(op2.digits, op2Len, op1.digits, op1Len);
} else {
resSign = op1Sign;
if (op1Sign == op2Sign) {
if (cmp == BigInteger.EQUALS) {
return BigInteger.ZERO;
}
resDigits = subtract(op1.digits, op1Len, op2.digits, op2Len);
} else {
resDigits = add(op1.digits, op1Len, op2.digits, op2Len);
}
}
BigInteger res = new BigInteger(resSign, resDigits.length, resDigits);
res.cutOffLeadingZeroes();
return res;
}
/**
* Addss the value represented by {@code b} to the value represented by
* {@code a}. It is assumed the magnitude of a is not less than the magnitude
* of b.
*
* @return {@code a + b}
*/
private static int[] add(int a[], int aSize, int b[], int bSize) {
// PRE: a[] >= b[]
int res[] = new int[aSize + 1];
add(res, a, aSize, b, bSize);
return res;
}
/**
* Performs {@code res = a + b}.
*/
private static void add(int res[], int a[], int aSize, int b[], int bSize) {
// PRE: a.length < max(aSize, bSize)
int i;
long carry = (a[0] & 0xFFFFFFFFL) + (b[0] & 0xFFFFFFFFL);
res[0] = (int) carry;
carry >>= 32;
if (aSize >= bSize) {
for (i = 1; i < bSize; i++) {
carry += (a[i] & 0xFFFFFFFFL) + (b[i] & 0xFFFFFFFFL);
res[i] = (int) carry;
carry >>= 32;
}
for (; i < aSize; i++) {
carry += a[i] & 0xFFFFFFFFL;
res[i] = (int) carry;
carry >>= 32;
}
} else {
for (i = 1; i < aSize; i++) {
carry += (a[i] & 0xFFFFFFFFL) + (b[i] & 0xFFFFFFFFL);
res[i] = (int) carry;
carry >>= 32;
}
for (; i < bSize; i++) {
carry += b[i] & 0xFFFFFFFFL;
res[i] = (int) carry;
carry >>= 32;
}
}
if (carry != 0) {
res[i] = (int) carry;
}
}
/**
* Performs {@code res = b - a}.
*/
private static void inverseSubtract(int res[], int a[], int aSize, int b[],
int bSize) {
int i;
long borrow = 0;
if (aSize < bSize) {
for (i = 0; i < aSize; i++) {
borrow += (b[i] & 0xFFFFFFFFL) - (a[i] & 0xFFFFFFFFL);
res[i] = (int) borrow;
borrow >>= 32; // -1 or 0
}
for (; i < bSize; i++) {
borrow += b[i] & 0xFFFFFFFFL;
res[i] = (int) borrow;
borrow >>= 32; // -1 or 0
}
} else {
for (i = 0; i < bSize; i++) {
borrow += (b[i] & 0xFFFFFFFFL) - (a[i] & 0xFFFFFFFFL);
res[i] = (int) borrow;
borrow >>= 32; // -1 or 0
}
for (; i < aSize; i++) {
borrow -= a[i] & 0xFFFFFFFFL;
res[i] = (int) borrow;
borrow >>= 32; // -1 or 0
}
}
}
/**
* Subtracts the value represented by {@code b} from the value represented by
* {@code a}. It is assumed the magnitude of a is not less than the magnitude
* of b.
*
* @return {@code a - b}
*/
private static int[] subtract(int a[], int aSize, int b[], int bSize) {
// PRE: a[] >= b[]
int res[] = new int[aSize];
subtract(res, a, aSize, b, bSize);
return res;
}
/**
* Performs {@code res = a - b}. It is assumed the magnitude of a is not less
* than the magnitude of b.
*/
private static void subtract(int res[], int a[], int aSize, int b[], int bSize) {
// PRE: a[] >= b[]
int i;
long borrow = 0;
for (i = 0; i < bSize; i++) {
borrow += (a[i] & 0xFFFFFFFFL) - (b[i] & 0xFFFFFFFFL);
res[i] = (int) borrow;
borrow >>= 32; // -1 or 0
}
for (; i < aSize; i++) {
borrow += a[i] & 0xFFFFFFFFL;
res[i] = (int) borrow;
borrow >>= 32; // -1 or 0
}
}
/**
* Compares two arrays, representing unsigned integer in little-endian order.
* Returns +1,0,-1 if a is - respective - greater, equal or lesser then b
*/
private static int unsignedArraysCompare(int[] a, int[] b, int aSize,
int bSize) {
if (aSize > bSize) {
return 1;
} else if (aSize < bSize) {
return -1;
} else {
int i;
for (i = aSize - 1; i >= 0 && a[i] == b[i]; i--) {
// empty
}
return i < 0 ? BigInteger.EQUALS
: ((a[i] & 0xFFFFFFFFL) < (b[i] & 0xFFFFFFFFL) ? BigInteger.LESS
: BigInteger.GREATER);
}
}
/**
* Just to denote that this class can't be instantiated.
*/
private Elementary() {
}
}

View File

@ -0,0 +1,926 @@
/*
* Copyright 2009 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with this
* work for additional information regarding copyright ownership. The ASF
* licenses this file to You under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*
* INCLUDES MODIFICATIONS BY RICHARD ZSCHECH AS WELL AS GOOGLE.
*/
package java.math;
/**
* The library implements some logical operations over {@code BigInteger}. The
* operations provided are listed below. <ul type="circle"> <li>not</li> <li>and
* </li> <li>andNot</li> <li>or</li> <li>xor</li> </ul>
*/
class Logical {
/**
* @see BigInteger#and(BigInteger)
* @param val
* @param that
* @return
*/
static BigInteger and(BigInteger val, BigInteger that) {
if (that.sign == 0 || val.sign == 0) {
return BigInteger.ZERO;
}
if (that.equals(BigInteger.MINUS_ONE)) {
return val;
}
if (val.equals(BigInteger.MINUS_ONE)) {
return that;
}
if (val.sign > 0) {
if (that.sign > 0) {
return andPositive(val, that);
} else {
return andDiffSigns(val, that);
}
} else {
if (that.sign > 0) {
return andDiffSigns(that, val);
} else if (val.numberLength > that.numberLength) {
return andNegative(val, that);
} else {
return andNegative(that, val);
}
}
}
/**
* Return sign = positive.magnitude & magnitude = -negative.magnitude.
* @param positive
* @param negative
* @return
*/
static BigInteger andDiffSigns(BigInteger positive, BigInteger negative) {
// PRE: positive is positive and negative is negative
int iPos = positive.getFirstNonzeroDigit();
int iNeg = negative.getFirstNonzeroDigit();
// Look if the trailing zeros of the negative will "blank" all
// the positive digits
if (iNeg >= positive.numberLength) {
return BigInteger.ZERO;
}
int resLength = positive.numberLength;
int resDigits[] = new int[resLength];
// Must start from max(iPos, iNeg)
int i = Math.max(iPos, iNeg);
if (i == iNeg) {
resDigits[i] = -negative.digits[i] & positive.digits[i];
i++;
}
int limit = Math.min(negative.numberLength, positive.numberLength);
for (; i < limit; i++) {
resDigits[i] = ~negative.digits[i] & positive.digits[i];
}
// if the negative was shorter must copy the remaining digits
// from positive
if (i >= negative.numberLength) {
for (; i < positive.numberLength; i++) {
resDigits[i] = positive.digits[i];
}
} // else positive ended and must "copy" virtual 0's, do nothing then
BigInteger result = new BigInteger(1, resLength, resDigits);
result.cutOffLeadingZeroes();
return result;
}
/**
* Return sign = -1, magnitude = -(-longer.magnitude & -shorter.magnitude).
* @param longer
* @param shorter
* @return
*/
static BigInteger andNegative(BigInteger longer, BigInteger shorter) {
// PRE: longer and shorter are negative
// PRE: longer has at least as many digits as shorter
int iLonger = longer.getFirstNonzeroDigit();
int iShorter = shorter.getFirstNonzeroDigit();
// Does shorter matter?
if (iLonger >= shorter.numberLength) {
return longer;
}
int resLength;
int resDigits[];
int i = Math.max(iShorter, iLonger);
int digit;
if (iShorter > iLonger) {
digit = -shorter.digits[i] & ~longer.digits[i];
} else if (iShorter < iLonger) {
digit = ~shorter.digits[i] & -longer.digits[i];
} else {
digit = -shorter.digits[i] & -longer.digits[i];
}
if (digit == 0) {
for (i++; i < shorter.numberLength
&& (digit = ~(longer.digits[i] | shorter.digits[i])) == 0; i++) {
// digit
}
// = ~longer.digits[i] & ~shorter.digits[i]
if (digit == 0) {
// shorter has only the remaining virtual sign bits
for (; i < longer.numberLength && (digit = ~longer.digits[i]) == 0; i++) {
// empty
}
if (digit == 0) {
resLength = longer.numberLength + 1;
resDigits = new int[resLength];
resDigits[resLength - 1] = 1;
BigInteger result = new BigInteger(-1, resLength, resDigits);
return result;
}
}
}
resLength = longer.numberLength;
resDigits = new int[resLength];
resDigits[i] = -digit;
for (i++; i < shorter.numberLength; i++) {
// resDigits[i] = ~(~longer.digits[i] & ~shorter.digits[i];)
resDigits[i] = longer.digits[i] | shorter.digits[i];
}
// shorter has only the remaining virtual sign bits
for (; i < longer.numberLength; i++) {
resDigits[i] = longer.digits[i];
}
BigInteger result = new BigInteger(-1, resLength, resDigits);
return result;
}
/**
* @see BigInteger#andNot(BigInteger)
* @param val
* @param that
* @return
*/
static BigInteger andNot(BigInteger val, BigInteger that) {
if (that.sign == 0) {
return val;
}
if (val.sign == 0) {
return BigInteger.ZERO;
}
if (val.equals(BigInteger.MINUS_ONE)) {
return that.not();
}
if (that.equals(BigInteger.MINUS_ONE)) {
return BigInteger.ZERO;
}
// if val == that, return 0
if (val.sign > 0) {
if (that.sign > 0) {
return andNotPositive(val, that);
} else {
return andNotPositiveNegative(val, that);
}
} else {
if (that.sign > 0) {
return andNotNegativePositive(val, that);
} else {
return andNotNegative(val, that);
}
}
}
/**
* Return sign = 1, magnitude = -val.magnitude & ~(-that.magnitude).
* @param val
* @param that
* @return
*/
static BigInteger andNotNegative(BigInteger val, BigInteger that) {
// PRE: val < 0 && that < 0
int iVal = val.getFirstNonzeroDigit();
int iThat = that.getFirstNonzeroDigit();
if (iVal >= that.numberLength) {
return BigInteger.ZERO;
}
int resLength = that.numberLength;
int resDigits[] = new int[resLength];
int limit;
int i = iVal;
if (iVal < iThat) {
// resDigits[i] = -val.digits[i] & -1;
resDigits[i] = -val.digits[i];
limit = Math.min(val.numberLength, iThat);
for (i++; i < limit; i++) {
// resDigits[i] = ~val.digits[i] & -1;
resDigits[i] = ~val.digits[i];
}
if (i == val.numberLength) {
for (; i < iThat; i++) {
// resDigits[i] = -1 & -1;
resDigits[i] = -1;
}
// resDigits[i] = -1 & ~-that.digits[i];
resDigits[i] = that.digits[i] - 1;
} else {
// resDigits[i] = ~val.digits[i] & ~-that.digits[i];
resDigits[i] = ~val.digits[i] & (that.digits[i] - 1);
}
} else if (iThat < iVal) {
// resDigits[i] = -val.digits[i] & ~~that.digits[i];
resDigits[i] = -val.digits[i] & that.digits[i];
} else {
// resDigits[i] = -val.digits[i] & ~-that.digits[i];
resDigits[i] = -val.digits[i] & (that.digits[i] - 1);
}
limit = Math.min(val.numberLength, that.numberLength);
for (i++; i < limit; i++) {
// resDigits[i] = ~val.digits[i] & ~~that.digits[i];
resDigits[i] = ~val.digits[i] & that.digits[i];
}
for (; i < that.numberLength; i++) {
// resDigits[i] = -1 & ~~that.digits[i];
resDigits[i] = that.digits[i];
}
BigInteger result = new BigInteger(1, resLength, resDigits);
result.cutOffLeadingZeroes();
return result;
}
/**
* Return sign = -1, magnitude = -(-negative.magnitude & ~positive.magnitude).
* @param negative
* @param positive
* @return
*/
static BigInteger andNotNegativePositive(BigInteger negative,
BigInteger positive) {
// PRE: negative < 0 && positive > 0
int resLength;
int resDigits[];
int limit;
int digit;
int iNeg = negative.getFirstNonzeroDigit();
int iPos = positive.getFirstNonzeroDigit();
if (iNeg >= positive.numberLength) {
return negative;
}
resLength = Math.max(negative.numberLength, positive.numberLength);
int i = iNeg;
if (iPos > iNeg) {
resDigits = new int[resLength];
limit = Math.min(negative.numberLength, iPos);
for (; i < limit; i++) {
// 1st case: resDigits [i] = -(-negative.digits[i] & (~0))
// otherwise: resDigits[i] = ~(~negative.digits[i] & ~0) ;
resDigits[i] = negative.digits[i];
}
if (i == negative.numberLength) {
for (i = iPos; i < positive.numberLength; i++) {
// resDigits[i] = ~(~positive.digits[i] & -1);
resDigits[i] = positive.digits[i];
}
}
} else {
digit = -negative.digits[i] & ~positive.digits[i];
if (digit == 0) {
limit = Math.min(positive.numberLength, negative.numberLength);
for (i++; i < limit
&& (digit = ~(negative.digits[i] | positive.digits[i])) == 0; i++) {
// digit
}
// = ~negative.digits[i] & ~positive.digits[i]
if (digit == 0) {
// the shorter has only the remaining virtual sign bits
for (; i < positive.numberLength
&& (digit = ~positive.digits[i]) == 0; i++) {
// digit = -1 & ~positive.digits[i]
}
for (; i < negative.numberLength
&& (digit = ~negative.digits[i]) == 0; i++) {
// empty
}
// digit = ~negative.digits[i] & ~0
if (digit == 0) {
resLength++;
resDigits = new int[resLength];
resDigits[resLength - 1] = 1;
BigInteger result = new BigInteger(-1, resLength, resDigits);
return result;
}
}
}
resDigits = new int[resLength];
resDigits[i] = -digit;
i++;
}
limit = Math.min(positive.numberLength, negative.numberLength);
for (; i < limit; i++) {
// resDigits[i] = ~(~negative.digits[i] & ~positive.digits[i]);
resDigits[i] = negative.digits[i] | positive.digits[i];
}
// Actually one of the next two cycles will be executed
for (; i < negative.numberLength; i++) {
resDigits[i] = negative.digits[i];
}
for (; i < positive.numberLength; i++) {
resDigits[i] = positive.digits[i];
}
BigInteger result = new BigInteger(-1, resLength, resDigits);
return result;
}
/**
* Return sign = 1, magnitude = val.magnitude & ~that.magnitude.
* @param val
* @param that
* @return
*/
static BigInteger andNotPositive(BigInteger val, BigInteger that) {
// PRE: both arguments are positive
int resDigits[] = new int[val.numberLength];
int limit = Math.min(val.numberLength, that.numberLength);
int i;
for (i = val.getFirstNonzeroDigit(); i < limit; i++) {
resDigits[i] = val.digits[i] & ~that.digits[i];
}
for (; i < val.numberLength; i++) {
resDigits[i] = val.digits[i];
}
BigInteger result = new BigInteger(1, val.numberLength, resDigits);
result.cutOffLeadingZeroes();
return result;
}
/**
* Return sign = 1, magnitude = positive.magnitude & ~(-negative.magnitude).
* @param positive
* @param negative
* @return
*/
static BigInteger andNotPositiveNegative(BigInteger positive,
BigInteger negative) {
// PRE: positive > 0 && negative < 0
int iNeg = negative.getFirstNonzeroDigit();
int iPos = positive.getFirstNonzeroDigit();
if (iNeg >= positive.numberLength) {
return positive;
}
int resLength = Math.min(positive.numberLength, negative.numberLength);
int resDigits[] = new int[resLength];
// Always start from first non zero of positive
int i = iPos;
for (; i < iNeg; i++) {
// resDigits[i] = positive.digits[i] & -1 (~0)
resDigits[i] = positive.digits[i];
}
if (i == iNeg) {
resDigits[i] = positive.digits[i] & (negative.digits[i] - 1);
i++;
}
for (; i < resLength; i++) {
// resDigits[i] = positive.digits[i] & ~(~negative.digits[i]);
resDigits[i] = positive.digits[i] & negative.digits[i];
}
BigInteger result = new BigInteger(1, resLength, resDigits);
result.cutOffLeadingZeroes();
return result;
}
/**
* Return sign = 1, magnitude = val.magnitude & that.magnitude.
* @param val
* @param that
* @return
*/
static BigInteger andPositive(BigInteger val, BigInteger that) {
// PRE: both arguments are positive
int resLength = Math.min(val.numberLength, that.numberLength);
int i = Math.max(val.getFirstNonzeroDigit(), that.getFirstNonzeroDigit());
if (i >= resLength) {
return BigInteger.ZERO;
}
int resDigits[] = new int[resLength];
for (; i < resLength; i++) {
resDigits[i] = val.digits[i] & that.digits[i];
}
BigInteger result = new BigInteger(1, resLength, resDigits);
result.cutOffLeadingZeroes();
return result;
}
/**
* @see BigInteger#not()
* @param val
* @return
*/
static BigInteger not(BigInteger val) {
if (val.sign == 0) {
return BigInteger.MINUS_ONE;
}
if (val.equals(BigInteger.MINUS_ONE)) {
return BigInteger.ZERO;
}
int resDigits[] = new int[val.numberLength + 1];
int i;
if (val.sign > 0) {
// ~val = -val + 1
if (val.digits[val.numberLength - 1] != -1) {
for (i = 0; val.digits[i] == -1; i++) {
// empty
}
} else {
for (i = 0; (i < val.numberLength) && (val.digits[i] == -1); i++) {
// empty
}
if (i == val.numberLength) {
resDigits[i] = 1;
return new BigInteger(-val.sign, i + 1, resDigits);
}
}
// Here a carry 1 was generated
} else {
// (val.sign < 0)
// ~val = -val - 1
for (i = 0; val.digits[i] == 0; i++) {
resDigits[i] = -1;
}
// Here a borrow -1 was generated
}
// Now, the carry/borrow can be absorbed
resDigits[i] = val.digits[i] + val.sign;
// Copying the remaining unchanged digit
for (i++; i < val.numberLength; i++) {
resDigits[i] = val.digits[i];
}
return new BigInteger(-val.sign, i, resDigits);
}
/**
* @see BigInteger#or(BigInteger).
* @param val
* @param that
* @return
*/
static BigInteger or(BigInteger val, BigInteger that) {
if (that.equals(BigInteger.MINUS_ONE) || val.equals(BigInteger.MINUS_ONE)) {
return BigInteger.MINUS_ONE;
}
if (that.sign == 0) {
return val;
}
if (val.sign == 0) {
return that;
}
if (val.sign > 0) {
if (that.sign > 0) {
if (val.numberLength > that.numberLength) {
return orPositive(val, that);
} else {
return orPositive(that, val);
}
} else {
return orDiffSigns(val, that);
}
} else {
if (that.sign > 0) {
return orDiffSigns(that, val);
} else if (that.getFirstNonzeroDigit() > val.getFirstNonzeroDigit()) {
return orNegative(that, val);
} else {
return orNegative(val, that);
}
}
}
/**
* Return sign = -1, magnitude = -(positive.magnitude | -negative.magnitude).
* @param positive
* @param negative
* @return
*/
static BigInteger orDiffSigns(BigInteger positive, BigInteger negative) {
// Jumping over the least significant zero bits
int iNeg = negative.getFirstNonzeroDigit();
int iPos = positive.getFirstNonzeroDigit();
int i;
int limit;
// Look if the trailing zeros of the positive will "copy" all
// the negative digits
if (iPos >= negative.numberLength) {
return negative;
}
int resLength = negative.numberLength;
int resDigits[] = new int[resLength];
if (iNeg < iPos) {
// We know for sure that this will
// be the first non zero digit in the result
for (i = iNeg; i < iPos; i++) {
resDigits[i] = negative.digits[i];
}
} else if (iPos < iNeg) {
i = iPos;
resDigits[i] = -positive.digits[i];
limit = Math.min(positive.numberLength, iNeg);
for (i++; i < limit; i++) {
resDigits[i] = ~positive.digits[i];
}
if (i != positive.numberLength) {
resDigits[i] = ~(-negative.digits[i] | positive.digits[i]);
} else {
for (; i < iNeg; i++) {
resDigits[i] = -1;
}
// resDigits[i] = ~(-negative.digits[i] | 0);
resDigits[i] = negative.digits[i] - 1;
}
i++;
} else {
// iNeg == iPos
// Applying two complement to negative and to result
i = iPos;
resDigits[i] = -(-negative.digits[i] | positive.digits[i]);
i++;
}
limit = Math.min(negative.numberLength, positive.numberLength);
for (; i < limit; i++) {
// Applying two complement to negative and to result
// resDigits[i] = ~(~negative.digits[i] | positive.digits[i] );
resDigits[i] = negative.digits[i] & ~positive.digits[i];
}
for (; i < negative.numberLength; i++) {
resDigits[i] = negative.digits[i];
}
BigInteger result = new BigInteger(-1, resLength, resDigits);
result.cutOffLeadingZeroes();
return result;
}
/**
* Return sign = -1, magnitude = -(-val.magnitude | -that.magnitude).
* @param val
* @param that
* @return
*/
static BigInteger orNegative(BigInteger val, BigInteger that) {
// PRE: val and that are negative;
// PRE: val has at least as many trailing zeros digits as that
int iThat = that.getFirstNonzeroDigit();
int iVal = val.getFirstNonzeroDigit();
int i;
if (iVal >= that.numberLength) {
return that;
} else if (iThat >= val.numberLength) {
return val;
}
int resLength = Math.min(val.numberLength, that.numberLength);
int resDigits[] = new int[resLength];
// Looking for the first non-zero digit of the result
if (iThat == iVal) {
resDigits[iVal] = -(-val.digits[iVal] | -that.digits[iVal]);
i = iVal;
} else {
for (i = iThat; i < iVal; i++) {
resDigits[i] = that.digits[i];
}
resDigits[i] = that.digits[i] & (val.digits[i] - 1);
}
for (i++; i < resLength; i++) {
resDigits[i] = val.digits[i] & that.digits[i];
}
BigInteger result = new BigInteger(-1, resLength, resDigits);
result.cutOffLeadingZeroes();
return result;
}
/**
* Return sign = 1, magnitude = longer.magnitude | shorter.magnitude.
* @param longer
* @param shorter
* @return
*/
static BigInteger orPositive(BigInteger longer, BigInteger shorter) {
// PRE: longer and shorter are positive;
// PRE: longer has at least as many digits as shorter
int resLength = longer.numberLength;
int resDigits[] = new int[resLength];
int i = Math.min(longer.getFirstNonzeroDigit(),
shorter.getFirstNonzeroDigit());
for (i = 0; i < shorter.numberLength; i++) {
resDigits[i] = longer.digits[i] | shorter.digits[i];
}
for (; i < resLength; i++) {
resDigits[i] = longer.digits[i];
}
BigInteger result = new BigInteger(1, resLength, resDigits);
return result;
}
/**
* @see BigInteger#xor(BigInteger)
* @param val
* @param that
* @return
*/
static BigInteger xor(BigInteger val, BigInteger that) {
if (that.sign == 0) {
return val;
}
if (val.sign == 0) {
return that;
}
if (that.equals(BigInteger.MINUS_ONE)) {
return val.not();
}
if (val.equals(BigInteger.MINUS_ONE)) {
return that.not();
}
if (val.sign > 0) {
if (that.sign > 0) {
if (val.numberLength > that.numberLength) {
return xorPositive(val, that);
} else {
return xorPositive(that, val);
}
} else {
return xorDiffSigns(val, that);
}
} else {
if (that.sign > 0) {
return xorDiffSigns(that, val);
} else if (that.getFirstNonzeroDigit() > val.getFirstNonzeroDigit()) {
return xorNegative(that, val);
} else {
return xorNegative(val, that);
}
}
}
/**
* Return sign = 1, magnitude = -(positive.magnitude ^ -negative.magnitude).
* @param positive
* @param negative
* @return
*/
static BigInteger xorDiffSigns(BigInteger positive, BigInteger negative) {
int resLength = Math.max(negative.numberLength, positive.numberLength);
int resDigits[];
int iNeg = negative.getFirstNonzeroDigit();
int iPos = positive.getFirstNonzeroDigit();
int i;
int limit;
// The first
if (iNeg < iPos) {
resDigits = new int[resLength];
i = iNeg;
// resDigits[i] = -(-negative.digits[i]);
resDigits[i] = negative.digits[i];
limit = Math.min(negative.numberLength, iPos);
// Skip the positive digits while they are zeros
for (i++; i < limit; i++) {
// resDigits[i] = ~(~negative.digits[i]);
resDigits[i] = negative.digits[i];
}
// if the negative has no more elements, must fill the
// result with the remaining digits of the positive
if (i == negative.numberLength) {
for (; i < positive.numberLength; i++) {
// resDigits[i] = ~(positive.digits[i] ^ -1) -> ~(~positive.digits[i])
resDigits[i] = positive.digits[i];
}
}
} else if (iPos < iNeg) {
resDigits = new int[resLength];
i = iPos;
// Applying two complement to the first non-zero digit of the result
resDigits[i] = -positive.digits[i];
limit = Math.min(positive.numberLength, iNeg);
for (i++; i < limit; i++) {
// Continue applying two complement the result
resDigits[i] = ~positive.digits[i];
}
// When the first non-zero digit of the negative is reached, must apply
// two complement (arithmetic negation) to it, and then operate
if (i == iNeg) {
resDigits[i] = ~(positive.digits[i] ^ -negative.digits[i]);
i++;
} else {
// if the positive has no more elements must fill the remaining digits
// with
// the negative ones
for (; i < iNeg; i++) {
// resDigits[i] = ~(0 ^ 0)
resDigits[i] = -1;
}
for (; i < negative.numberLength; i++) {
// resDigits[i] = ~(~negative.digits[i] ^ 0)
resDigits[i] = negative.digits[i];
}
}
} else {
int digit;
// The first non-zero digit of the positive and negative are the same
i = iNeg;
digit = positive.digits[i] ^ -negative.digits[i];
if (digit == 0) {
limit = Math.min(positive.numberLength, negative.numberLength);
for (i++; i < limit
&& (digit = positive.digits[i] ^ ~negative.digits[i]) == 0; i++) {
// empty
}
if (digit == 0) {
// shorter has only the remaining virtual sign bits
for (; i < positive.numberLength
&& (digit = ~positive.digits[i]) == 0; i++) {
// empty
}
for (; i < negative.numberLength
&& (digit = ~negative.digits[i]) == 0; i++) {
// empty
}
if (digit == 0) {
resLength = resLength + 1;
resDigits = new int[resLength];
resDigits[resLength - 1] = 1;
BigInteger result = new BigInteger(-1, resLength, resDigits);
return result;
}
}
}
resDigits = new int[resLength];
resDigits[i] = -digit;
i++;
}
limit = Math.min(negative.numberLength, positive.numberLength);
for (; i < limit; i++) {
resDigits[i] = ~(~negative.digits[i] ^ positive.digits[i]);
}
for (; i < positive.numberLength; i++) {
// resDigits[i] = ~(positive.digits[i] ^ -1)
resDigits[i] = positive.digits[i];
}
for (; i < negative.numberLength; i++) {
// resDigits[i] = ~(0 ^ ~negative.digits[i])
resDigits[i] = negative.digits[i];
}
BigInteger result = new BigInteger(-1, resLength, resDigits);
result.cutOffLeadingZeroes();
return result;
}
/**
* Return sign = 0, magnitude = -val.magnitude ^ -that.magnitude.
* @param val
* @param that
* @return
*/
static BigInteger xorNegative(BigInteger val, BigInteger that) {
// PRE: val and that are negative
// PRE: val has at least as many trailing zero digits as that
int resLength = Math.max(val.numberLength, that.numberLength);
int resDigits[] = new int[resLength];
int iVal = val.getFirstNonzeroDigit();
int iThat = that.getFirstNonzeroDigit();
int i = iThat;
int limit;
if (iVal == iThat) {
resDigits[i] = -val.digits[i] ^ -that.digits[i];
} else {
resDigits[i] = -that.digits[i];
limit = Math.min(that.numberLength, iVal);
for (i++; i < limit; i++) {
resDigits[i] = ~that.digits[i];
}
// Remains digits in that?
if (i == that.numberLength) {
// Jumping over the remaining zero to the first non one
for (; i < iVal; i++) {
// resDigits[i] = 0 ^ -1;
resDigits[i] = -1;
}
// resDigits[i] = -val.digits[i] ^ -1;
resDigits[i] = val.digits[i] - 1;
} else {
resDigits[i] = -val.digits[i] ^ ~that.digits[i];
}
}
limit = Math.min(val.numberLength, that.numberLength);
// Perform ^ between that al val until that ends
for (i++; i < limit; i++) {
// resDigits[i] = ~val.digits[i] ^ ~that.digits[i];
resDigits[i] = val.digits[i] ^ that.digits[i];
}
// Perform ^ between val digits and -1 until val ends
for (; i < val.numberLength; i++) {
// resDigits[i] = ~val.digits[i] ^ -1 ;
resDigits[i] = val.digits[i];
}
for (; i < that.numberLength; i++) {
// resDigits[i] = -1 ^ ~that.digits[i] ;
resDigits[i] = that.digits[i];
}
BigInteger result = new BigInteger(1, resLength, resDigits);
result.cutOffLeadingZeroes();
return result;
}
/**
* Return sign = 0, magnitude = longer.magnitude | shorter.magnitude.
*
* @param longer
* @param shorter
* @return
*/
static BigInteger xorPositive(BigInteger longer, BigInteger shorter) {
// PRE: longer and shorter are positive;
// PRE: longer has at least as many digits as shorter
int resLength = longer.numberLength;
int resDigits[] = new int[resLength];
int i = Math.min(longer.getFirstNonzeroDigit(),
shorter.getFirstNonzeroDigit());
for (; i < shorter.numberLength; i++) {
resDigits[i] = longer.digits[i] ^ shorter.digits[i];
}
for (; i < longer.numberLength; i++) {
resDigits[i] = longer.digits[i];
}
BigInteger result = new BigInteger(1, resLength, resDigits);
result.cutOffLeadingZeroes();
return result;
}
/**
* Just to denote that this class can't be instantiated.
*/
private Logical() {
}
}

View File

@ -0,0 +1,313 @@
/*
* Copyright 2009 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with this
* work for additional information regarding copyright ownership. The ASF
* licenses this file to You under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*
* INCLUDES MODIFICATIONS BY RICHARD ZSCHECH AS WELL AS GOOGLE.
*/
package java.math;
import java.io.Serializable;
/**
* Immutable objects describing settings such as rounding mode and digit
* precision for the numerical operations provided by class {@link BigDecimal}.
*/
public final class MathContext implements Serializable {
/**
* A {@code MathContext} which corresponds to the IEEE 754r quadruple decimal
* precision format: 34 digit precision and {@link RoundingMode#HALF_EVEN}
* rounding.
*/
public static final MathContext DECIMAL128 = new MathContext(34,
RoundingMode.HALF_EVEN);
/**
* A {@code MathContext} which corresponds to the IEEE 754r single decimal
* precision format: 7 digit precision and {@link RoundingMode#HALF_EVEN}
* rounding.
*/
public static final MathContext DECIMAL32 = new MathContext(7,
RoundingMode.HALF_EVEN);
/**
* A {@code MathContext} which corresponds to the IEEE 754r double decimal
* precision format: 16 digit precision and {@link RoundingMode#HALF_EVEN}
* rounding.
*/
public static final MathContext DECIMAL64 = new MathContext(16,
RoundingMode.HALF_EVEN);
/**
* A {@code MathContext} for unlimited precision with
* {@link RoundingMode#HALF_UP} rounding.
*/
public static final MathContext UNLIMITED = new MathContext(0,
RoundingMode.HALF_UP);
/**
* An array of {@code char} containing: {@code
* 'p','r','e','c','i','s','i','o','n','='}. It's used to improve the methods
* related to {@code String} conversion.
*
* @see #MathContext(String)
* @see #toString()
*/
private static final char[] chPrecision = {
'p', 'r', 'e', 'c', 'i', 's', 'i', 'o', 'n', '='};
/**
* An array of {@code char} containing: {@code
* 'r','o','u','n','d','i','n','g','M','o','d','e','='}. It's used to improve
* the methods related to {@code String} conversion.
*
* @see #MathContext(String)
* @see #toString()
*/
private static final char[] chRoundingMode = {
'r', 'o', 'u', 'n', 'd', 'i', 'n', 'g', 'M', 'o', 'd', 'e', '='};
/**
* This is the serialVersionUID used by the sun implementation.
*/
private static final long serialVersionUID = 5579720004786848255L;
/**
* The number of digits to be used for an operation; results are rounded to
* this precision.
*/
private int precision;
/**
* A {@code RoundingMode} object which specifies the algorithm to be used for
* rounding.
*/
private RoundingMode roundingMode;
/**
* Constructs a new {@code MathContext} with the specified precision and with
* the rounding mode {@link RoundingMode#HALF_UP HALF_UP}. If the precision
* passed is zero, then this implies that the computations have to be
* performed exact, the rounding mode in this case is irrelevant.
*
* @param precision the precision for the new {@code MathContext}.
* @throws IllegalArgumentException if {@code precision < 0}.
*/
public MathContext(int precision) {
this(precision, RoundingMode.HALF_UP);
}
/**
* Constructs a new {@code MathContext} with the specified precision and with
* the specified rounding mode. If the precision passed is zero, then this
* implies that the computations have to be performed exact, the rounding mode
* in this case is irrelevant.
*
* @param precision the precision for the new {@code MathContext}.
* @param roundingMode the rounding mode for the new {@code MathContext}.
* @throws IllegalArgumentException if {@code precision < 0}.
* @throws NullPointerException if {@code roundingMode} is {@code null}.
*/
public MathContext(int precision, RoundingMode roundingMode) {
if (precision < 0) {
// math.0C=Digits < 0
throw new IllegalArgumentException("Digits < 0"); //$NON-NLS-1$
}
if (roundingMode == null) {
// math.0D=null RoundingMode
throw new NullPointerException("null RoundingMode"); //$NON-NLS-1$
}
this.precision = precision;
this.roundingMode = roundingMode;
}
/**
* Constructs a new {@code MathContext} from a string. The string has to
* specify the precision and the rounding mode to be used and has to follow
* the following syntax:
* "precision=&lt;precision&gt; roundingMode=&lt;roundingMode&gt;" This is the
* same form as the one returned by the {@link #toString} method.
*
* @param val a string describing the precision and rounding mode for the new
* {@code MathContext}.
* @throws IllegalArgumentException if the string is not in the correct format
* or if the precision specified is < 0.
*/
public MathContext(String val) {
if (val == null) {
throw new NullPointerException("null string");
}
char[] charVal = val.toCharArray();
int i; // Index of charVal
int j; // Index of chRoundingMode
int digit; // It will contain the digit parsed
if ((charVal.length < 27) || (charVal.length > 45)) {
// math.0E=bad string format
throw new IllegalArgumentException("bad string format"); //$NON-NLS-1$
}
// Parsing "precision=" String
for (i = 0; (i < chPrecision.length) && (charVal[i] == chPrecision[i]); i++) {
// empty
}
if (i < chPrecision.length) {
// math.0E=bad string format
throw new IllegalArgumentException("bad string format"); //$NON-NLS-1$
}
// Parsing the value for "precision="...
digit = Character.digit(charVal[i], 10);
if (digit == -1) {
// math.0E=bad string format
throw new IllegalArgumentException("bad string format"); //$NON-NLS-1$
}
this.precision = this.precision * 10 + digit;
i++;
do {
digit = Character.digit(charVal[i], 10);
if (digit == -1) {
if (charVal[i] == ' ') {
// It parsed all the digits
i++;
break;
}
// It isn't a valid digit, and isn't a white space
// math.0E=bad string format
throw new IllegalArgumentException("bad string format"); //$NON-NLS-1$
}
// Accumulating the value parsed
this.precision = this.precision * 10 + digit;
if (this.precision < 0) {
// math.0E=bad string format
throw new IllegalArgumentException("bad string format"); //$NON-NLS-1$
}
i++;
} while (true);
// Parsing "roundingMode="
for (j = 0; (j < chRoundingMode.length)
&& (charVal[i] == chRoundingMode[j]); i++, j++) {
// empty
}
if (j < chRoundingMode.length) {
// math.0E=bad string format
throw new IllegalArgumentException("bad string format"); //$NON-NLS-1$
}
// Parsing the value for "roundingMode"...
/*
* don't use implicit calls to RoundingMode.valueOf here, since it will break
* if enum name obfuscation is enabled.
*/
this.roundingMode = RoundingMode.valueOfExplicit(String.valueOf(charVal, i,
charVal.length - i));
}
/* Public Methods */
/**
* Returns true if x is a {@code MathContext} with the same precision setting
* and the same rounding mode as this {@code MathContext} instance.
*
* @param x object to be compared.
* @return {@code true} if this {@code MathContext} instance is equal to the
* {@code x} argument; {@code false} otherwise.
*/
@Override
public boolean equals(Object x) {
return ((x instanceof MathContext)
&& (((MathContext) x).getPrecision() == precision)
&& (((MathContext) x).getRoundingMode() == roundingMode));
}
/**
* Returns the precision. The precision is the number of digits used for an
* operation. Results are rounded to this precision. The precision is
* guaranteed to be non negative. If the precision is zero, then the
* computations have to be performed exact, results are not rounded in this
* case.
*
* @return the precision.
*/
public int getPrecision() {
return precision;
}
/**
* Returns the rounding mode. The rounding mode is the strategy to be used to
* round results.
* <p>
* The rounding mode is one of {@link RoundingMode#UP},
* {@link RoundingMode#DOWN}, {@link RoundingMode#CEILING},
* {@link RoundingMode#FLOOR}, {@link RoundingMode#HALF_UP},
* {@link RoundingMode#HALF_DOWN}, {@link RoundingMode#HALF_EVEN}, or
* {@link RoundingMode#UNNECESSARY}.
*
* @return the rounding mode.
*/
public RoundingMode getRoundingMode() {
return roundingMode;
}
/**
* Returns the hash code for this {@code MathContext} instance.
*
* @return the hash code for this {@code MathContext}.
*/
@Override
public int hashCode() {
// Make place for the necessary bits to represent 8 rounding modes
return ((precision << 3) | roundingMode.ordinal());
}
/**
* Returns the string representation for this {@code MathContext} instance.
* The string has the form {@code
* "precision=<precision> roundingMode=<roundingMode>" * } where
* {@code <precision>} is an integer describing the number of digits
* used for operations and {@code <roundingMode>} is the string
* representation of the rounding mode.
*
* @return a string representation for this {@code MathContext} instance
*/
@Override
public String toString() {
StringBuilder sb = new StringBuilder(45);
sb.append(chPrecision);
sb.append(precision);
sb.append(' ');
sb.append(chRoundingMode);
sb.append(roundingMode);
return sb.toString();
}
}

View File

@ -0,0 +1,534 @@
/*
* Copyright 2009 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with this
* work for additional information regarding copyright ownership. The ASF
* licenses this file to You under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*
* INCLUDES MODIFICATIONS BY RICHARD ZSCHECH AS WELL AS GOOGLE.
*/
package java.math;
/**
* Static library that provides all multiplication of {@link BigInteger}
* methods.
*/
class Multiplication {
/**
* An array with the first powers of five in {@code BigInteger} version. (
* {@code 5^0,5^1,...,5^31})
*/
static final BigInteger bigFivePows[] = new BigInteger[32];
/**
* An array with the first powers of ten in {@code BigInteger} version. (
* {@code 10^0,10^1,...,10^31})
*/
static final BigInteger[] bigTenPows = new BigInteger[32];
/**
* An array with powers of five that fit in the type {@code int}. ({@code
* 5^0,5^1,...,5^13})
*/
static final int fivePows[] = {
1, 5, 25, 125, 625, 3125, 15625, 78125, 390625, 1953125, 9765625,
48828125, 244140625, 1220703125};
/**
* An array with powers of ten that fit in the type {@code int}. ({@code
* 10^0,10^1,...,10^9})
*/
static final int tenPows[] = {
1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000};
/**
* Break point in digits (number of {@code int} elements) between Karatsuba
* and Pencil and Paper multiply.
*/
static final int whenUseKaratsuba = 63; // an heuristic value
static {
int i;
long fivePow = 1L;
for (i = 0; i <= 18; i++) {
bigFivePows[i] = BigInteger.valueOf(fivePow);
bigTenPows[i] = BigInteger.valueOf(fivePow << i);
fivePow *= 5;
}
for (; i < bigTenPows.length; i++) {
bigFivePows[i] = bigFivePows[i - 1].multiply(bigFivePows[1]);
bigTenPows[i] = bigTenPows[i - 1].multiply(BigInteger.TEN);
}
}
/**
* Performs the multiplication with the Karatsuba's algorithm. <b>Karatsuba's
* algorithm:</b> <tt>
* u = u<sub>1</sub> * B + u<sub>0</sub><br>
* v = v<sub>1</sub> * B + v<sub>0</sub><br>
*
*
* u*v = (u<sub>1</sub> * v<sub>1</sub>) * B<sub>2</sub> + ((u<sub>1</sub> - u<sub>0</sub>) * (v<sub>0</sub> - v<sub>1</sub>) + u<sub>1</sub> * v<sub>1</sub> +
* u<sub>0</sub> * v<sub>0</sub> ) * B + u<sub>0</sub> * v<sub>0</sub><br>
*</tt>
*
* @param op1 first factor of the product
* @param op2 second factor of the product
* @return {@code op1 * op2}
* @see #multiply(BigInteger, BigInteger)
*/
static BigInteger karatsuba(BigInteger op1, BigInteger op2) {
BigInteger temp;
if (op2.numberLength > op1.numberLength) {
temp = op1;
op1 = op2;
op2 = temp;
}
if (op2.numberLength < whenUseKaratsuba) {
return multiplyPAP(op1, op2);
}
/*
* Karatsuba: u = u1*B + u0 v = v1*B + v0 u*v = (u1*v1)*B^2 +
* ((u1-u0)*(v0-v1) + u1*v1 + u0*v0)*B + u0*v0
*/
// ndiv2 = (op1.numberLength / 2) * 32
int ndiv2 = (op1.numberLength & 0xFFFFFFFE) << 4;
BigInteger upperOp1 = op1.shiftRight(ndiv2);
BigInteger upperOp2 = op2.shiftRight(ndiv2);
BigInteger lowerOp1 = op1.subtract(upperOp1.shiftLeft(ndiv2));
BigInteger lowerOp2 = op2.subtract(upperOp2.shiftLeft(ndiv2));
BigInteger upper = karatsuba(upperOp1, upperOp2);
BigInteger lower = karatsuba(lowerOp1, lowerOp2);
BigInteger middle = karatsuba(upperOp1.subtract(lowerOp1),
lowerOp2.subtract(upperOp2));
middle = middle.add(upper).add(lower);
middle = middle.shiftLeft(ndiv2);
upper = upper.shiftLeft(ndiv2 << 1);
return upper.add(middle).add(lower);
}
static void multArraysPAP(int[] aDigits, int aLen, int[] bDigits, int bLen,
int[] resDigits) {
if (aLen == 0 || bLen == 0) {
return;
}
if (aLen == 1) {
resDigits[bLen] = multiplyByInt(resDigits, bDigits, bLen, aDigits[0]);
} else if (bLen == 1) {
resDigits[aLen] = multiplyByInt(resDigits, aDigits, aLen, bDigits[0]);
} else {
multPAP(aDigits, bDigits, resDigits, aLen, bLen);
}
}
/**
* Performs a multiplication of two BigInteger and hides the algorithm used.
*
* @see BigInteger#multiply(BigInteger)
*/
static BigInteger multiply(BigInteger x, BigInteger y) {
return karatsuba(x, y);
}
/**
* Multiplies a number by a power of five. This method is used in {@code
* BigDecimal} class.
*
* @param val the number to be multiplied
* @param exp a positive {@code int} exponent
* @return {@code val * 5<sup>exp</sup>}
*/
static BigInteger multiplyByFivePow(BigInteger val, int exp) {
// PRE: exp >= 0
if (exp < fivePows.length) {
return multiplyByPositiveInt(val, fivePows[exp]);
} else if (exp < bigFivePows.length) {
return val.multiply(bigFivePows[exp]);
} else {
// Large powers of five
return val.multiply(bigFivePows[1].pow(exp));
}
}
/**
* Multiplies an array of integers by an integer value.
*
* @param a the array of integers
* @param aSize the number of elements of intArray to be multiplied
* @param factor the multiplier
* @return the top digit of production
*/
static int multiplyByInt(int a[], final int aSize, final int factor) {
return multiplyByInt(a, a, aSize, factor);
}
/**
* Multiplies a number by a positive integer.
*
* @param val an arbitrary {@code BigInteger}
* @param factor a positive {@code int} number
* @return {@code val * factor}
*/
static BigInteger multiplyByPositiveInt(BigInteger val, int factor) {
int resSign = val.sign;
if (resSign == 0) {
return BigInteger.ZERO;
}
int aNumberLength = val.numberLength;
int[] aDigits = val.digits;
if (aNumberLength == 1) {
long res = unsignedMultAddAdd(aDigits[0], factor, 0, 0);
int resLo = (int) res;
int resHi = (int) (res >>> 32);
return ((resHi == 0) ? new BigInteger(resSign, resLo) : new BigInteger(
resSign, 2, new int[] {resLo, resHi}));
}
// Common case
int resLength = aNumberLength + 1;
int resDigits[] = new int[resLength];
resDigits[aNumberLength] = multiplyByInt(resDigits, aDigits, aNumberLength,
factor);
BigInteger result = new BigInteger(resSign, resLength, resDigits);
result.cutOffLeadingZeroes();
return result;
}
/**
* Multiplies a number by a power of ten. This method is used in {@code
* BigDecimal} class.
*
* @param val the number to be multiplied
* @param exp a positive {@code long} exponent
* @return {@code val * 10<sup>exp</sup>}
*/
static BigInteger multiplyByTenPow(BigInteger val, int exp) {
// PRE: exp >= 0
return ((exp < tenPows.length) ? multiplyByPositiveInt(val,
tenPows[(int) exp]) : val.multiply(powerOf10(exp)));
}
/**
* Multiplies two BigIntegers. Implements traditional scholar algorithm
* described by Knuth.
*
* <br>
* <tt>
* <table border="0">
* <tbody>
*
*
* <tr>
* <td align="center">A=</td>
* <td>a<sub>3</sub></td>
* <td>a<sub>2</sub></td>
* <td>a<sub>1</sub></td>
* <td>a<sub>0</sub></td>
* <td></td>
* <td></td>
* </tr>
*
* <tr>
* <td align="center">B=</td>
* <td></td>
* <td>b<sub>2</sub></td>
* <td>b<sub>1</sub></td>
* <td>b<sub>1</sub></td>
* <td></td>
* <td></td>
* </tr>
*
* <tr>
* <td></td>
* <td></td>
* <td></td>
* <td>b<sub>0</sub>*a<sub>3</sub></td>
* <td>b<sub>0</sub>*a<sub>2</sub></td>
* <td>b<sub>0</sub>*a<sub>1</sub></td>
* <td>b<sub>0</sub>*a<sub>0</sub></td>
* </tr>
*
* <tr>
* <td></td>
* <td></td>
* <td>b<sub>1</sub>*a<sub>3</sub></td>
* <td>b<sub>1</sub>*a<sub>2</sub></td>
* <td>b<sub>1</sub>*a1</td>
* <td>b<sub>1</sub>*a0</td>
* </tr>
*
* <tr>
* <td>+</td>
* <td>b<sub>2</sub>*a<sub>3</sub></td>
* <td>b<sub>2</sub>*a<sub>2</sub></td>
* <td>b<sub>2</sub>*a<sub>1</sub></td>
* <td>b<sub>2</sub>*a<sub>0</sub></td>
* </tr>
*
* <tr>
* <td></td>
* <td>______</td>
* <td>______</td>
* <td>______</td>
* <td>______</td>
* <td>______</td>
* <td>______</td>
* </tr>
*
* <tr>
*
* <td align="center">A*B=R=</td>
* <td align="center">r<sub>5</sub></td>
* <td align="center">r<sub>4</sub></td>
* <td align="center">r<sub>3</sub></td>
* <td align="center">r<sub>2</sub></td>
* <td align="center">r<sub>1</sub></td>
* <td align="center">r<sub>0</sub></td>
* <td></td>
* </tr>
*
* </tbody>
* </table>
*
*</tt>
*
* @param op1 first factor of the multiplication {@code op1 >= 0}
* @param op2 second factor of the multiplication {@code op2 >= 0}
* @return a {@code BigInteger} of value {@code op1 * op2}
*/
static BigInteger multiplyPAP(BigInteger a, BigInteger b) {
// PRE: a >= b
int aLen = a.numberLength;
int bLen = b.numberLength;
int resLength = aLen + bLen;
int resSign = (a.sign != b.sign) ? -1 : 1;
// A special case when both numbers don't exceed int
if (resLength == 2) {
long val = unsignedMultAddAdd(a.digits[0], b.digits[0], 0, 0);
int valueLo = (int) val;
int valueHi = (int) (val >>> 32);
return ((valueHi == 0) ? new BigInteger(resSign, valueLo)
: new BigInteger(resSign, 2, new int[] {valueLo, valueHi}));
}
int[] aDigits = a.digits;
int[] bDigits = b.digits;
int resDigits[] = new int[resLength];
// Common case
multArraysPAP(aDigits, aLen, bDigits, bLen, resDigits);
BigInteger result = new BigInteger(resSign, resLength, resDigits);
result.cutOffLeadingZeroes();
return result;
}
static void multPAP(int a[], int b[], int t[], int aLen, int bLen) {
if (a == b && aLen == bLen) {
square(a, aLen, t);
return;
}
for (int i = 0; i < aLen; i++) {
long carry = 0;
int aI = a[i];
for (int j = 0; j < bLen; j++) {
carry = unsignedMultAddAdd(aI, b[j], t[i + j], (int) carry);
t[i + j] = (int) carry;
carry >>>= 32;
}
t[i + bLen] = (int) carry;
}
}
static BigInteger pow(BigInteger base, int exponent) {
// PRE: exp > 0
BigInteger res = BigInteger.ONE;
BigInteger acc = base;
for (; exponent > 1; exponent >>= 1) {
if ((exponent & 1) != 0) {
// if odd, multiply one more time by acc
res = res.multiply(acc);
}
// acc = base^(2^i)
// a limit where karatsuba performs a faster square than the square
// algorithm
if (acc.numberLength == 1) {
acc = acc.multiply(acc); // square
} else {
acc = new BigInteger(1, square(acc.digits, acc.numberLength,
new int[acc.numberLength << 1]));
}
}
// exponent == 1, multiply one more time
res = res.multiply(acc);
return res;
}
/**
* It calculates a power of ten, which exponent could be out of 32-bit range.
* Note that internally this method will be used in the worst case with an
* exponent equals to: {@code Integer.MAX_VALUE - Integer.MIN_VALUE}.
*
* @param exp the exponent of power of ten, it must be positive.
* @return a {@code BigInteger} with value {@code 10<sup>exp</sup>}.
*/
static BigInteger powerOf10(double exp) {
// PRE: exp >= 0
int intExp = (int) exp;
// "SMALL POWERS"
if (exp < bigTenPows.length) {
// The largest power that fit in 'long' type
return bigTenPows[intExp];
} else if (exp <= 50) {
// To calculate: 10^exp
return BigInteger.TEN.pow(intExp);
} else if (exp <= 1000) {
// To calculate: 5^exp * 2^exp
return bigFivePows[1].pow(intExp).shiftLeft(intExp);
}
// "LARGE POWERS"
/*
* To check if there is free memory to allocate a BigInteger of the
* estimated size, measured in bytes: 1 + [exp / log10(2)]
*/
if (exp > 1000000) {
throw new ArithmeticException("power of ten too big"); //$NON-NLS-1$
}
if (exp <= Integer.MAX_VALUE) {
// To calculate: 5^exp * 2^exp
return bigFivePows[1].pow(intExp).shiftLeft(intExp);
}
/*
* "HUGE POWERS"
*
* This branch probably won't be executed since the power of ten is too big.
*/
// To calculate: 5^exp
BigInteger powerOfFive = bigFivePows[1].pow(Integer.MAX_VALUE);
BigInteger res = powerOfFive;
long longExp = (long) (exp - Integer.MAX_VALUE);
intExp = (int) (exp % Integer.MAX_VALUE);
while (longExp > Integer.MAX_VALUE) {
res = res.multiply(powerOfFive);
longExp -= Integer.MAX_VALUE;
}
res = res.multiply(bigFivePows[1].pow(intExp));
// To calculate: 5^exp << exp
res = res.shiftLeft(Integer.MAX_VALUE);
longExp = (long) (exp - Integer.MAX_VALUE);
while (longExp > Integer.MAX_VALUE) {
res = res.shiftLeft(Integer.MAX_VALUE);
longExp -= Integer.MAX_VALUE;
}
res = res.shiftLeft(intExp);
return res;
}
/**
* Performs a<sup>2</sup>.
*
* @param a The number to square.
* @param aLen The length of the number to square.
*/
static int[] square(int[] a, int aLen, int[] res) {
long carry;
for (int i = 0; i < aLen; i++) {
carry = 0;
for (int j = i + 1; j < aLen; j++) {
carry = unsignedMultAddAdd(a[i], a[j], res[i + j], (int) carry);
res[i + j] = (int) carry;
carry >>>= 32;
}
res[i + aLen] = (int) carry;
}
BitLevel.shiftLeftOneBit(res, res, aLen << 1);
carry = 0;
for (int i = 0, index = 0; i < aLen; i++, index++) {
carry = unsignedMultAddAdd(a[i], a[i], res[index], (int) carry);
res[index] = (int) carry;
carry >>>= 32;
index++;
carry += res[index] & 0xFFFFFFFFL;
res[index] = (int) carry;
carry >>>= 32;
}
return res;
}
/**
* Computes the value unsigned ((uint)a*(uint)b + (uint)c + (uint)d). This
* method could improve the readability and performance of the code.
*
* @param a parameter 1
* @param b parameter 2
* @param c parameter 3
* @param d parameter 4
* @return value of expression
*/
static long unsignedMultAddAdd(int a, int b, int c, int d) {
return (a & 0xFFFFFFFFL) * (b & 0xFFFFFFFFL) + (c & 0xFFFFFFFFL)
+ (d & 0xFFFFFFFFL);
}
/**
* Multiplies an array of integers by an integer value and saves the result in
* {@code res}.
*
* @param a the array of integers
* @param aSize the number of elements of intArray to be multiplied
* @param factor the multiplier
* @return the top digit of production
*/
private static int multiplyByInt(int res[], int a[], final int aSize,
final int factor) {
long carry = 0;
for (int i = 0; i < aSize; i++) {
carry = unsignedMultAddAdd(a[i], factor, (int) carry, 0);
res[i] = (int) carry;
carry >>>= 32;
}
return (int) carry;
}
/**
* Just to denote that this class can't be instantiated.
*/
private Multiplication() {
}
}

View File

@ -0,0 +1,303 @@
/*
* Copyright 2009 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with this
* work for additional information regarding copyright ownership. The ASF
* licenses this file to You under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*
* INCLUDES MODIFICATIONS BY RICHARD ZSCHECH AS WELL AS GOOGLE.
*/
package java.math;
import java.util.Arrays;
import java.util.Random;
/**
* Provides primality probabilistic methods.
*/
class Primality {
/**
* It encodes how many iterations of Miller-Rabin test are need to get an
* error bound not greater than {@code 2<sup>(-100)</sup>}. For example: for a
* {@code 1000}-bit number we need {@code 4} iterations, since {@code BITS[3]
* < 1000 <= BITS[4]}.
*/
private static final int[] BITS = {
0, 0, 1854, 1233, 927, 747, 627, 543, 480, 431, 393, 361, 335, 314, 295,
279, 265, 253, 242, 232, 223, 216, 181, 169, 158, 150, 145, 140, 136,
132, 127, 123, 119, 114, 110, 105, 101, 96, 92, 87, 83, 78, 73, 69, 64,
59, 54, 49, 44, 38, 32, 26, 1};
/**
* It encodes how many i-bit primes there are in the table for {@code
* i=2,...,10}. For example {@code offsetPrimes[6]} says that from index
* {@code 11} exists {@code 7} consecutive {@code 6}-bit prime numbers in the
* array.
*/
private static final int[][] offsetPrimes = {
null, null, {0, 2}, {2, 2}, {4, 2}, {6, 5}, {11, 7}, {18, 13}, {31, 23},
{54, 43}, {97, 75}};
/**
* All prime numbers with bit length lesser than 10 bits.
*/
private static final int primes[] = {
2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67,
71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149,
151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227,
229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307,
311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389,
397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467,
479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571,
577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653,
659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751,
757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853,
857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947,
953, 967, 971, 977, 983, 991, 997, 1009, 1013, 1019, 1021};
/**
* All {@code BigInteger} prime numbers with bit length lesser than 8 bits.
*/
private static final BigInteger BIprimes[] = new BigInteger[primes.length];
static {
// To initialize the dual table of BigInteger primes
for (int i = 0; i < primes.length; i++) {
BIprimes[i] = BigInteger.valueOf(primes[i]);
}
}
/**
* A random number is generated until a probable prime number is found.
*
* @see BigInteger#BigInteger(int,int,Random)
* @see BigInteger#probablePrime(int,Random)
* @see #isProbablePrime(BigInteger, int)
*/
static BigInteger consBigInteger(int bitLength, int certainty, Random rnd) {
// PRE: bitLength >= 2;
// For small numbers get a random prime from the prime table
if (bitLength <= 10) {
int rp[] = offsetPrimes[bitLength];
return BIprimes[rp[0] + rnd.nextInt(rp[1])];
}
int shiftCount = (-bitLength) & 31;
int last = (bitLength + 31) >> 5;
BigInteger n = new BigInteger(1, last, new int[last]);
last--;
do {
// To fill the array with random integers
for (int i = 0; i < n.numberLength; i++) {
n.digits[i] = rnd.nextInt();
}
// To fix to the correct bitLength
n.digits[last] |= 0x80000000;
n.digits[last] >>>= shiftCount;
// To create an odd number
n.digits[0] |= 1;
} while (!isProbablePrime(n, certainty));
return n;
}
/**
* @see BigInteger#isProbablePrime(int)
* @see #millerRabin(BigInteger, int)
* @ar.org.fitc.ref Optimizations: "A. Menezes - Handbook of applied
* Cryptography, Chapter 4".
*/
static boolean isProbablePrime(BigInteger n, int certainty) {
// PRE: n >= 0;
if ((certainty <= 0) || ((n.numberLength == 1) && (n.digits[0] == 2))) {
return true;
}
// To discard all even numbers
if (!n.testBit(0)) {
return false;
}
// To check if 'n' exists in the table (it fit in 10 bits)
if ((n.numberLength == 1) && ((n.digits[0] & 0XFFFFFC00) == 0)) {
return (Arrays.binarySearch(primes, n.digits[0]) >= 0);
}
// To check if 'n' is divisible by some prime of the table
for (int i = 1; i < primes.length; i++) {
if (Division.remainderArrayByInt(n.digits, n.numberLength, primes[i]) == 0) {
return false;
}
}
// To set the number of iterations necessary for Miller-Rabin test
int i;
int bitLength = n.bitLength();
for (i = 2; bitLength < BITS[i]; i++) {
// empty
}
certainty = Math.min(i, 1 + ((certainty - 1) >> 1));
return millerRabin(n, certainty);
}
/**
* It uses the sieve of Eratosthenes to discard several composite numbers in
* some appropriate range (at the moment {@code [this, this + 1024]}). After
* this process it applies the Miller-Rabin test to the numbers that were not
* discarded in the sieve.
*
* @see BigInteger#nextProbablePrime()
* @see #millerRabin(BigInteger, int)
*/
static BigInteger nextProbablePrime(BigInteger n) {
// PRE: n >= 0
int i, j;
int certainty;
int gapSize = 1024; // for searching of the next probable prime number
int modules[] = new int[primes.length];
boolean isDivisible[] = new boolean[gapSize];
BigInteger startPoint;
BigInteger probPrime;
// If n < "last prime of table" searches next prime in the table
if ((n.numberLength == 1) && (n.digits[0] >= 0)
&& (n.digits[0] < primes[primes.length - 1])) {
for (i = 0; n.digits[0] >= primes[i]; i++) {
// empty
}
return BIprimes[i];
}
/*
* Creates a "N" enough big to hold the next probable prime Note that: N <
* "next prime" < 2*N
*/
startPoint = new BigInteger(1, n.numberLength, new int[n.numberLength + 1]);
System.arraycopy(n.digits, 0, startPoint.digits, 0, n.numberLength);
// To fix N to the "next odd number"
if (n.testBit(0)) {
Elementary.inplaceAdd(startPoint, 2);
} else {
startPoint.digits[0] |= 1;
}
// To set the improved certainly of Miller-Rabin
j = startPoint.bitLength();
for (certainty = 2; j < BITS[certainty]; certainty++) {
// empty
}
// To calculate modules: N mod p1, N mod p2, ... for first primes.
for (i = 0; i < primes.length; i++) {
modules[i] = Division.remainder(startPoint, primes[i]) - gapSize;
}
while (true) {
// At this point, all numbers in the gap are initialized as
// probably primes
Arrays.fill(isDivisible, false);
// To discard multiples of first primes
for (i = 0; i < primes.length; i++) {
modules[i] = (modules[i] + gapSize) % primes[i];
j = (modules[i] == 0) ? 0 : (primes[i] - modules[i]);
for (; j < gapSize; j += primes[i]) {
isDivisible[j] = true;
}
}
// To execute Miller-Rabin for non-divisible numbers by all first
// primes
for (j = 0; j < gapSize; j++) {
if (!isDivisible[j]) {
probPrime = startPoint.copy();
Elementary.inplaceAdd(probPrime, j);
if (millerRabin(probPrime, certainty)) {
return probPrime;
}
}
}
Elementary.inplaceAdd(startPoint, gapSize);
}
}
/**
* The Miller-Rabin primality test.
*
* @param n the input number to be tested.
* @param t the number of trials.
* @return {@code false} if the number is definitely compose, otherwise
* {@code true} with probability {@code 1 - 4<sup>(-t)</sup>}.
* @ar.org.fitc.ref "D. Knuth, The Art of Computer Programming Vo.2, Section
* 4.5.4., Algorithm P"
*/
private static boolean millerRabin(BigInteger n, int t) {
// PRE: n >= 0, t >= 0
BigInteger x; // x := UNIFORM{2...n-1}
BigInteger y; // y := x^(q * 2^j) mod n
BigInteger nMinus1 = n.subtract(BigInteger.ONE); // n-1
int bitLength = nMinus1.bitLength(); // ~ log2(n-1)
// (q,k) such that: n-1 = q * 2^k and q is odd
int k = nMinus1.getLowestSetBit();
BigInteger q = nMinus1.shiftRight(k);
Random rnd = new Random();
for (int i = 0; i < t; i++) {
// To generate a witness 'x', first it use the primes of table
if (i < primes.length) {
x = BIprimes[i];
} else {
/*
* It generates random witness only if it's necesssary. Note that all
* methods would call Miller-Rabin with t <= 50 so this part is only to
* do more robust the algorithm
*/
do {
x = new BigInteger(bitLength, rnd);
} while ((x.compareTo(n) >= BigInteger.EQUALS) || (x.sign == 0)
|| x.isOne());
}
y = x.modPow(q, n);
if (y.isOne() || y.equals(nMinus1)) {
continue;
}
for (int j = 1; j < k; j++) {
if (y.equals(nMinus1)) {
continue;
}
y = y.multiply(y).mod(n);
if (y.isOne()) {
return false;
}
}
if (!y.equals(nMinus1)) {
return false;
}
}
return true;
}
/**
* Just to denote that this class can't be instantiated.
*/
private Primality() {
}
}

View File

@ -0,0 +1,214 @@
/*
* Copyright 2009 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with this
* work for additional information regarding copyright ownership. The ASF
* licenses this file to You under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*
* INCLUDES MODIFICATIONS BY RICHARD ZSCHECH AS WELL AS GOOGLE.
*/
package java.math;
/**
* Specifies the rounding behavior for operations whose results cannot be
* represented exactly.
*/
public enum RoundingMode {
/**
* Rounding mode where positive values are rounded towards positive infinity
* and negative values towards negative infinity. <br>
* Rule: {@code x.round().abs() >= x.abs()}
*/
UP(BigDecimal.ROUND_UP),
/**
* Rounding mode where the values are rounded towards zero. <br>
* Rule: {@code x.round().abs() <= x.abs()}
*/
DOWN(BigDecimal.ROUND_DOWN),
/**
* Rounding mode to round towards positive infinity. For positive values this
* rounding mode behaves as {@link #UP}, for negative values as {@link #DOWN}. <br>
* Rule: {@code x.round() >= x}
*/
CEILING(BigDecimal.ROUND_CEILING),
/**
* Rounding mode to round towards negative infinity. For positive values this
* rounding mode behaves as {@link #DOWN}, for negative values as {@link #UP}. <br>
* Rule: {@code x.round() <= x}
*/
FLOOR(BigDecimal.ROUND_FLOOR),
/**
* Rounding mode where values are rounded towards the nearest neighbor. Ties
* are broken by rounding up.
*/
HALF_UP(BigDecimal.ROUND_HALF_UP),
/**
* Rounding mode where values are rounded towards the nearest neighbor. Ties
* are broken by rounding down.
*/
HALF_DOWN(BigDecimal.ROUND_HALF_DOWN),
/**
* Rounding mode where values are rounded towards the nearest neighbor. Ties
* are broken by rounding to the even neighbor.
*/
HALF_EVEN(BigDecimal.ROUND_HALF_EVEN),
/**
* Rounding mode where the rounding operations throws an ArithmeticException
* for the case that rounding is necessary, i.e. for the case that the value
* cannot be represented exactly.
*/
UNNECESSARY(BigDecimal.ROUND_UNNECESSARY);
/**
* Some constant char arrays for optimized comparisons
*/
private static final char[] chCEILING = {'C','E','I','L','I','N','G'};
private static final char[] chDOWN = {'D','O','W','N'};
private static final char[] chFLOOR = {'F','L','O','O','R'};
private static final char[] chHALF_DOWN = {'H','A','L','F','_','D','O','W','N'};
private static final char[] chHALF_EVEN = {'H','A','L','F','_','E','V','E','N'};
private static final char[] chHALF_UP = {'H','A','L','F','_','U','P'};
private static final char[] chUNNECESSARY = {'U','N','N','E','C','E','S','S','A','R','Y'};
private static final char[] chUP = {'U','P'};
/**
* Converts rounding mode constants from class {@code BigDecimal} into {@code
* RoundingMode} values.
*
* @param mode rounding mode constant as defined in class {@code BigDecimal}
* @return corresponding rounding mode object
*/
public static RoundingMode valueOf(int mode) {
switch (mode) {
case BigDecimal.ROUND_CEILING:
return CEILING;
case BigDecimal.ROUND_DOWN:
return DOWN;
case BigDecimal.ROUND_FLOOR:
return FLOOR;
case BigDecimal.ROUND_HALF_DOWN:
return HALF_DOWN;
case BigDecimal.ROUND_HALF_EVEN:
return HALF_EVEN;
case BigDecimal.ROUND_HALF_UP:
return HALF_UP;
case BigDecimal.ROUND_UNNECESSARY:
return UNNECESSARY;
case BigDecimal.ROUND_UP:
return UP;
default:
// math.00=Invalid rounding mode
throw new IllegalArgumentException("Invalid rounding mode"); //$NON-NLS-1$
}
}
/**
* Bypasses calls to the implicit valueOf(String) method, which will break
* if enum name obfuscation is enabled. This should be package visible only.
*
* @param mode rounding mode string as defined in class {@code BigDecimal}
* @return corresponding rounding mode object
*/
static RoundingMode valueOfExplicit(String mode) {
/*
* Note this is optimized to avoid multiple String compares,
* using specific knowledge of the set of allowed enum constants.
*/
if (mode == null) {
throw new NullPointerException();
}
char[] modeChars = mode.toCharArray();
int len = modeChars.length;
if (len < chUP.length || len > chUNNECESSARY.length) {
throw new IllegalArgumentException();
}
char[] targetChars = null;
RoundingMode target = null;
if (modeChars[0] == 'C') {
target = RoundingMode.CEILING;
targetChars = chCEILING;
} else if (modeChars[0] == 'D') {
target = RoundingMode.DOWN;
targetChars = chDOWN;
} else if (modeChars[0] == 'F') {
target = RoundingMode.FLOOR;
targetChars = chFLOOR;
} else if (modeChars[0] == 'H') {
if (len > 6) {
if (modeChars[5] == 'D') {
target = RoundingMode.HALF_DOWN;
targetChars = chHALF_DOWN;
} else if (modeChars[5] == 'E') {
target = RoundingMode.HALF_EVEN;
targetChars = chHALF_EVEN;
} else if (modeChars[5] == 'U') {
target = RoundingMode.HALF_UP;
targetChars = chHALF_UP;
}
}
} else if (modeChars[0] == 'U') {
if (modeChars[1] == 'P') {
target = RoundingMode.UP;
targetChars = chUP;
} else if (modeChars[1] == 'N') {
target = RoundingMode.UNNECESSARY;
targetChars = chUNNECESSARY;
}
}
if (target != null && len == targetChars.length) {
int i;
for (i = 1; i < len && modeChars[i] == targetChars[i]; i++) {
}
if (i == len) {
return target;
}
}
throw new IllegalArgumentException();
}
/**
* Set the old constant.
* @param rm unused
*/
RoundingMode(int rm) {
// Note that we do not need the old-style rounding mode, so we ignore it.
}
}

View File

@ -0,0 +1,21 @@
package java.net;
import java.io.IOException;
public class UnknownServiceException extends IOException {
public UnknownServiceException() {
// TODO Auto-generated constructor stub
}
public UnknownServiceException(String s) {
super(s);
// TODO Auto-generated constructor stub
}
public UnknownServiceException(Exception e) {
super(e);
// TODO Auto-generated constructor stub
}
}

View File

@ -0,0 +1,121 @@
package java.security;
import com.google.gwt.core.client.JsArrayInteger;
public class SecureRandom extends java.util.Random
{
private static final double twoToThe24 = 16777216.0;
private static final double twoToThe31 = 2147483648.0;
private static final double twoToThe32 = 4294967296.0;
private static final double twoToTheMinus24 =
5.9604644775390625e-8;
private static final double twoToTheMinus26 =
1.490116119384765625e-8;
private static final double twoToTheMinus31 =
4.656612873077392578125e-10;
private static final double twoToTheMinus53 =
1.1102230246251565404236316680908203125e-16;
protected native JsArrayInteger jsNextChunk() /*-{
var words = $wnd.sjcl.random.randomWords(4);
return words;
}-*/;
public int next(int numBits)
{
int numBytes = (numBits+7)/8;
byte[] bytes = new byte[numBytes];
nextBytes(bytes);
int result=0;
for (int i=0; i<numBytes; ++i)
{
result |= bytes[i] << (8 * i);
}
return result;
}
public void nextBytes(byte[] bytes)
{
final int chunkSize = 4;
int chunks = (bytes.length+(chunkSize-1)) / chunkSize;
int j=0;
for (int i=0; i<chunks; ++i)
{
JsArrayInteger a = jsNextChunk();
int k=0;
while (j < bytes.length && k < chunkSize)
bytes[j++] = (byte)(a.get(k++));
}
}
public boolean nextBoolean ()
{
return next(1) != 0;
}
public int nextInt(int max)
{
return (int) next(32) % max;
}
public long nextLong()
{
return ((long) next(32) << 32) + (long) next(32);
}
public double nextDouble() {
return
next(26) * twoToTheMinus26 +
next(27) * twoToTheMinus53;
}
public float nextFloat() {
return (float) (next(24) * twoToTheMinus24);
}
public static class Test {
public static double test() {
// create random number generators
SecureRandom rand = new SecureRandom();
// total number of sample points to take
int numPoints = 10000;
int inRandCircle = 0;
double xr, yr, zr;
// xr and yr will be the random point
// zr will be the calculated distance to the center
for(int i=0; i < numPoints; ++i)
{
xr = rand.nextDouble();
yr = rand.nextDouble();
zr = (xr * xr) + (yr * yr);
if(zr <= 1.0)
inRandCircle++;
}
// calculate the Pi approximations
double randomPi = approxPi(inRandCircle, numPoints);
// calculate the % error
double randomError = calcError(randomPi);
return randomError;
}
static double approxPi(int inCircle, int totalPoints)
{
return (double)inCircle / totalPoints * 4.0;
}
static double calcError(double pi)
{
return (pi - Math.PI)/Math.PI * 100;
}
}
}

View File

@ -0,0 +1,109 @@
/*
* Copyright 2007 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package java.util;
/**
* Implements a hash table, which maps non-null keys to non-null values.
*
* @deprecated use @see{java.util.HashMap} instead
* @link http://java.sun.com/j2se/1.5.0/docs/api/java/util/Hashtable.html
*
* @param <K> key type.
* @param <V> value type.
*/
@Deprecated
public class Hashtable<K,V> implements Map<K,V>,
Cloneable {
/*
* This implementation simply delegates to HashMap.
*/
private HashMap<K,V> map;
public Hashtable() {
map = new HashMap<K,V>();
}
public Hashtable clone ()
{
Hashtable<K,V> c = new Hashtable<K,V>();
for (Map.Entry<K,V> e : map.entrySet())
c.put(e.getKey(), e.getValue());
return c;
}
public Hashtable(int initialSize) {
map = new HashMap<K,V>();
}
public void clear() {
map.clear();
}
public boolean containsKey(Object key) {
return map.containsKey(key);
}
public boolean containsValue(Object value) {
return map.containsValue(value);
}
public Enumeration<V> elements() {
return Collections.enumeration(map.values());
}
public Set<Map.Entry<K, V>> entrySet() {
return map.entrySet();
}
public V get(Object key) {
return map.get(key);
}
public boolean isEmpty() {
return map.isEmpty();
}
public Enumeration<K> keys() {
return Collections.enumeration(map.keySet());
}
public Set<K> keySet() {
return map.keySet();
}
public V put(K key, V value) {
return map.put(key, value);
}
public void putAll(Map<? extends K,? extends V> otherMap) {
map.putAll(otherMap);
}
public V remove(Object key) {
return map.remove(key);
}
public int size() {
return map.size();
}
public Collection<V> values() {
return map.values();
}
}

View File

@ -0,0 +1,5 @@
package java.util;
public class Properties {
}

View File

@ -0,0 +1,201 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package java.util;
/**
* String tokenizer is used to break a string apart into tokens.
*
* If returnDelimiters is false, successive calls to nextToken() return maximal
* blocks of characters that do not contain a delimiter.
*
* If returnDelimiters is true, delimiters are considered to be tokens, and
* successive calls to nextToken() return either a one character delimiter, or a
* maximal block of text between delimiters.
*/
public class StringTokenizer {
private String string;
private String delimiters;
private boolean returnDelimiters;
private int position;
/**
* Constructs a new StringTokenizer for string using whitespace as the
* delimiter, returnDelimiters is false.
*
* @param string
* the string to be tokenized
*/
public StringTokenizer(String string) {
this(string, " \t\n\r\f", false); //$NON-NLS-1$
}
/**
* Constructs a new StringTokenizer for string using the specified
* delimiters, returnDelimiters is false.
*
* @param string
* the string to be tokenized
* @param delimiters
* the delimiters to use
*/
public StringTokenizer(String string, String delimiters) {
this(string, delimiters, false);
}
/**
* Constructs a new StringTokenizer for string using the specified
* delimiters and returning delimiters as tokens when specified.
*
* @param string
* the string to be tokenized
* @param delimiters
* the delimiters to use
* @param returnDelimiters
* true to return each delimiter as a token
*/
public StringTokenizer(String string, String delimiters,
boolean returnDelimiters) {
if (string != null) {
this.string = string;
this.delimiters = delimiters;
this.returnDelimiters = returnDelimiters;
this.position = 0;
} else
throw new NullPointerException();
}
/**
* Returns the number of unprocessed tokens remaining in the string.
*
* @return number of tokens that can be retreived before an exception will
* result
*/
public int countTokens() {
int count = 0;
boolean inToken = false;
for (int i = position, length = string.length(); i < length; i++) {
if (delimiters.indexOf(string.charAt(i), 0) >= 0) {
if (returnDelimiters)
count++;
if (inToken) {
count++;
inToken = false;
}
} else {
inToken = true;
}
}
if (inToken)
count++;
return count;
}
/**
* Returns true if unprocessed tokens remain.
*
* @return true if unprocessed tokens remain
*/
public boolean hasMoreElements() {
return hasMoreTokens();
}
/**
* Returns true if unprocessed tokens remain.
*
* @return true if unprocessed tokens remain
*/
public boolean hasMoreTokens() {
int length = string.length();
if (position < length) {
if (returnDelimiters)
return true; // there is at least one character and even if
// it is a delimiter it is a token
// otherwise find a character which is not a delimiter
for (int i = position; i < length; i++)
if (delimiters.indexOf(string.charAt(i), 0) == -1)
return true;
}
return false;
}
/**
* Returns the next token in the string as an Object.
*
* @return next token in the string as an Object
* @exception NoSuchElementException
* if no tokens remain
*/
public Object nextElement() {
return nextToken();
}
/**
* Returns the next token in the string as a String.
*
* @return next token in the string as a String
* @exception NoSuchElementException
* if no tokens remain
*/
public String nextToken() {
int i = position;
int length = string.length();
if (i < length) {
if (returnDelimiters) {
if (delimiters.indexOf(string.charAt(position), 0) >= 0)
return String.valueOf(string.charAt(position++));
for (position++; position < length; position++)
if (delimiters.indexOf(string.charAt(position), 0) >= 0)
return string.substring(i, position);
return string.substring(i);
}
while (i < length && delimiters.indexOf(string.charAt(i), 0) >= 0)
i++;
position = i;
if (i < length) {
for (position++; position < length; position++)
if (delimiters.indexOf(string.charAt(position), 0) >= 0)
return string.substring(i, position);
return string.substring(i);
}
}
throw new NoSuchElementException();
}
/**
* Returns the next token in the string as a String. The delimiters used are
* changed to the specified delimiters.
*
* @param delims
* the new delimiters to use
* @return next token in the string as a String
* @exception NoSuchElementException
* if no tokens remain
*/
public String nextToken(String delims) {
this.delimiters = delims;
return nextToken();
}
}

12
gwt/src/app/GWT.gwt.xml Normal file
View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
When updating your version of GWT, you should also update this DTD reference,
so that your app can take advantage of the latest GWT module capabilities.
-->
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.5.0//EN"
"http://google-web-toolkit.googlecode.com/svn/tags/2.5.0/distro-source/core/src/gwt-module.dtd">
<module>
<!-- Specify the paths for translatable code -->
<source path=''/>
</module>

View File

@ -0,0 +1,21 @@
/**
* Author: Timothy Prepscius
* License: GPLv3 Affero + keep my name in the code!
*/
package app.service;
import org.timepedia.exporter.client.Export;
import org.timepedia.exporter.client.Exportable;
@Export()
public class AsyncException extends Exception implements Exportable {
public AsyncException() {
// TODO Auto-generated constructor stub
}
public AsyncException(String message) {
super(message);
// TODO Auto-generated constructor stub
}
}

View File

@ -0,0 +1,19 @@
/**
* Author: Timothy Prepscius
* License: GPLv3 Affero + keep my name in the code!
*/
package app.service;
import com.google.gwt.core.client.JavaScriptObject;
public class JSApplet {
// public void paint( Graphics g ) {
// g.drawString(VERSION_STRING,4,15);
// }
static public native JavaScriptObject getWindow(Object o) /*-{
return $wnd;
}-*/;
}

View File

@ -0,0 +1 @@
../../../../java/app/service/src/app/service/JSClient.java

View File

@ -0,0 +1,103 @@
/**
* Author: Timothy Prepscius
* License: GPLv3 Affero + keep my name in the code!
*/
package app.service;
import org.timepedia.exporter.client.Export;
import org.timepedia.exporter.client.Exportable;
import mail.auth.MailServerAuthenticatorNoThread;
import mail.client.EventPropagator;
import core.callback.CallbackChain;
import core.callback.CallbackDefault;
import core.callback.CallbackWithVariables;
import core.constants.ConstantsClient;
import core.crypt.KeyPairFromPassword;
import core.srp.client.SRPClientListener;
import core.util.LogNull;
@Export
public class JSDelete implements Exportable, SRPClientListener
{
static LogNull log = new LogNull(JSDelete.class);
Main main;
JSDelete (Main main)
{
this.main = main;
}
static class DeleteInfo
{
String name, password;
KeyPairFromPassword keyPair;
JSResult<Boolean> callback;
public DeleteInfo(String name, String password, JSResult<Boolean> callback)
{
this.name = name;
this.password = password;
this.callback = callback;
}
}
public void doDelete (
String name, String password,
Object callback
)
{
log.debug("delete", name, password);
CallbackChain chain = new CallbackChain();
DeleteInfo info = new DeleteInfo(name, password, new JSResult<Boolean>(callback));
chain.addCallback(new CallbackDefault(info) {
public void onSuccess(Object... arguments) throws Exception {
log.debug("delete_step_genKeyPair");
DeleteInfo info = (DeleteInfo)V(0);
JSInvoker.invoke(info.callback.getCallback(), "progress", new Object[] { "Creating verification key pair." });
info.keyPair = new KeyPairFromPassword(info.password);
info.keyPair.generate_().addCallback(callback).invoke();
}
});
chain.addCallback(new CallbackDefault(info) {
public void onSuccess(Object... arguments) throws Exception {
log.debug("delete_step_doDelete");
DeleteInfo info = (DeleteInfo)V(0);
JSInvoker.invoke(info.callback.getCallback(), "progress", new Object[] { "Deleting account." });
call(
MailServerAuthenticatorNoThread.delete_(
info.name, info.keyPair,
new JSStreamSessionWebSocket(ConstantsClient.MAIL_SERVER_WEBSOCKET, main.delegate),
JSDelete.this
)
);
}
});
chain.addCallback(new CallbackWithVariables(info) {
@Override
public void invoke(Object... arguments) {
DeleteInfo info = (DeleteInfo)V(0);
info.callback.invoke(arguments);
}
});
main.eventPropagator.signal(
EventPropagator.INVOKE,
chain
);
}
public void onSRPStep (String event)
{
main.eventPropagator.signal("onAuthenticationStep", event);
}
}

View File

@ -0,0 +1 @@
../../../../java/app/service/src/app/service/JSEventPropagator.java

View File

@ -0,0 +1 @@
../../../../java/app/service/src/app/service/JSHttpDelegate.java

View File

@ -0,0 +1,377 @@
/**
* Author: Timothy Prepscius
* License: GPLv3 Affero + keep my name in the code!
*/
package app.service;
import java.util.Collection;
import mail.client.model.Mail;
import org.timepedia.exporter.client.Export;
import org.timepedia.exporter.client.Exportable;
import org.timepedia.exporter.client.ExporterUtil;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.JsArray;
import core.util.LogNull;
import core.util.LogOut;
@Export
public class JSInvoker implements Exportable
{
static LogNull log = new LogNull(JSInvoker.class);
private static native JavaScriptObject _wrap(boolean o) /*-{
return o;
}-*/;
private static native JavaScriptObject _wrap(int o) /*-{
return o;
}-*/;
private static native JavaScriptObject _wrap(String o) /*-{
return o;
}-*/;
private static JsArray<JavaScriptObject> _wrap(Object[] o)
{
JsArray<JavaScriptObject> a = JavaScriptObject.createArray().cast();
for (Object i : o)
a.push(wrap(i));
return a;
}
static public JavaScriptObject wrap(Object o)
{
if (o instanceof Boolean)
return _wrap((boolean)(Boolean)o);
else
if (o instanceof Integer)
return _wrap((int)(Integer)o);
else
if (o instanceof String)
return _wrap((String)o);
else
if (o instanceof Object[])
return _wrap((Object[])o);
else
if (o instanceof Collection)
return _wrap(((Collection<?>)o).toArray());
else
if (o instanceof Mail)
return wrap(new MailI((Mail)o));
try
{
return ExporterUtil.wrap(o);
}
catch (Throwable e)
{
log.debug(e);
return (JavaScriptObject)o;
}
}
static JavaScriptObject invoke (Object oo, String f, Object[] p) throws Exception
{
try
{
return doInvoke(oo, f, p);
}
catch (Exception e)
{
throw e;
}
catch (Throwable t)
{
throw new Exception(t.toString());
}
}
static JavaScriptObject doInvoke (Object oo, String f, Object[] p) throws Throwable
{
JavaScriptObject o = (JavaScriptObject)oo;
if (p == null || p.length == 0)
return invoke0(o,f);
else
if (p.length == 1)
return invoke1(o,f,
wrap(p[0])
);
else
if (p.length == 2)
return invoke2(o,f,
wrap(p[0]),
wrap(p[1])
);
else
if (p.length == 3)
return invoke3(o,f,
wrap(p[0]),
wrap(p[1]),
wrap(p[2])
);
else
if (p.length == 4)
return invoke4(o,f,
wrap(p[0]),
wrap(p[1]),
wrap(p[2]),
wrap(p[3])
);
else
if (p.length == 5)
return invoke5(o,f,
wrap(p[0]),
wrap(p[1]),
wrap(p[2]),
wrap(p[3]),
wrap(p[4])
);
else
if (p.length == 6)
return invoke6(o,f,
wrap(p[0]),
wrap(p[1]),
wrap(p[2]),
wrap(p[3]),
wrap(p[4]),
wrap(p[5])
);
else
if (p.length == 7)
return invoke7(o,f,
wrap(p[0]),
wrap(p[1]),
wrap(p[2]),
wrap(p[3]),
wrap(p[4]),
wrap(p[5]),
wrap(p[6])
);
else
if (p.length == 8)
return invoke8(o,f,
wrap(p[0]),
wrap(p[1]),
wrap(p[2]),
wrap(p[3]),
wrap(p[4]),
wrap(p[5]),
wrap(p[6]),
wrap(p[7])
);
else
if (p.length == 9)
return invoke9(o,f,
wrap(p[0]),
wrap(p[1]),
wrap(p[2]),
wrap(p[3]),
wrap(p[4]),
wrap(p[5]),
wrap(p[6]),
wrap(p[7]),
wrap(p[8])
);
else
if (p.length == 10)
return invoke10(o,f,
wrap(p[0]),
wrap(p[1]),
wrap(p[2]),
wrap(p[3]),
wrap(p[4]),
wrap(p[5]),
wrap(p[6]),
wrap(p[7]),
wrap(p[8]),
wrap(p[9])
);
return null;
}
static native JavaScriptObject invoke0 (JavaScriptObject o, String f) /*-{
return o[f].call(o);
}-*/;
static native JavaScriptObject invoke1 (JavaScriptObject o, String f,
JavaScriptObject p0
) /*-{
return o[f].call(o,
p0
);
}-*/;
static native JavaScriptObject invoke2 (JavaScriptObject o, String f,
JavaScriptObject p0,
JavaScriptObject p1
) /*-{
return o[f].call(o,
p0,
p1
);
}-*/;
static native JavaScriptObject invoke3 (JavaScriptObject o, String f,
JavaScriptObject p0,
JavaScriptObject p1,
JavaScriptObject p2
) /*-{
return o[f].call(o,
p0,
p1,
p2
);
}-*/;
static native JavaScriptObject invoke4 (JavaScriptObject o, String f,
JavaScriptObject p0,
JavaScriptObject p1,
JavaScriptObject p2,
JavaScriptObject p3
) /*-{
return o[f].call(o,
p0,
p1,
p2,
p3
);
}-*/;
static native JavaScriptObject invoke5 (JavaScriptObject o, String f,
JavaScriptObject p0,
JavaScriptObject p1,
JavaScriptObject p2,
JavaScriptObject p3,
JavaScriptObject p4
) /*-{
return o[f].call(o,
p0,
p1,
p2,
p3,
p4
);
}-*/;
static native JavaScriptObject invoke6 (JavaScriptObject o, String f,
JavaScriptObject p0,
JavaScriptObject p1,
JavaScriptObject p2,
JavaScriptObject p3,
JavaScriptObject p4,
JavaScriptObject p5
) /*-{
return o[f].call(o,
p0,
p1,
p2,
p3,
p4,
p5
);
}-*/;
static native JavaScriptObject invoke7 (JavaScriptObject o, String f,
JavaScriptObject p0,
JavaScriptObject p1,
JavaScriptObject p2,
JavaScriptObject p3,
JavaScriptObject p4,
JavaScriptObject p5,
JavaScriptObject p6
) /*-{
return o[f].call(o,
p0,
p1,
p2,
p3,
p4,
p5,
p6
);
}-*/;
static native JavaScriptObject invoke8 (JavaScriptObject o, String f,
JavaScriptObject p0,
JavaScriptObject p1,
JavaScriptObject p2,
JavaScriptObject p3,
JavaScriptObject p4,
JavaScriptObject p5,
JavaScriptObject p6,
JavaScriptObject p7
) /*-{
return o[f].call(o,
p0,
p1,
p2,
p3,
p4,
p5,
p6,
p7
);
}-*/;
static native JavaScriptObject invoke9 (JavaScriptObject o, String f,
JavaScriptObject p0,
JavaScriptObject p1,
JavaScriptObject p2,
JavaScriptObject p3,
JavaScriptObject p4,
JavaScriptObject p5,
JavaScriptObject p6,
JavaScriptObject p7,
JavaScriptObject p8
) /*-{
return o[f].call(o,
p0,
p1,
p2,
p3,
p4,
p5,
p6,
p7,
p8
);
}-*/;
static native JavaScriptObject invoke10 (JavaScriptObject o, String f,
JavaScriptObject p0,
JavaScriptObject p1,
JavaScriptObject p2,
JavaScriptObject p3,
JavaScriptObject p4,
JavaScriptObject p5,
JavaScriptObject p6,
JavaScriptObject p7,
JavaScriptObject p8,
JavaScriptObject p9
) /*-{
return o[f].call(o,
p0,
p1,
p2,
p3,
p4,
p5,
p6,
p7,
p8,
p9
);
}-*/;
public native static JavaScriptObject getMember(Object o, String s) /*-{
return o[s];
}-*/;
}

View File

@ -0,0 +1,323 @@
/**
* Author: Timothy Prepscius
* License: GPLv3 Affero + keep my name in the code!
*/
package app.service;
import com.google.gwt.core.client.JavaScriptObject;
import core.util.Characters;
import core.util.LogNull;
import core.util.LogOut;
public class JSInvokerNo
{
static LogNull log = new LogNull(JSInvokerNo.class);
static String className(Class<?> c)
{
String name = c.getName();
int d = name.lastIndexOf('$');
if (d != -1)
{
if (d+1 < name.length())
{
if (Characters.isNumber(name.charAt(d+1)))
return className(c.getSuperclass());
}
}
return name;
}
static String classOf(Object p)
{
if (p == null)
return null;
return className(p.getClass());
}
static JavaScriptObject invoke (Object oo, String f, Object[] p)
{
JavaScriptObject o = (JavaScriptObject)oo;
if (p == null || p.length == 0)
return invoke0(o,f);
else
if (p.length == 1)
return invoke1(o,f,classOf(p[0]), p[0]);
else
if (p.length == 2)
return invoke2(o,f,
classOf(p[0]), p[0],
classOf(p[1]), p[1]
);
else
if (p.length == 3)
return invoke3(o,f,
classOf(p[0]), p[0],
classOf(p[1]), p[1],
classOf(p[2]), p[2]
);
else
if (p.length == 4)
return invoke4(o,f,
classOf(p[0]), p[0],
classOf(p[1]), p[1],
classOf(p[2]), p[2],
classOf(p[3]), p[3]
);
else
if (p.length == 5)
return invoke5(o,f,
classOf(p[0]), p[0],
classOf(p[1]), p[1],
classOf(p[2]), p[2],
classOf(p[3]), p[3],
classOf(p[4]), p[4]
);
else
if (p.length == 6)
return invoke6(o,f,
classOf(p[0]), p[0],
classOf(p[1]), p[1],
classOf(p[2]), p[2],
classOf(p[3]), p[3],
classOf(p[4]), p[4],
classOf(p[5]), p[5]
);
else
if (p.length == 7)
return invoke7(o,f,
classOf(p[0]), p[0],
classOf(p[1]), p[1],
classOf(p[2]), p[2],
classOf(p[3]), p[3],
classOf(p[4]), p[4],
classOf(p[5]), p[5],
classOf(p[6]), p[6]
);
else
if (p.length == 8)
return invoke8(o,f,
classOf(p[0]), p[0],
classOf(p[1]), p[1],
classOf(p[2]), p[2],
classOf(p[3]), p[3],
classOf(p[4]), p[4],
classOf(p[5]), p[5],
classOf(p[6]), p[6],
classOf(p[7]), p[7]
);
else
if (p.length == 9)
return invoke9(o,f,
classOf(p[0]), p[0],
classOf(p[1]), p[1],
classOf(p[2]), p[2],
classOf(p[3]), p[3],
classOf(p[4]), p[4],
classOf(p[5]), p[5],
classOf(p[6]), p[6],
classOf(p[7]), p[7],
classOf(p[8]), p[8]
);
else
if (p.length == 10)
return invoke10(o,f,
classOf(p[0]), p[0],
classOf(p[1]), p[1],
classOf(p[2]), p[2],
classOf(p[3]), p[3],
classOf(p[4]), p[4],
classOf(p[5]), p[5],
classOf(p[6]), p[6],
classOf(p[7]), p[7],
classOf(p[8]), p[8],
classOf(p[9]), p[9]
);
return null;
}
static native JavaScriptObject invoke0 (JavaScriptObject o, String f) /*-{
return o[f].call(o);
}-*/;
static native JavaScriptObject invoke1 (JavaScriptObject o, String f,
String c0, Object p0
) /*-{
return o[f].call(o,
$wnd.bindExportable(p0, c0)
);
}-*/;
static native JavaScriptObject invoke2 (JavaScriptObject o, String f,
String c0, Object p0,
String c1, Object p1
) /*-{
return o[f].call(o,
$wnd.bindExportable(p0, c0),
$wnd.bindExportable(p1, c1)
);
}-*/;
static native JavaScriptObject invoke3 (JavaScriptObject o, String f,
String c0, Object p0,
String c1, Object p1,
String c2, Object p2
) /*-{
return o[f].call(o,
$wnd.bindExportable(p0, c0),
$wnd.bindExportable(p1, c1),
$wnd.bindExportable(p2, c2)
);
}-*/;
static native JavaScriptObject invoke4 (JavaScriptObject o, String f,
String c0, Object p0,
String c1, Object p1,
String c2, Object p2,
String c3, Object p3
) /*-{
return o[f].call(o,
$wnd.bindExportable(p0, c0),
$wnd.bindExportable(p1, c1),
$wnd.bindExportable(p2, c2),
$wnd.bindExportable(p3, c3)
);
}-*/;
static native JavaScriptObject invoke5 (JavaScriptObject o, String f,
String c0, Object p0,
String c1, Object p1,
String c2, Object p2,
String c3, Object p3,
String c4, Object p4
) /*-{
return o[f].call(o,
$wnd.bindExportable(p0, c0),
$wnd.bindExportable(p1, c1),
$wnd.bindExportable(p2, c2),
$wnd.bindExportable(p3, c3),
$wnd.bindExportable(p4, c4)
);
}-*/;
static native JavaScriptObject invoke6 (JavaScriptObject o, String f,
String c0, Object p0,
String c1, Object p1,
String c2, Object p2,
String c3, Object p3,
String c4, Object p4,
String c5, Object p5
) /*-{
return o[f].call(o,
$wnd.bindExportable(p0, c0),
$wnd.bindExportable(p1, c1),
$wnd.bindExportable(p2, c2),
$wnd.bindExportable(p3, c3),
$wnd.bindExportable(p4, c4),
$wnd.bindExportable(p5, c5)
);
}-*/;
static native JavaScriptObject invoke7 (JavaScriptObject o, String f,
String c0, Object p0,
String c1, Object p1,
String c2, Object p2,
String c3, Object p3,
String c4, Object p4,
String c5, Object p5,
String c6, Object p6
) /*-{
return o[f].call(o,
$wnd.bindExportable(p0, c0),
$wnd.bindExportable(p1, c1),
$wnd.bindExportable(p2, c2),
$wnd.bindExportable(p3, c3),
$wnd.bindExportable(p4, c4),
$wnd.bindExportable(p5, c5),
$wnd.bindExportable(p6, c6)
);
}-*/;
static native JavaScriptObject invoke8 (JavaScriptObject o, String f,
String c0, Object p0,
String c1, Object p1,
String c2, Object p2,
String c3, Object p3,
String c4, Object p4,
String c5, Object p5,
String c6, Object p6,
String c7, Object p7
) /*-{
return o[f].call(o,
$wnd.bindExportable(p0, c0),
$wnd.bindExportable(p1, c1),
$wnd.bindExportable(p2, c2),
$wnd.bindExportable(p3, c3),
$wnd.bindExportable(p4, c4),
$wnd.bindExportable(p5, c5),
$wnd.bindExportable(p6, c6),
$wnd.bindExportable(p7, c7)
);
}-*/;
static native JavaScriptObject invoke9 (JavaScriptObject o, String f,
String c0, Object p0,
String c1, Object p1,
String c2, Object p2,
String c3, Object p3,
String c4, Object p4,
String c5, Object p5,
String c6, Object p6,
String c7, Object p7,
String c8, Object p8
) /*-{
return o[f].call(o,
$wnd.bindExportable(p0, c0),
$wnd.bindExportable(p1, c1),
$wnd.bindExportable(p2, c2),
$wnd.bindExportable(p3, c3),
$wnd.bindExportable(p4, c4),
$wnd.bindExportable(p5, c5),
$wnd.bindExportable(p6, c6),
$wnd.bindExportable(p7, c7),
$wnd.bindExportable(p8, c8)
);
}-*/;
static native JavaScriptObject invoke10 (JavaScriptObject o, String f,
String c0, Object p0,
String c1, Object p1,
String c2, Object p2,
String c3, Object p3,
String c4, Object p4,
String c5, Object p5,
String c6, Object p6,
String c7, Object p7,
String c8, Object p8,
String c9, Object p9
) /*-{
return o[f].call(o,
$wnd.bindExportable(p0, c0),
$wnd.bindExportable(p1, c1),
$wnd.bindExportable(p2, c2),
$wnd.bindExportable(p3, c3),
$wnd.bindExportable(p4, c4),
$wnd.bindExportable(p5, c5),
$wnd.bindExportable(p6, c6),
$wnd.bindExportable(p7, c7),
$wnd.bindExportable(p8, c8),
$wnd.bindExportable(p9, c9)
);
}-*/;
public native static JavaScriptObject getMember(Object o, String s) /*-{
return o[s];
}-*/;
}

View File

@ -0,0 +1 @@
../../../../java/app/service/src/app/service/JSRefill.java

View File

@ -0,0 +1 @@
../../../../java/app/service/src/app/service/JSResult.java

View File

@ -0,0 +1 @@
../../../../java/app/service/src/app/service/JSSignUp.java

View File

@ -0,0 +1 @@
../../../../java/app/service/src/app/service/JSStreamSessionWebSocket.java

View File

@ -0,0 +1 @@
../../../../java/app/service/src/app/service/MailI.java

View File

@ -0,0 +1 @@
../../../../java/app/service/src/app/service/Main.java

View File

@ -0,0 +1 @@
../../../../java/app/service/src/app/service/ServiceAppletRunnable.java

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
When updating your version of GWT, you should also update this DTD reference,
so that your app can take advantage of the latest GWT module capabilities.
-->
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.5.0//EN"
"http://google-web-toolkit.googlecode.com/svn/tags/2.5.0/distro-source/core/src/gwt-module.dtd">
<module>
<!-- Specify the paths for translatable code -->
<source path=''/>
</module>

View File

@ -0,0 +1,17 @@
/**
* Author: Timothy Prepscius
* License: GPLv3 Affero + keep my name in the code!
*/
package com.jordanzimmerman;
import core.crypt.HashSha256;
public class Hash256i
{
HashSha256 hash = new HashSha256();
public byte[] hash(byte[] bytes)
{
return hash.hash(bytes);
}
}

View File

@ -0,0 +1,13 @@
/**
* Author: Timothy Prepscius
* License: GPLv3 Affero + keep my name in the code!
*/
package com.jordanzimmerman;
public class Logz {
public static void println(String string) {
System.out.println(string);
}
}

View File

@ -0,0 +1 @@
../../../../java/ext/jordanzimmerman/src/com/jordanzimmerman/SRPAuthenticationFailedException.java

View File

@ -0,0 +1 @@
../../../../java/ext/jordanzimmerman/src/com/jordanzimmerman/SRPClientSession.java

View File

@ -0,0 +1,12 @@
package com.jordanzimmerman;
public interface SRPClientSessionInterface {
public void setSalt_s(byte[] bs);
public void setServerPublicKey_B(byte[] publicKey) throws SRPAuthenticationFailedException;
public byte[] getSessionKey_K();
public byte[] getPublicKey_A();
public byte[] getEvidenceValue_M1();
public void validateServerEvidenceValue_M2(byte[] evidence) throws SRPAuthenticationFailedException;
}

View File

@ -0,0 +1 @@
../../../../java/ext/jordanzimmerman/src/com/jordanzimmerman/SRPConstants.java

View File

@ -0,0 +1 @@
../../../../java/ext/jordanzimmerman/src/com/jordanzimmerman/SRPFactory.java

View File

@ -0,0 +1 @@
../../../../java/ext/jordanzimmerman/src/com/jordanzimmerman/SRPRunner.java

View File

@ -0,0 +1 @@
../../../../java/ext/jordanzimmerman/src/com/jordanzimmerman/SRPServerSession.java

View File

@ -0,0 +1 @@
../../../../java/ext/jordanzimmerman/src/com/jordanzimmerman/SRPUtils.java

View File

@ -0,0 +1 @@
../../../../java/ext/jordanzimmerman/src/com/jordanzimmerman/SRPVerifier.java

View File

@ -0,0 +1,9 @@
/**
* Author: Timothy Prepscius
* License: GPLv3 Affero + keep my name in the code!
*/
package com.jordanzimmerman;
public class SecureRandomi extends java.security.SecureRandom {
}

View File

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
When updating your version of GWT, you should also update this DTD reference,
so that your app can take advantage of the latest GWT module capabilities.
-->
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.5.0//EN"
"http://google-web-toolkit.googlecode.com/svn/tags/2.5.0/distro-source/core/src/gwt-module.dtd">
<module rename-to='mailiverse_gwt'>
<inherits name='com.google.gwt.user.User'/>
<inherits name='com.google.gwt.xml.XML'/>
<inherits name='com.google.gwt.json.JSON'/>
<inherits name='com.jordanzimmerman.GWT'/>
<inherits name='org.json.GWT'/>
<inherits name='core.GWT'/>
<inherits name='key.GWT'/>
<inherits name='mail.GWT'/>
<inherits name='app.GWT'/>
<inherits name='JRE'/>
<inherits name='org.timepedia.exporter.Exporter'/>
<set-property name="export" value="yes"/>
<!-- Specify the app entry point class. -->
<entry-point class='com.mailiverse.gwt.client.Mailiverse_GWT'/>
<!--
<add-linker name="xsiframe" />
<set-configuration-property name="devModeRedirectEnabled" value="true" />
<set-property name="user.agent" value="safari" />
-->
<!-- Specify the paths for translatable code -->
<source path='client'/>
<source path='shared'/>
</module>

View File

@ -0,0 +1,48 @@
/**
* Author: Timothy Prepscius
* License: GPLv3 Affero + keep my name in the code!
*/
package com.mailiverse.gwt.client;
import org.timepedia.exporter.client.ExporterUtil;
import mail.client.model.Original;
import app.service.Main;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.event.dom.client.KeyUpHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
/**
* Entry point classes define <code>onModuleLoad()</code>.
*/
public class Mailiverse_GWT implements EntryPoint {
/**
* This is the entry point method.
*/
public native void propagateLoad (JavaScriptObject main) /*-{
$wnd.onMailiverseBootstrapGWT(main);
}-*/;
public void onModuleLoad()
{
ExporterUtil.exportAll();
propagateLoad(ExporterUtil.wrap(new Main()));
}
}

12
gwt/src/core/GWT.gwt.xml Normal file
View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
When updating your version of GWT, you should also update this DTD reference,
so that your app can take advantage of the latest GWT module capabilities.
-->
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.5.0//EN"
"http://google-web-toolkit.googlecode.com/svn/tags/2.5.0/distro-source/core/src/gwt-module.dtd">
<module>
<!-- Specify the paths for translatable code -->
<source path=''/>
</module>

View File

@ -0,0 +1 @@
../../../../java/core/src/core/callback/Callback.java

View File

@ -0,0 +1 @@
../../../../java/core/src/core/callback/CallbackChain.java

View File

@ -0,0 +1 @@
../../../../java/core/src/core/callback/CallbackDefault.java

View File

@ -0,0 +1 @@
../../../../java/core/src/core/callback/CallbackEmpty.java

View File

@ -0,0 +1 @@
../../../../java/core/src/core/callback/CallbackInterface.java

View File

@ -0,0 +1 @@
../../../../java/core/src/core/callback/CallbackSync.java

View File

@ -0,0 +1 @@
../../../../java/core/src/core/callback/CallbackWithVariables.java

View File

@ -0,0 +1 @@
../../../../java/core/src/core/callbacks/CountDown.java

View File

@ -0,0 +1 @@
../../../../java/core/src/core/callbacks/IoOnReceive.java

View File

@ -0,0 +1 @@
../../../../java/core/src/core/callbacks/IoOpen.java

View File

@ -0,0 +1 @@
../../../../java/core/src/core/callbacks/IoSend.java

View File

@ -0,0 +1 @@
../../../../java/core/src/core/callbacks/IoStop.java

View File

@ -0,0 +1 @@
../../../../java/core/src/core/callbacks/JSONDeserialize.java

View File

@ -0,0 +1 @@
../../../../java/core/src/core/callbacks/JSONSerialize.java

View File

@ -0,0 +1 @@
../../../../java/core/src/core/callbacks/Memory.java

View File

@ -0,0 +1 @@
../../../../java/core/src/core/callbacks/SaveArguments.java

View File

@ -0,0 +1 @@
../../../../java/core/src/core/callbacks/Single.java

Some files were not shown because too many files have changed in this diff Show More