Added MersenneTwisterFast (replaces java.util.Random), added missing licenses. Added field annonation exclusion serilaizer. Code polish

This commit is contained in:
nathan 2014-08-25 01:56:20 +02:00
parent 499e0bbfd7
commit 61e9862069
64 changed files with 357 additions and 2062 deletions

View File

@ -4,36 +4,36 @@ Legal:
- Copyright (c) 2010 and beyond, dorkbox llc. All rights reserved.
This software is a commercial product. Use, redistribution, and
This software is a commercial product. Use, redistribution, and
modification without a license is NOT permitted. Contact
license@dorkbox.com for a license.
Neither the name of dorkbox, dorkbox llc, or dorkbox.com or the names of
its contributors may be used to endorse or promote products derived from
Neither the name of dorkbox, dorkbox llc, or dorkbox.com or the names of
its contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
THE POSSIBILITY OF SUCH DAMAGE.
THIS SOFTWARE IS NOT DESIGNED OR INTENDED FOR USE OR RESALE AS
THIS SOFTWARE IS NOT DESIGNED OR INTENDED FOR USE OR RESALE AS
ON-LINE CONTROL EQUIPMENT IN HAZARDOUS ENVIRONMENTS REQUIRING FAIL-SAFE
PERFORMANCE, SUCH AS IN THE OPERATION OF NUCLEAR FACILITIES, AIRCRAFT
NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL, DIRECT LIFE
PERFORMANCE, SUCH AS IN THE OPERATION OF NUCLEAR FACILITIES, AIRCRAFT
NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL, DIRECT LIFE
SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH THE FAILURE OF THE SOFTWARE
COULD LEAD DIRECTLY TO DEATH, PERSONAL INJURY, OR SEVERE PHYSICAL OR
COULD LEAD DIRECTLY TO DEATH, PERSONAL INJURY, OR SEVERE PHYSICAL OR
ENVIRONMENTAL DAMAGE ("HIGH RISK ACTIVITIES").
THIS AGREEMENT IS GOVERNED THE INTELLECTUAL PROPERTY LAWS OF THE UNITED
STATES OF AMERICA. NO PARTY TO THIS AGREEMENT WILL BRING A LEGAL ACTION
STATES OF AMERICA. NO PARTY TO THIS AGREEMENT WILL BRING A LEGAL ACTION
UNDER THIS AGREEMENT MORE THAN ONE YEAR AFTER THE CAUSE OF ACTION AROSE.
EACH PARTY WAIVES ITS RIGHTS TO A JURY TRIAL IN ANY RESULTING LITIGATION.
@ -47,25 +47,25 @@ Legal:
https://bxa.ntis.gov/
Details of the U.S. Commercial Encryption Export Controls can be found at
the Bureau of Industry and Security (BIS) web site.
the Bureau of Industry and Security (BIS) web site.
http://www.bis.doc.gov/
PROHIBITED END USERS
ALL products are prohibited for export/reexport to the following:
- Any company or national of Cuba, Iran, North Korea, Sudan, and Syria.
- Any company or national of Cuba, Iran, North Korea, Sudan, and Syria.
Licenses to these countries and parties are presumed denied.
- Re-export to these countries is prohibited; if you "know or have reason
- Re-export to these countries is prohibited; if you "know or have reason
to know" that an illegal reshipment will take place, you may not ship to
such a user.
- Entities listed on any U.S. Government Denied Party/Person List. See BIS's
The Denied Persons List, the Office of Foreign Assets Control's Economic
and Trade sanctions list, (OFAC), and the Office of Defense Trade
- Entities listed on any U.S. Government Denied Party/Person List. See BIS's
The Denied Persons List, the Office of Foreign Assets Control's Economic
and Trade sanctions list, (OFAC), and the Office of Defense Trade
Controls (DTC).
- Any customer you know or have reason to know, who is involved in the
- Any customer you know or have reason to know, who is involved in the
design, development, manufacture or production of nuclear technology, or
nuclear, biological or chemical "weapons of mass destruction."
@ -74,11 +74,19 @@ Legal:
- ArraysAsListSerializer,
UnmodifiableCollectionsSerializer - Apache 2.0 license
https://github.com/magro/kryo-serializers
Copyright 2010 Martin Grotzke
- ASM - Bytecode manipulation framework and utilities - New BSD license
http://asm.ow2.org/
Copyright (c) 2012 France Télécom
All rights reserved.
- BarchartUDT - BSD license
@ -90,17 +98,23 @@ Legal:
- BouncyCastle - MIT X11 License
http://www.bouncycastle.org
Copyright (c) 2000 - 2009 The Legion Of The Bouncy Castle
- FieldAnnotationAwareSerializer - Apache 2.0 license
https://github.com/magro/kryo-serializers
Copyright 2010 Martin Grotzke, Rafael Winterhalter
- JAVASSIST - Apache 2.0 license
http://www.csg.is.titech.ac.jp/~chiba/javassist/
Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
Contributor(s): Bill Burke, Jason T. Greene
Note: it is licensed under the MPL/LGPL/Apache triple license
- JsonBeans, Kryo, Minlog (Minlog-SLF4J), ReflectASM - New BSD license
http://code.google.com/p/jsonbeans/
http://code.google.com/p/kryo/
@ -115,34 +129,41 @@ Legal:
https://github.com/magro/kryo-serializers
Copyright 2010 Martin Grotzke
- Logback - EPL v1.0
http://logback.qos.ch/
Copyright (C) 1999-2012, QOS.ch. All rights reserved.
Copyright (C) 1999-2012, QOS.ch. All rights reserved.
- MathUtils, IntArray, IntMap - Apache 2.0 license
http://github.com/libgdx/libgdx/
Copyright (c) 2013
Mario Zechner <badlogicgames@gmail.com>
Nathan Sweet <nathan.sweet@gmail.com>
Nathan Sweet <nathan.sweet@gmail.com>
- MersenneTwisterFast, v20 - BSD license
http://www.cs.gmu.edu/~sean/research/mersenne/MersenneTwisterFast.java
Copyright (c) 2003 by Sean Luke.
Portions copyright (c) 1993 by Michael Lecuyer.
- Netty - Apache 2.0 license
http://netty.io
Copyright (c) 2013 The Netty Project
Copyright (c) 2013 The Netty Project
- Objenesis - Apache 2.0 license
http://http://code.google.com/p/objenesis/
Copyright (c) 2003-2009, Joe Walnes, Henri Tremblay, Leonardo Mesquita
- SLF4J - MIT license.
http://www.slf4j.org/
Copyright (c) 2004-2008 QOS.ch
@ -154,6 +175,7 @@ Legal:
http://udt.sourceforge.net/
Copyright 2001 - 2009, The Board of Trustees of the University of Illinois.
All rights reserved.

View File

@ -32,10 +32,10 @@ import dorkbox.network.connection.registration.local.RegistrationLocalHandlerCli
import dorkbox.network.connection.registration.remote.RegistrationRemoteHandlerClientTCP;
import dorkbox.network.connection.registration.remote.RegistrationRemoteHandlerClientUDP;
import dorkbox.network.connection.registration.remote.RegistrationRemoteHandlerClientUDT;
import dorkbox.network.util.InitializationException;
import dorkbox.network.util.NamedThreadFactory;
import dorkbox.network.util.SecurityException;
import dorkbox.network.util.SerializationManager;
import dorkbox.network.util.exceptions.InitializationException;
import dorkbox.network.util.exceptions.SecurityException;
import dorkbox.network.util.udt.UdtEndpointProxy;
/**

View File

@ -22,9 +22,9 @@ import dorkbox.network.connection.registration.local.RegistrationLocalHandlerSer
import dorkbox.network.connection.registration.remote.RegistrationRemoteHandlerServerTCP;
import dorkbox.network.connection.registration.remote.RegistrationRemoteHandlerServerUDP;
import dorkbox.network.connection.registration.remote.RegistrationRemoteHandlerServerUDT;
import dorkbox.network.util.InitializationException;
import dorkbox.network.util.NamedThreadFactory;
import dorkbox.network.util.SecurityException;
import dorkbox.network.util.exceptions.InitializationException;
import dorkbox.network.util.exceptions.SecurityException;
import dorkbox.network.util.udt.UdtEndpointProxy;

View File

@ -23,16 +23,16 @@ import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import dorkbox.network.ConnectionOptions;
import dorkbox.network.connection.registration.MetaChannel;
import dorkbox.network.rmi.RmiBridge;
import dorkbox.network.util.InitializationException;
import dorkbox.network.util.SecurityException;
import dorkbox.network.util.entropy.Entropy;
import dorkbox.network.util.entropy.SimpleEntropy;
import dorkbox.network.util.primativeCollections.IntMap;
import dorkbox.network.util.primativeCollections.IntMap.Entries;
import dorkbox.network.util.exceptions.InitializationException;
import dorkbox.network.util.exceptions.SecurityException;
import dorkbox.network.util.store.NullSettingsStore;
import dorkbox.network.util.store.SettingsStore;
import dorkbox.network.util.udt.UdtEndpointProxy;
import dorkbox.util.crypto.Crypto;
import dorkbox.util.primativeCollections.IntMap;
import dorkbox.util.primativeCollections.IntMap.Entries;
/** represents the base of a client/server end point */
public abstract class EndPoint {

View File

@ -3,8 +3,8 @@ package dorkbox.network.connection;
import org.slf4j.Logger;
import dorkbox.network.ConnectionOptions;
import dorkbox.network.util.InitializationException;
import dorkbox.network.util.SecurityException;
import dorkbox.network.util.exceptions.InitializationException;
import dorkbox.network.util.exceptions.SecurityException;
/**
* This serves the purpose of making sure that specific methods are not available to the end user.

View File

@ -1,8 +1,8 @@
package dorkbox.network.connection;
import dorkbox.network.ConnectionOptions;
import dorkbox.network.util.InitializationException;
import dorkbox.network.util.SecurityException;
import dorkbox.network.util.exceptions.InitializationException;
import dorkbox.network.util.exceptions.SecurityException;
/**
* This serves the purpose of making sure that specific methods are not available to the end user.

View File

@ -19,10 +19,10 @@ import dorkbox.network.connection.wrapper.ChannelWrapper;
import dorkbox.network.pipeline.KryoEncoder;
import dorkbox.network.pipeline.KryoEncoderCrypto;
import dorkbox.network.rmi.RmiBridge;
import dorkbox.network.util.InitializationException;
import dorkbox.network.util.KryoSerializationManager;
import dorkbox.network.util.SecurityException;
import dorkbox.network.util.SerializationManager;
import dorkbox.network.util.exceptions.InitializationException;
import dorkbox.network.util.exceptions.SecurityException;
import dorkbox.util.crypto.serialization.EccPrivateKeySerializer;
import dorkbox.util.crypto.serialization.EccPublicKeySerializer;
import dorkbox.util.crypto.serialization.IesParametersSerializer;

View File

@ -59,7 +59,7 @@ class PropertyStore extends SettingsStore {
* Simple, property based method to getting the private key of the server
*/
@Override
public synchronized ECPrivateKeyParameters getPrivateKey() throws dorkbox.network.util.SecurityException {
public synchronized ECPrivateKeyParameters getPrivateKey() throws dorkbox.network.util.exceptions.SecurityException {
checkAccess(EndPoint.class);
return this.props.serverPrivateKey;
@ -69,7 +69,7 @@ class PropertyStore extends SettingsStore {
* Simple, property based method for saving the private key of the server
*/
@Override
public synchronized void savePrivateKey(ECPrivateKeyParameters serverPrivateKey) throws dorkbox.network.util.SecurityException {
public synchronized void savePrivateKey(ECPrivateKeyParameters serverPrivateKey) throws dorkbox.network.util.exceptions.SecurityException {
checkAccess(EndPoint.class);
this.props.serverPrivateKey = serverPrivateKey;
@ -81,7 +81,7 @@ class PropertyStore extends SettingsStore {
* Simple, property based method to getting the public key of the server
*/
@Override
public synchronized ECPublicKeyParameters getPublicKey() throws dorkbox.network.util.SecurityException {
public synchronized ECPublicKeyParameters getPublicKey() throws dorkbox.network.util.exceptions.SecurityException {
checkAccess(EndPoint.class);
return this.props.serverPublicKey;
@ -91,7 +91,7 @@ class PropertyStore extends SettingsStore {
* Simple, property based method for saving the public key of the server
*/
@Override
public synchronized void savePublicKey(ECPublicKeyParameters serverPublicKey) throws dorkbox.network.util.SecurityException {
public synchronized void savePublicKey(ECPublicKeyParameters serverPublicKey) throws dorkbox.network.util.exceptions.SecurityException {
checkAccess(EndPoint.class);
this.props.serverPublicKey = serverPublicKey;
@ -122,7 +122,7 @@ class PropertyStore extends SettingsStore {
* Simple, property based method to getting a connected computer by host IP address
*/
@Override
public synchronized ECPublicKeyParameters getRegisteredServerKey(byte[] hostAddress) throws dorkbox.network.util.SecurityException {
public synchronized ECPublicKeyParameters getRegisteredServerKey(byte[] hostAddress) throws dorkbox.network.util.exceptions.SecurityException {
checkAccess(RegistrationWrapper.class);
return this.props.registeredServer.get(new ByteArrayWrapper(hostAddress));
@ -132,7 +132,7 @@ class PropertyStore extends SettingsStore {
* Saves a connected computer by host IP address and public key
*/
@Override
public synchronized void addRegisteredServerKey(byte[] hostAddress, ECPublicKeyParameters publicKey) throws dorkbox.network.util.SecurityException {
public synchronized void addRegisteredServerKey(byte[] hostAddress, ECPublicKeyParameters publicKey) throws dorkbox.network.util.exceptions.SecurityException {
checkAccess(RegistrationWrapper.class);
this.props.registeredServer.put(new ByteArrayWrapper(hostAddress), publicKey);
@ -143,7 +143,7 @@ class PropertyStore extends SettingsStore {
* Deletes a registered computer by host IP address
*/
@Override
public synchronized boolean removeRegisteredServerKey(byte[] hostAddress) throws dorkbox.network.util.SecurityException {
public synchronized boolean removeRegisteredServerKey(byte[] hostAddress) throws dorkbox.network.util.exceptions.SecurityException {
checkAccess(RegistrationWrapper.class);
ECPublicKeyParameters remove = this.props.registeredServer.remove(new ByteArrayWrapper(hostAddress));

View File

@ -16,9 +16,9 @@ import org.slf4j.Logger;
import dorkbox.network.connection.registration.MetaChannel;
import dorkbox.network.pipeline.KryoEncoder;
import dorkbox.network.pipeline.KryoEncoderCrypto;
import dorkbox.network.util.SecurityException;
import dorkbox.network.util.primativeCollections.IntMap;
import dorkbox.network.util.exceptions.SecurityException;
import dorkbox.util.crypto.Crypto;
import dorkbox.util.primativeCollections.IntMap;
/**
* Just wraps common/needed methods of the client/server endpoint by the registration stage/handshake.

View File

@ -6,7 +6,7 @@ import java.io.IOException;
import java.io.InputStream;
import dorkbox.network.connection.Connection;
import dorkbox.network.util.NetException;
import dorkbox.network.util.exceptions.NetException;
abstract public class InputStreamSender<C extends Connection> extends IdleSender<C,byte[]> {

View File

@ -5,8 +5,8 @@ import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import dorkbox.network.connection.RegistrationWrapper;
import dorkbox.network.util.primativeCollections.IntMap;
import dorkbox.network.util.primativeCollections.IntMap.Entries;
import dorkbox.util.primativeCollections.IntMap;
import dorkbox.util.primativeCollections.IntMap.Entries;
@Sharable
public abstract class RegistrationHandler extends ChannelInboundHandlerAdapter {

View File

@ -9,8 +9,8 @@ import dorkbox.network.connection.EndPoint;
import dorkbox.network.connection.RegistrationWrapper;
import dorkbox.network.connection.registration.MetaChannel;
import dorkbox.network.connection.registration.RegistrationHandler;
import dorkbox.network.util.primativeCollections.IntMap;
import dorkbox.network.util.primativeCollections.IntMap.Entries;
import dorkbox.util.primativeCollections.IntMap;
import dorkbox.util.primativeCollections.IntMap.Entries;
public abstract class RegistrationLocalHandler extends RegistrationHandler {

View File

@ -7,7 +7,7 @@ import dorkbox.network.connection.Connection;
import dorkbox.network.connection.RegistrationWrapper;
import dorkbox.network.connection.registration.MetaChannel;
import dorkbox.network.connection.registration.Registration;
import dorkbox.network.util.primativeCollections.IntMap;
import dorkbox.util.primativeCollections.IntMap;
public class RegistrationLocalHandlerClient extends RegistrationLocalHandler {

View File

@ -10,7 +10,7 @@ import org.slf4j.Logger;
import dorkbox.network.connection.Connection;
import dorkbox.network.connection.RegistrationWrapper;
import dorkbox.network.connection.registration.MetaChannel;
import dorkbox.network.util.primativeCollections.IntMap;
import dorkbox.util.primativeCollections.IntMap;
public class RegistrationLocalHandlerServer extends RegistrationLocalHandler {

View File

@ -26,8 +26,8 @@ import dorkbox.network.pipeline.KryoDecoderCrypto;
import dorkbox.network.pipeline.udp.KryoDecoderUdpCrypto;
import dorkbox.network.pipeline.udp.KryoEncoderUdpCrypto;
import dorkbox.network.util.SerializationManager;
import dorkbox.network.util.primativeCollections.IntMap;
import dorkbox.network.util.primativeCollections.IntMap.Entries;
import dorkbox.util.primativeCollections.IntMap;
import dorkbox.util.primativeCollections.IntMap.Entries;
public abstract class RegistrationRemoteHandler extends RegistrationHandler {
private static final String IDLE_HANDLER_FULL = "idleHandlerFull";

View File

@ -25,12 +25,12 @@ import com.esotericsoftware.kryo.io.Output;
import dorkbox.network.connection.RegistrationWrapper;
import dorkbox.network.connection.registration.MetaChannel;
import dorkbox.network.connection.registration.Registration;
import dorkbox.network.util.SecurityException;
import dorkbox.network.util.SerializationManager;
import dorkbox.network.util.primativeCollections.IntMap;
import dorkbox.network.util.exceptions.SecurityException;
import dorkbox.util.bytes.OptimizeUtils;
import dorkbox.util.crypto.Crypto;
import dorkbox.util.crypto.serialization.EccPublicKeySerializer;
import dorkbox.util.primativeCollections.IntMap;
public class RegistrationRemoteHandlerClientTCP extends RegistrationRemoteHandlerClient {

View File

@ -16,10 +16,10 @@ import dorkbox.network.connection.registration.Registration;
import dorkbox.network.pipeline.udp.KryoDecoderUdp;
import dorkbox.network.pipeline.udp.KryoEncoderUdp;
import dorkbox.network.util.SerializationManager;
import dorkbox.network.util.primativeCollections.IntMap;
import dorkbox.network.util.primativeCollections.IntMap.Entries;
import dorkbox.util.bytes.OptimizeUtils;
import dorkbox.util.crypto.Crypto;
import dorkbox.util.primativeCollections.IntMap;
import dorkbox.util.primativeCollections.IntMap.Entries;
public class RegistrationRemoteHandlerClientUDP extends RegistrationRemoteHandlerClient {

View File

@ -13,10 +13,10 @@ import dorkbox.network.connection.RegistrationWrapper;
import dorkbox.network.connection.registration.MetaChannel;
import dorkbox.network.connection.registration.Registration;
import dorkbox.network.util.SerializationManager;
import dorkbox.network.util.primativeCollections.IntMap;
import dorkbox.network.util.primativeCollections.IntMap.Entries;
import dorkbox.util.bytes.OptimizeUtils;
import dorkbox.util.crypto.Crypto;
import dorkbox.util.primativeCollections.IntMap;
import dorkbox.util.primativeCollections.IntMap.Entries;
public class RegistrationRemoteHandlerClientUDT extends RegistrationRemoteHandlerClient {

View File

@ -26,12 +26,12 @@ import com.esotericsoftware.kryo.io.Output;
import dorkbox.network.connection.RegistrationWrapper;
import dorkbox.network.connection.registration.MetaChannel;
import dorkbox.network.connection.registration.Registration;
import dorkbox.network.util.RandomConnectionIdGenerator;
import dorkbox.network.util.SerializationManager;
import dorkbox.network.util.primativeCollections.IntMap;
import dorkbox.util.MathUtils;
import dorkbox.util.bytes.OptimizeUtils;
import dorkbox.util.crypto.Crypto;
import dorkbox.util.crypto.serialization.EccPublicKeySerializer;
import dorkbox.util.primativeCollections.IntMap;
public class RegistrationRemoteHandlerServerTCP extends RegistrationRemoteHandlerServer {
@ -160,13 +160,13 @@ public class RegistrationRemoteHandlerServerTCP extends RegistrationRemoteHandle
}
Integer connectionID = RandomConnectionIdGenerator.getRandom();
Integer connectionID = MathUtils.randomInt();
// if I'm unlucky, keep from confusing connections!
try {
IntMap<MetaChannel> channelMap = this.registrationWrapper.getAndLockChannelMap();
while (channelMap.containsKey(connectionID)) {
connectionID = RandomConnectionIdGenerator.getRandom();
connectionID = MathUtils.randomInt();
}
metaChannel.connectionID = connectionID;

View File

@ -22,12 +22,12 @@ import dorkbox.network.connection.RegistrationWrapper;
import dorkbox.network.connection.registration.MetaChannel;
import dorkbox.network.connection.registration.Registration;
import dorkbox.network.connection.wrapper.UdpWrapper;
import dorkbox.network.util.NetException;
import dorkbox.network.util.SerializationManager;
import dorkbox.network.util.primativeCollections.IntMap;
import dorkbox.network.util.primativeCollections.IntMap.Entries;
import dorkbox.network.util.exceptions.NetException;
import dorkbox.util.bytes.OptimizeUtils;
import dorkbox.util.crypto.Crypto;
import dorkbox.util.primativeCollections.IntMap;
import dorkbox.util.primativeCollections.IntMap.Entries;
@Sharable
public class RegistrationRemoteHandlerServerUDP extends MessageToMessageCodec<DatagramPacket, UdpWrapper> {

View File

@ -11,10 +11,10 @@ import dorkbox.network.connection.RegistrationWrapper;
import dorkbox.network.connection.registration.MetaChannel;
import dorkbox.network.connection.registration.Registration;
import dorkbox.network.util.SerializationManager;
import dorkbox.network.util.primativeCollections.IntMap;
import dorkbox.network.util.primativeCollections.IntMap.Entries;
import dorkbox.util.bytes.OptimizeUtils;
import dorkbox.util.crypto.Crypto;
import dorkbox.util.primativeCollections.IntMap;
import dorkbox.util.primativeCollections.IntMap.Entries;
public class RegistrationRemoteHandlerServerUDT extends RegistrationRemoteHandlerServer {

View File

@ -5,7 +5,7 @@ import io.netty.channel.Channel;
import java.net.InetSocketAddress;
import dorkbox.network.connection.UdpServer;
import dorkbox.network.util.NetException;
import dorkbox.network.util.exceptions.NetException;
public class ChannelNetworkUdp extends ChannelNetwork {

View File

@ -1,9 +1,8 @@
package dorkbox.network.pipeline;
import dorkbox.network.connection.Connection;
import dorkbox.network.util.NetException;
import dorkbox.network.util.SerializationManager;
import dorkbox.network.util.exceptions.NetException;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;

View File

@ -7,8 +7,8 @@ import io.netty.handler.codec.MessageToByteEncoder;
import com.esotericsoftware.kryo.KryoException;
import dorkbox.network.util.NetException;
import dorkbox.network.util.SerializationManager;
import dorkbox.network.util.exceptions.NetException;
import dorkbox.util.bytes.OptimizeUtilsByteBuf;
@Sharable

View File

@ -1,9 +1,8 @@
package dorkbox.network.pipeline;
import dorkbox.network.connection.Connection;
import dorkbox.network.util.NetException;
import dorkbox.network.util.SerializationManager;
import dorkbox.network.util.exceptions.NetException;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandler.Sharable;

View File

@ -8,8 +8,8 @@ import io.netty.handler.codec.MessageToMessageDecoder;
import java.util.List;
import dorkbox.network.util.NetException;
import dorkbox.network.util.SerializationManager;
import dorkbox.network.util.exceptions.NetException;
@Sharable
public class KryoDecoderUdp extends MessageToMessageDecoder<DatagramPacket> {

View File

@ -10,8 +10,8 @@ import io.netty.handler.codec.MessageToMessageDecoder;
import java.util.List;
import dorkbox.network.connection.Connection;
import dorkbox.network.util.NetException;
import dorkbox.network.util.SerializationManager;
import dorkbox.network.util.exceptions.NetException;
@Sharable
public class KryoDecoderUdpCrypto extends MessageToMessageDecoder<DatagramPacket> {

View File

@ -13,8 +13,8 @@ import java.util.List;
import com.esotericsoftware.kryo.KryoException;
import dorkbox.network.connection.EndPoint;
import dorkbox.network.util.NetException;
import dorkbox.network.util.SerializationManager;
import dorkbox.network.util.exceptions.NetException;
@Sharable
// UDP uses messages --- NOT bytebuf!

View File

@ -1,9 +1,8 @@
package dorkbox.network.pipeline.udp;
import dorkbox.network.connection.Connection;
import dorkbox.network.util.NetException;
import dorkbox.network.util.SerializationManager;
import dorkbox.network.util.exceptions.NetException;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandler.Sharable;

View File

@ -30,8 +30,8 @@ import com.esotericsoftware.kryo.util.IntMap;
import dorkbox.network.connection.Connection;
import dorkbox.network.connection.EndPoint;
import dorkbox.network.connection.Listener;
import dorkbox.network.util.ObjectIntMap;
import dorkbox.network.util.SerializationManager;
import dorkbox.util.primativeCollections.ObjectIntMap;
/**
* Allows methods on objects to be invoked remotely over TCP. Objects are

View File

@ -3,7 +3,7 @@ package dorkbox.network.util;
import java.util.Arrays;
/**
* Necessary to provide equals and hashcode for byte arrays (if they are to be used in a map/set/etc)
* Necessary to provide equals and hashcode for byte arrays (if they are to be used as keys in a map/set/etc)
*/
public final class ByteArrayWrapper {
private final byte[] data;

View File

@ -28,6 +28,8 @@ import dorkbox.network.pipeline.ByteBufInput;
import dorkbox.network.pipeline.ByteBufOutput;
import dorkbox.network.rmi.RmiRegisterClassesCallback;
import dorkbox.network.rmi.SerializerRegistration;
import dorkbox.network.util.exceptions.NetException;
import dorkbox.network.util.serializers.UnmodifiableCollectionsSerializer;
import dorkbox.util.crypto.Crypto;
import dorkbox.util.crypto.bouncycastle.GCMBlockCipher_ByteBuf;

View File

@ -1,559 +0,0 @@
package dorkbox.network.util;
import java.util.Random;
import com.esotericsoftware.kryo.util.ObjectMap;
/** An unordered map where the values are ints. This implementation is a cuckoo hash map using 3 hashes, random walking, and a
* small stash for problematic keys. Null keys are not allowed. No allocation is done except when growing the table size. <br>
* <br>
* This map performs very fast get, containsKey, and remove (typically O(1), worst case O(log(n))). Put may be a bit slower,
* depending on hash collisions. Load factors greater than 0.91 greatly increase the chances the map will have to rehash to the
* next higher POT size.
* @author Nathan Sweet */
public class ObjectIntMap<K> {
@SuppressWarnings("unused")
private static final int PRIME1 = 0xbe1f14b1;
private static final int PRIME2 = 0xb4b82e39;
private static final int PRIME3 = 0xced1c241;
static Random random = new Random();
public int size;
K[] keyTable;
int[] valueTable;
int capacity, stashSize;
private float loadFactor;
private int hashShift, mask, threshold;
private int stashCapacity;
private int pushIterations;
/** Creates a new map with an initial capacity of 32 and a load factor of 0.8. This map will hold 25 items before growing the
* backing table. */
public ObjectIntMap () {
this(32, 0.8f);
}
/** Creates a new map with a load factor of 0.8. This map will hold initialCapacity * 0.8 items before growing the backing
* table. */
public ObjectIntMap (int initialCapacity) {
this(initialCapacity, 0.8f);
}
/** Creates a new map with the specified initial capacity and load factor. This map will hold initialCapacity * loadFactor items
* before growing the backing table. */
@SuppressWarnings("unchecked")
public ObjectIntMap (int initialCapacity, float loadFactor) {
if (initialCapacity < 0) {
throw new IllegalArgumentException("initialCapacity must be >= 0: " + initialCapacity);
}
if (initialCapacity > 1 << 30) {
throw new IllegalArgumentException("initialCapacity is too large: " + initialCapacity);
}
capacity = ObjectMap.nextPowerOfTwo(initialCapacity);
if (loadFactor <= 0) {
throw new IllegalArgumentException("loadFactor must be > 0: " + loadFactor);
}
this.loadFactor = loadFactor;
threshold = (int)(capacity * loadFactor);
mask = capacity - 1;
hashShift = 31 - Integer.numberOfTrailingZeros(capacity);
stashCapacity = Math.max(3, (int)Math.ceil(Math.log(capacity)) * 2);
pushIterations = Math.max(Math.min(capacity, 8), (int)Math.sqrt(capacity) / 8);
keyTable = (K[])new Object[capacity + stashCapacity];
valueTable = new int[keyTable.length];
}
/** Creates a new map identical to the specified map. */
public ObjectIntMap (ObjectIntMap<? extends K> map) {
this(map.capacity, map.loadFactor);
stashSize = map.stashSize;
System.arraycopy(map.keyTable, 0, keyTable, 0, map.keyTable.length);
System.arraycopy(map.valueTable, 0, valueTable, 0, map.valueTable.length);
size = map.size;
}
public void put (K key, int value) {
if (key == null) {
throw new IllegalArgumentException("key cannot be null.");
}
K[] keyTable = this.keyTable;
// Check for existing keys.
int hashCode = key.hashCode();
int index1 = hashCode & mask;
K key1 = keyTable[index1];
if (key.equals(key1)) {
valueTable[index1] = value;
return;
}
int index2 = hash2(hashCode);
K key2 = keyTable[index2];
if (key.equals(key2)) {
valueTable[index2] = value;
return;
}
int index3 = hash3(hashCode);
K key3 = keyTable[index3];
if (key.equals(key3)) {
valueTable[index3] = value;
return;
}
// Update key in the stash.
for (int i = capacity, n = i + stashSize; i < n; i++) {
if (key.equals(keyTable[i])) {
valueTable[i] = value;
return;
}
}
// Check for empty buckets.
if (key1 == null) {
keyTable[index1] = key;
valueTable[index1] = value;
if (size++ >= threshold) {
resize(capacity << 1);
}
return;
}
if (key2 == null) {
keyTable[index2] = key;
valueTable[index2] = value;
if (size++ >= threshold) {
resize(capacity << 1);
}
return;
}
if (key3 == null) {
keyTable[index3] = key;
valueTable[index3] = value;
if (size++ >= threshold) {
resize(capacity << 1);
}
return;
}
push(key, value, index1, key1, index2, key2, index3, key3);
}
/** Skips checks for existing keys. */
private void putResize (K key, int value) {
// Check for empty buckets.
int hashCode = key.hashCode();
int index1 = hashCode & mask;
K key1 = keyTable[index1];
if (key1 == null) {
keyTable[index1] = key;
valueTable[index1] = value;
if (size++ >= threshold) {
resize(capacity << 1);
}
return;
}
int index2 = hash2(hashCode);
K key2 = keyTable[index2];
if (key2 == null) {
keyTable[index2] = key;
valueTable[index2] = value;
if (size++ >= threshold) {
resize(capacity << 1);
}
return;
}
int index3 = hash3(hashCode);
K key3 = keyTable[index3];
if (key3 == null) {
keyTable[index3] = key;
valueTable[index3] = value;
if (size++ >= threshold) {
resize(capacity << 1);
}
return;
}
push(key, value, index1, key1, index2, key2, index3, key3);
}
private void push (K insertKey, int insertValue, int index1, K key1, int index2, K key2, int index3, K key3) {
K[] keyTable = this.keyTable;
int[] valueTable = this.valueTable;
int mask = this.mask;
// Push keys until an empty bucket is found.
K evictedKey;
int evictedValue;
int i = 0, pushIterations = this.pushIterations;
do {
// Replace the key and value for one of the hashes.
switch (random.nextInt(3)) {
case 0:
evictedKey = key1;
evictedValue = valueTable[index1];
keyTable[index1] = insertKey;
valueTable[index1] = insertValue;
break;
case 1:
evictedKey = key2;
evictedValue = valueTable[index2];
keyTable[index2] = insertKey;
valueTable[index2] = insertValue;
break;
default:
evictedKey = key3;
evictedValue = valueTable[index3];
keyTable[index3] = insertKey;
valueTable[index3] = insertValue;
break;
}
// If the evicted key hashes to an empty bucket, put it there and stop.
int hashCode = evictedKey.hashCode();
index1 = hashCode & mask;
key1 = keyTable[index1];
if (key1 == null) {
keyTable[index1] = evictedKey;
valueTable[index1] = evictedValue;
if (size++ >= threshold) {
resize(capacity << 1);
}
return;
}
index2 = hash2(hashCode);
key2 = keyTable[index2];
if (key2 == null) {
keyTable[index2] = evictedKey;
valueTable[index2] = evictedValue;
if (size++ >= threshold) {
resize(capacity << 1);
}
return;
}
index3 = hash3(hashCode);
key3 = keyTable[index3];
if (key3 == null) {
keyTable[index3] = evictedKey;
valueTable[index3] = evictedValue;
if (size++ >= threshold) {
resize(capacity << 1);
}
return;
}
if (++i == pushIterations) {
break;
}
insertKey = evictedKey;
insertValue = evictedValue;
} while (true);
putStash(evictedKey, evictedValue);
}
private void putStash (K key, int value) {
if (stashSize == stashCapacity) {
// Too many pushes occurred and the stash is full, increase the table size.
resize(capacity << 1);
put(key, value);
return;
}
// Store key in the stash.
int index = capacity + stashSize;
keyTable[index] = key;
valueTable[index] = value;
stashSize++;
size++;
}
/** @param defaultValue Returned if the key was not associated with a value. */
public int get (K key, int defaultValue) {
int hashCode = key.hashCode();
int index = hashCode & mask;
if (!key.equals(keyTable[index])) {
index = hash2(hashCode);
if (!key.equals(keyTable[index])) {
index = hash3(hashCode);
if (!key.equals(keyTable[index])) {
return getStash(key, defaultValue);
}
}
}
return valueTable[index];
}
private int getStash (K key, int defaultValue) {
K[] keyTable = this.keyTable;
for (int i = capacity, n = i + stashSize; i < n; i++) {
if (key.equals(keyTable[i])) {
return valueTable[i];
}
}
return defaultValue;
}
/** Returns the key's current value and increments the stored value. If the key is not in the map, defaultValue + increment is
* put into the map. */
public int getAndIncrement (K key, int defaultValue, int increment) {
int hashCode = key.hashCode();
int index = hashCode & mask;
if (!key.equals(keyTable[index])) {
index = hash2(hashCode);
if (!key.equals(keyTable[index])) {
index = hash3(hashCode);
if (!key.equals(keyTable[index])) {
return getAndIncrementStash(key, defaultValue, increment);
}
}
}
int value = valueTable[index];
valueTable[index] = value + increment;
return value;
}
private int getAndIncrementStash (K key, int defaultValue, int increment) {
K[] keyTable = this.keyTable;
for (int i = capacity, n = i + stashSize; i < n; i++) {
if (key.equals(keyTable[i])) {
int value = valueTable[i];
valueTable[i] = value + increment;
return value;
}
}
put(key, defaultValue + increment);
return defaultValue;
}
public int remove (K key, int defaultValue) {
int hashCode = key.hashCode();
int index = hashCode & mask;
if (key.equals(keyTable[index])) {
keyTable[index] = null;
int oldValue = valueTable[index];
size--;
return oldValue;
}
index = hash2(hashCode);
if (key.equals(keyTable[index])) {
keyTable[index] = null;
int oldValue = valueTable[index];
size--;
return oldValue;
}
index = hash3(hashCode);
if (key.equals(keyTable[index])) {
keyTable[index] = null;
int oldValue = valueTable[index];
size--;
return oldValue;
}
return removeStash(key, defaultValue);
}
int removeStash (K key, int defaultValue) {
K[] keyTable = this.keyTable;
for (int i = capacity, n = i + stashSize; i < n; i++) {
if (key.equals(keyTable[i])) {
int oldValue = valueTable[i];
removeStashIndex(i);
size--;
return oldValue;
}
}
return defaultValue;
}
void removeStashIndex (int index) {
// If the removed location was not last, move the last tuple to the removed location.
stashSize--;
int lastIndex = capacity + stashSize;
if (index < lastIndex) {
keyTable[index] = keyTable[lastIndex];
valueTable[index] = valueTable[lastIndex];
}
}
/** Reduces the size of the backing arrays to be the specified capacity or less. If the capacity is already less, nothing is
* done. If the map contains more items than the specified capacity, the next highest power of two capacity is used instead. */
public void shrink (int maximumCapacity) {
if (maximumCapacity < 0) {
throw new IllegalArgumentException("maximumCapacity must be >= 0: " + maximumCapacity);
}
if (size > maximumCapacity) {
maximumCapacity = size;
}
if (capacity <= maximumCapacity) {
return;
}
maximumCapacity = ObjectMap.nextPowerOfTwo(maximumCapacity);
resize(maximumCapacity);
}
/** Clears the map and reduces the size of the backing arrays to be the specified capacity if they are larger. */
public void clear (int maximumCapacity) {
if (capacity <= maximumCapacity) {
clear();
return;
}
size = 0;
resize(maximumCapacity);
}
public void clear () {
K[] keyTable = this.keyTable;
for (int i = capacity + stashSize; i-- > 0;) {
keyTable[i] = null;
}
size = 0;
stashSize = 0;
}
/** Returns true if the specified value is in the map. Note this traverses the entire map and compares every value, which may be
* an expensive operation. */
public boolean containsValue (int value) {
int[] valueTable = this.valueTable;
for (int i = capacity + stashSize; i-- > 0;) {
if (valueTable[i] == value) {
return true;
}
}
return false;
}
public boolean containsKey (K key) {
int hashCode = key.hashCode();
int index = hashCode & mask;
if (!key.equals(keyTable[index])) {
index = hash2(hashCode);
if (!key.equals(keyTable[index])) {
index = hash3(hashCode);
if (!key.equals(keyTable[index])) {
return containsKeyStash(key);
}
}
}
return true;
}
private boolean containsKeyStash (K key) {
K[] keyTable = this.keyTable;
for (int i = capacity, n = i + stashSize; i < n; i++) {
if (key.equals(keyTable[i])) {
return true;
}
}
return false;
}
/** Returns the key for the specified value, or null if it is not in the map. Note this traverses the entire map and compares
* every value, which may be an expensive operation. */
public K findKey (int value) {
int[] valueTable = this.valueTable;
for (int i = capacity + stashSize; i-- > 0;) {
if (valueTable[i] == value) {
return keyTable[i];
}
}
return null;
}
/** Increases the size of the backing array to acommodate the specified number of additional items. Useful before adding many
* items to avoid multiple backing array resizes. */
public void ensureCapacity (int additionalCapacity) {
int sizeNeeded = size + additionalCapacity;
if (sizeNeeded >= threshold) {
resize(ObjectMap.nextPowerOfTwo((int)(sizeNeeded / loadFactor)));
}
}
@SuppressWarnings("unchecked")
private void resize (int newSize) {
int oldEndIndex = capacity + stashSize;
capacity = newSize;
threshold = (int)(newSize * loadFactor);
mask = newSize - 1;
hashShift = 31 - Integer.numberOfTrailingZeros(newSize);
stashCapacity = Math.max(3, (int)Math.ceil(Math.log(newSize)) * 2);
pushIterations = Math.max(Math.min(newSize, 8), (int)Math.sqrt(newSize) / 8);
K[] oldKeyTable = keyTable;
int[] oldValueTable = valueTable;
keyTable = (K[])new Object[newSize + stashCapacity];
valueTable = new int[newSize + stashCapacity];
int oldSize = size;
size = 0;
stashSize = 0;
if (oldSize > 0) {
for (int i = 0; i < oldEndIndex; i++) {
K key = oldKeyTable[i];
if (key != null) {
putResize(key, oldValueTable[i]);
}
}
}
}
private int hash2 (int h) {
h *= PRIME2;
return (h ^ h >>> hashShift) & mask;
}
private int hash3 (int h) {
h *= PRIME3;
return (h ^ h >>> hashShift) & mask;
}
@Override
public String toString () {
if (size == 0) {
return "{}";
}
StringBuilder buffer = new StringBuilder(32);
buffer.append('{');
K[] keyTable = this.keyTable;
int[] valueTable = this.valueTable;
int i = keyTable.length;
while (i-- > 0) {
K key = keyTable[i];
if (key == null) {
continue;
}
buffer.append(key);
buffer.append('=');
buffer.append(valueTable[i]);
break;
}
while (i-- > 0) {
K key = keyTable[i];
if (key == null) {
continue;
}
buffer.append(", ");
buffer.append(key);
buffer.append('=');
buffer.append(valueTable[i]);
}
buffer.append('}');
return buffer.toString();
}
}

View File

@ -1,20 +0,0 @@
package dorkbox.network.util;
import java.security.SecureRandom;
public class RandomConnectionIdGenerator {
private static final SecureRandom secureRandom = new SecureRandom();
private static final ThreadLocal<Integer> uniqueNum =
new ThreadLocal<Integer>() {
@Override
protected Integer initialValue() {
return secureRandom.nextInt();
}
};
public static Integer getRandom() {
return uniqueNum.get();
}
}

View File

@ -6,7 +6,7 @@ import java.lang.reflect.Method;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import dorkbox.network.util.InitializationException;
import dorkbox.network.util.exceptions.InitializationException;
public class Entropy {

View File

@ -1,4 +1,4 @@
package dorkbox.network.util;
package dorkbox.network.util.exceptions;
public class InitializationException extends Exception {

View File

@ -1,5 +1,5 @@
package dorkbox.network.util;
package dorkbox.network.util.exceptions;
public class NetException extends RuntimeException {
private static final long serialVersionUID = 2963139576811306988L;

View File

@ -1,4 +1,4 @@
package dorkbox.network.util;
package dorkbox.network.util.exceptions;
public class SecurityException extends Exception {

View File

@ -1,381 +0,0 @@
/*******************************************************************************
* Copyright 2011 See AUTHORS file.
*
* 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.
*/
// from libGDX
package dorkbox.network.util.primativeCollections;
import java.util.Arrays;
/** A resizable, ordered or unordered int array. Avoids the boxing that occurs with ArrayList<Integer>. If unordered, this class
* avoids a memory copy when removing elements (the last element is moved to the removed element's position).
* @author Nathan Sweet */
public class IntArray {
public int[] items;
public int size;
public boolean ordered;
/** Creates an ordered array with a capacity of 16. */
public IntArray () {
this(true, 16);
}
/** Creates an ordered array with the specified capacity. */
public IntArray (int capacity) {
this(true, capacity);
}
/** @param ordered If false, methods that remove elements may change the order of other elements in the array, which avoids a
* memory copy.
* @param capacity Any elements added beyond this will cause the backing array to be grown. */
public IntArray (boolean ordered, int capacity) {
this.ordered = ordered;
items = new int[capacity];
}
/** Creates a new array containing the elements in the specific array. The new array will be ordered if the specific array is
* ordered. The capacity is set to the number of elements, so any subsequent elements added will cause the backing array to be
* grown. */
public IntArray (IntArray array) {
this.ordered = array.ordered;
size = array.size;
items = new int[size];
System.arraycopy(array.items, 0, items, 0, size);
}
/** Creates a new ordered array containing the elements in the specified array. The capacity is set to the number of elements,
* so any subsequent elements added will cause the backing array to be grown. */
public IntArray (int[] array) {
this(true, array, 0, array.length);
}
/** Creates a new array containing the elements in the specified array. The capacity is set to the number of elements, so any
* subsequent elements added will cause the backing array to be grown.
* @param ordered If false, methods that remove elements may change the order of other elements in the array, which avoids a
* memory copy. */
public IntArray (boolean ordered, int[] array, int startIndex, int count) {
this(ordered, array.length);
size = count;
System.arraycopy(array, startIndex, items, 0, count);
}
public void add (int value) {
int[] items = this.items;
if (size == items.length) {
items = resize(Math.max(8, (int)(size * 1.75f)));
}
items[size++] = value;
}
public void addAll (IntArray array) {
addAll(array, 0, array.size);
}
public void addAll (IntArray array, int offset, int length) {
if (offset + length > array.size) {
throw new IllegalArgumentException("offset + length must be <= size: " + offset + " + " + length + " <= " + array.size);
}
addAll(array.items, offset, length);
}
public void addAll (int[] array) {
addAll(array, 0, array.length);
}
public void addAll (int[] array, int offset, int length) {
int[] items = this.items;
int sizeNeeded = size + length;
if (sizeNeeded >= items.length) {
items = resize(Math.max(8, (int)(sizeNeeded * 1.75f)));
}
System.arraycopy(array, offset, items, size, length);
size += length;
}
public int get (int index) {
if (index >= size) {
throw new IndexOutOfBoundsException(String.valueOf(index));
}
return items[index];
}
public void set (int index, int value) {
if (index >= size) {
throw new IndexOutOfBoundsException(String.valueOf(index));
}
items[index] = value;
}
public void insert (int index, int value) {
if (index > size) {
throw new IndexOutOfBoundsException(String.valueOf(index));
}
int[] items = this.items;
if (size == items.length) {
items = resize(Math.max(8, (int)(size * 1.75f)));
}
if (ordered) {
System.arraycopy(items, index, items, index + 1, size - index);
} else {
items[size] = items[index];
}
size++;
items[index] = value;
}
public void swap (int first, int second) {
if (first >= size) {
throw new IndexOutOfBoundsException(String.valueOf(first));
}
if (second >= size) {
throw new IndexOutOfBoundsException(String.valueOf(second));
}
int[] items = this.items;
int firstValue = items[first];
items[first] = items[second];
items[second] = firstValue;
}
public boolean contains (int value) {
int i = size - 1;
int[] items = this.items;
while (i >= 0) {
if (items[i--] == value) {
return true;
}
}
return false;
}
public int indexOf (int value) {
int[] items = this.items;
for (int i = 0, n = size; i < n; i++) {
if (items[i] == value) {
return i;
}
}
return -1;
}
public int lastIndexOf (int value) {
int[] items = this.items;
for (int i = size - 1; i >= 0; i--) {
if (items[i] == value) {
return i;
}
}
return -1;
}
public boolean removeValue (int value) {
int[] items = this.items;
for (int i = 0, n = size; i < n; i++) {
if (items[i] == value) {
removeIndex(i);
return true;
}
}
return false;
}
/** Removes and returns the item at the specified index. */
public int removeIndex (int index) {
if (index >= size) {
throw new IndexOutOfBoundsException(String.valueOf(index));
}
int[] items = this.items;
int value = items[index];
size--;
if (ordered) {
System.arraycopy(items, index + 1, items, index, size - index);
} else {
items[index] = items[size];
}
return value;
}
/** Removes from this array all of elements contained in the specified array.
* @return true if this array was modified. */
public boolean removeAll (IntArray array) {
int size = this.size;
int startSize = size;
int[] items = this.items;
for (int i = 0, n = array.size; i < n; i++) {
int item = array.get(i);
for (int ii = 0; ii < size; ii++) {
if (item == items[ii]) {
removeIndex(ii);
size--;
break;
}
}
}
return size != startSize;
}
/** Removes and returns the last item. */
public int pop () {
return items[--size];
}
/** Returns the last item. */
public int peek () {
return items[size - 1];
}
/** Returns the first item. */
public int first () {
if (size == 0) {
throw new IllegalStateException("Array is empty.");
}
return items[0];
}
public void clear () {
size = 0;
}
/** Reduces the size of the backing array to the size of the actual items. This is useful to release memory when many items have
* been removed, or if it is known that more items will not be added. */
public void shrink () {
resize(size);
}
/** Increases the size of the backing array to acommodate the specified number of additional items. Useful before adding many
* items to avoid multiple backing array resizes.
* @return {@link #items} */
public int[] ensureCapacity (int additionalCapacity) {
int sizeNeeded = size + additionalCapacity;
if (sizeNeeded >= items.length) {
resize(Math.max(8, sizeNeeded));
}
return items;
}
protected int[] resize (int newSize) {
int[] newItems = new int[newSize];
int[] items = this.items;
System.arraycopy(items, 0, newItems, 0, Math.min(size, newItems.length));
this.items = newItems;
return newItems;
}
public void sort () {
Arrays.sort(items, 0, size);
}
public void reverse () {
for (int i = 0, lastIndex = size - 1, n = size / 2; i < n; i++) {
int ii = lastIndex - i;
int temp = items[i];
items[i] = items[ii];
items[ii] = temp;
}
}
public void shuffle () {
for (int i = size - 1; i >= 0; i--) {
int ii = MathUtils.random(i);
int temp = items[i];
items[i] = items[ii];
items[ii] = temp;
}
}
/** Reduces the size of the array to the specified size. If the array is already smaller than the specified size, no action is
* taken. */
public void truncate (int newSize) {
if (size > newSize) {
size = newSize;
}
}
/** Returns a random item from the array, or zero if the array is empty. */
public int random () {
if (size == 0) {
return 0;
}
return items[MathUtils.random(0, size - 1)];
}
public int[] toArray () {
int[] array = new int[size];
System.arraycopy(items, 0, array, 0, size);
return array;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + Arrays.hashCode(this.items);
result = prime * result + (this.ordered ? 1231 : 1237);
result = prime * result + this.size;
return result;
}
@Override
public boolean equals (Object object) {
if (object == this) {
return true;
}
if (!(object instanceof IntArray)) {
return false;
}
IntArray array = (IntArray)object;
int n = size;
if (n != array.size) {
return false;
}
for (int i = 0; i < n; i++) {
if (items[i] != array.items[i]) {
return false;
}
}
return true;
}
@Override
public String toString () {
if (size == 0) {
return "[]";
}
int[] items = this.items;
StringBuilder buffer = new StringBuilder(32);
buffer.append('[');
buffer.append(items[0]);
for (int i = 1; i < size; i++) {
buffer.append(", ");
buffer.append(items[i]);
}
buffer.append(']');
return buffer.toString();
}
public String toString (String separator) {
if (size == 0) {
return "";
}
int[] items = this.items;
StringBuilder buffer = new StringBuilder(32);
buffer.append(items[0]);
for (int i = 1; i < size; i++) {
buffer.append(separator);
buffer.append(items[i]);
}
return buffer.toString();
}
}

View File

@ -1,867 +0,0 @@
/*******************************************************************************
* Copyright 2011 See AUTHORS file.
*
* 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.
*/
// slightly tweaked from libGDX
package dorkbox.network.util.primativeCollections;
import java.util.Iterator;
import java.util.NoSuchElementException;
/** An unordered map that uses int keys. This implementation is a cuckoo hash map using 3 hashes, random walking, and a small stash
* for problematic keys. Null values are allowed. No allocation is done except when growing the table size. <br>
* <br>
* This map performs very fast get, containsKey, and remove (typically O(1), worst case O(log(n))). Put may be a bit slower,
* depending on hash collisions. Load factors greater than 0.91 greatly increase the chances the map will have to rehash to the
* next higher POT size.
* @author Nathan Sweet */
@SuppressWarnings({"rawtypes", "unchecked"})
public class IntMap<V> {
@SuppressWarnings("unused")
private static final int PRIME1 = 0xbe1f14b1;
private static final int PRIME2 = 0xb4b82e39;
private static final int PRIME3 = 0xced1c241;
private static final int EMPTY = 0;
public int size;
int[] keyTable;
V[] valueTable;
int capacity, stashSize;
V zeroValue;
boolean hasZeroValue;
private float loadFactor;
private int hashShift, mask, threshold;
private int stashCapacity;
private int pushIterations;
private Entries entries1, entries2;
private Values values1, values2;
private Keys keys1, keys2;
/** Creates a new map with an initial capacity of 32 and a load factor of 0.8. This map will hold 25 items before growing the
* backing table. */
public IntMap () {
this(32, 0.8f);
}
/** Creates a new map with a load factor of 0.8. This map will hold initialCapacity * 0.8 items before growing the backing
* table. */
public IntMap (int initialCapacity) {
this(initialCapacity, 0.8f);
}
/** Creates a new map with the specified initial capacity and load factor. This map will hold initialCapacity * loadFactor items
* before growing the backing table. */
public IntMap (int initialCapacity, float loadFactor) {
if (initialCapacity < 0) {
throw new IllegalArgumentException("initialCapacity must be >= 0: " + initialCapacity);
}
if (capacity > 1 << 30) {
throw new IllegalArgumentException("initialCapacity is too large: " + initialCapacity);
}
capacity = MathUtils.nextPowerOfTwo(initialCapacity);
if (loadFactor <= 0) {
throw new IllegalArgumentException("loadFactor must be > 0: " + loadFactor);
}
this.loadFactor = loadFactor;
threshold = (int)(capacity * loadFactor);
mask = capacity - 1;
hashShift = 31 - Integer.numberOfTrailingZeros(capacity);
stashCapacity = Math.max(3, (int)Math.ceil(Math.log(capacity)) * 2);
pushIterations = Math.max(Math.min(capacity, 8), (int)Math.sqrt(capacity) / 8);
keyTable = new int[capacity + stashCapacity];
valueTable = (V[])new Object[keyTable.length];
}
public V put (int key, V value) {
if (key == 0) {
V oldValue = zeroValue;
zeroValue = value;
if (!hasZeroValue) {
hasZeroValue = true;
size++;
}
return oldValue;
}
int[] keyTable = this.keyTable;
// Check for existing keys.
int index1 = key & mask;
int key1 = keyTable[index1];
if (key1 == key) {
V oldValue = valueTable[index1];
valueTable[index1] = value;
return oldValue;
}
int index2 = hash2(key);
int key2 = keyTable[index2];
if (key2 == key) {
V oldValue = valueTable[index2];
valueTable[index2] = value;
return oldValue;
}
int index3 = hash3(key);
int key3 = keyTable[index3];
if (key3 == key) {
V oldValue = valueTable[index3];
valueTable[index3] = value;
return oldValue;
}
// Update key in the stash.
for (int i = capacity, n = i + stashSize; i < n; i++) {
if (keyTable[i] == key) {
V oldValue = valueTable[i];
valueTable[i] = value;
return oldValue;
}
}
// Check for empty buckets.
if (key1 == EMPTY) {
keyTable[index1] = key;
valueTable[index1] = value;
if (size++ >= threshold) {
resize(capacity << 1);
}
return null;
}
if (key2 == EMPTY) {
keyTable[index2] = key;
valueTable[index2] = value;
if (size++ >= threshold) {
resize(capacity << 1);
}
return null;
}
if (key3 == EMPTY) {
keyTable[index3] = key;
valueTable[index3] = value;
if (size++ >= threshold) {
resize(capacity << 1);
}
return null;
}
push(key, value, index1, key1, index2, key2, index3, key3);
return null;
}
public void putAll (IntMap<V> map) {
for (Entry<V> entry : map.entries()) {
put(entry.key, entry.value);
}
}
/** Skips checks for existing keys. */
private void putResize (int key, V value) {
if (key == 0) {
zeroValue = value;
hasZeroValue = true;
return;
}
// Check for empty buckets.
int index1 = key & mask;
int key1 = keyTable[index1];
if (key1 == EMPTY) {
keyTable[index1] = key;
valueTable[index1] = value;
if (size++ >= threshold) {
resize(capacity << 1);
}
return;
}
int index2 = hash2(key);
int key2 = keyTable[index2];
if (key2 == EMPTY) {
keyTable[index2] = key;
valueTable[index2] = value;
if (size++ >= threshold) {
resize(capacity << 1);
}
return;
}
int index3 = hash3(key);
int key3 = keyTable[index3];
if (key3 == EMPTY) {
keyTable[index3] = key;
valueTable[index3] = value;
if (size++ >= threshold) {
resize(capacity << 1);
}
return;
}
push(key, value, index1, key1, index2, key2, index3, key3);
}
private void push (int insertKey, V insertValue, int index1, int key1, int index2, int key2, int index3, int key3) {
int[] keyTable = this.keyTable;
V[] valueTable = this.valueTable;
int mask = this.mask;
// Push keys until an empty bucket is found.
int evictedKey;
V evictedValue;
int i = 0, pushIterations = this.pushIterations;
do {
// Replace the key and value for one of the hashes.
switch (MathUtils.random(2)) {
case 0:
evictedKey = key1;
evictedValue = valueTable[index1];
keyTable[index1] = insertKey;
valueTable[index1] = insertValue;
break;
case 1:
evictedKey = key2;
evictedValue = valueTable[index2];
keyTable[index2] = insertKey;
valueTable[index2] = insertValue;
break;
default:
evictedKey = key3;
evictedValue = valueTable[index3];
keyTable[index3] = insertKey;
valueTable[index3] = insertValue;
break;
}
// If the evicted key hashes to an empty bucket, put it there and stop.
index1 = evictedKey & mask;
key1 = keyTable[index1];
if (key1 == EMPTY) {
keyTable[index1] = evictedKey;
valueTable[index1] = evictedValue;
if (size++ >= threshold) {
resize(capacity << 1);
}
return;
}
index2 = hash2(evictedKey);
key2 = keyTable[index2];
if (key2 == EMPTY) {
keyTable[index2] = evictedKey;
valueTable[index2] = evictedValue;
if (size++ >= threshold) {
resize(capacity << 1);
}
return;
}
index3 = hash3(evictedKey);
key3 = keyTable[index3];
if (key3 == EMPTY) {
keyTable[index3] = evictedKey;
valueTable[index3] = evictedValue;
if (size++ >= threshold) {
resize(capacity << 1);
}
return;
}
if (++i == pushIterations) {
break;
}
insertKey = evictedKey;
insertValue = evictedValue;
} while (true);
putStash(evictedKey, evictedValue);
}
private void putStash (int key, V value) {
if (stashSize == stashCapacity) {
// Too many pushes occurred and the stash is full, increase the table size.
resize(capacity << 1);
put(key, value);
return;
}
// Store key in the stash.
int index = capacity + stashSize;
keyTable[index] = key;
valueTable[index] = value;
stashSize++;
size++;
}
public V get (int key) {
if (key == 0) {
if (!hasZeroValue) {
return null;
}
return zeroValue;
}
int index = key & mask;
if (keyTable[index] != key) {
index = hash2(key);
if (keyTable[index] != key) {
index = hash3(key);
if (keyTable[index] != key) {
return getStash(key, null);
}
}
}
return valueTable[index];
}
public V get (int key, V defaultValue) {
if (key == 0) {
if (!hasZeroValue) {
return defaultValue;
}
return zeroValue;
}
int index = key & mask;
if (keyTable[index] != key) {
index = hash2(key);
if (keyTable[index] != key) {
index = hash3(key);
if (keyTable[index] != key) {
return getStash(key, defaultValue);
}
}
}
return valueTable[index];
}
private V getStash (int key, V defaultValue) {
int[] keyTable = this.keyTable;
for (int i = capacity, n = i + stashSize; i < n; i++) {
if (keyTable[i] == key) {
return valueTable[i];
}
}
return defaultValue;
}
public V remove (int key) {
if (key == 0) {
if (!hasZeroValue) {
return null;
}
V oldValue = zeroValue;
zeroValue = null;
hasZeroValue = false;
size--;
return oldValue;
}
int index = key & mask;
if (keyTable[index] == key) {
keyTable[index] = EMPTY;
V oldValue = valueTable[index];
valueTable[index] = null;
size--;
return oldValue;
}
index = hash2(key);
if (keyTable[index] == key) {
keyTable[index] = EMPTY;
V oldValue = valueTable[index];
valueTable[index] = null;
size--;
return oldValue;
}
index = hash3(key);
if (keyTable[index] == key) {
keyTable[index] = EMPTY;
V oldValue = valueTable[index];
valueTable[index] = null;
size--;
return oldValue;
}
return removeStash(key);
}
V removeStash (int key) {
int[] keyTable = this.keyTable;
for (int i = capacity, n = i + stashSize; i < n; i++) {
if (keyTable[i] == key) {
V oldValue = valueTable[i];
removeStashIndex(i);
size--;
return oldValue;
}
}
return null;
}
void removeStashIndex (int index) {
// If the removed location was not last, move the last tuple to the removed location.
stashSize--;
int lastIndex = capacity + stashSize;
if (index < lastIndex) {
keyTable[index] = keyTable[lastIndex];
valueTable[index] = valueTable[lastIndex];
valueTable[lastIndex] = null;
} else {
valueTable[index] = null;
}
}
public void clear () {
int[] keyTable = this.keyTable;
V[] valueTable = this.valueTable;
for (int i = capacity + stashSize; i-- > 0;) {
keyTable[i] = EMPTY;
valueTable[i] = null;
}
size = 0;
stashSize = 0;
zeroValue = null;
hasZeroValue = false;
}
/** Returns true if the specified value is in the map. Note this traverses the entire map and compares every value, which may be
* an expensive operation.
* @param identity If true, uses == to compare the specified value with values in the map. If false, uses
* {@link #equals(Object)}. */
public boolean containsValue (Object value, boolean identity) {
V[] valueTable = this.valueTable;
if (value == null) {
if (hasZeroValue && zeroValue == null) {
return true;
}
int[] keyTable = this.keyTable;
for (int i = capacity + stashSize; i-- > 0;) {
if (keyTable[i] != EMPTY && valueTable[i] == null) {
return true;
}
}
} else if (identity) {
if (value == zeroValue) {
return true;
}
for (int i = capacity + stashSize; i-- > 0;) {
if (valueTable[i] == value) {
return true;
}
}
} else {
if (hasZeroValue && value.equals(zeroValue)) {
return true;
}
for (int i = capacity + stashSize; i-- > 0;) {
if (value.equals(valueTable[i])) {
return true;
}
}
}
return false;
}
public boolean containsKey (int key) {
if (key == 0) {
return hasZeroValue;
}
int index = key & mask;
if (keyTable[index] != key) {
index = hash2(key);
if (keyTable[index] != key) {
index = hash3(key);
if (keyTable[index] != key) {
return containsKeyStash(key);
}
}
}
return true;
}
private boolean containsKeyStash (int key) {
int[] keyTable = this.keyTable;
for (int i = capacity, n = i + stashSize; i < n; i++) {
if (keyTable[i] == key) {
return true;
}
}
return false;
}
/** Returns the key for the specified value, or <tt>notFound</tt> if it is not in the map. Note this traverses the entire map
* and compares every value, which may be an expensive operation.
* @param identity If true, uses == to compare the specified value with values in the map. If false, uses
* {@link #equals(Object)}. */
public int findKey (Object value, boolean identity, int notFound) {
V[] valueTable = this.valueTable;
if (value == null) {
if (hasZeroValue && zeroValue == null) {
return 0;
}
int[] keyTable = this.keyTable;
for (int i = capacity + stashSize; i-- > 0;) {
if (keyTable[i] != EMPTY && valueTable[i] == null) {
return keyTable[i];
}
}
} else if (identity) {
if (value == zeroValue) {
return 0;
}
for (int i = capacity + stashSize; i-- > 0;) {
if (valueTable[i] == value) {
return keyTable[i];
}
}
} else {
if (hasZeroValue && value.equals(zeroValue)) {
return 0;
}
for (int i = capacity + stashSize; i-- > 0;) {
if (value.equals(valueTable[i])) {
return keyTable[i];
}
}
}
return notFound;
}
/** Increases the size of the backing array to acommodate the specified number of additional items. Useful before adding many
* items to avoid multiple backing array resizes. */
public void ensureCapacity (int additionalCapacity) {
int sizeNeeded = size + additionalCapacity;
if (sizeNeeded >= threshold) {
resize(MathUtils.nextPowerOfTwo((int)(sizeNeeded / loadFactor)));
}
}
private void resize (int newSize) {
int oldEndIndex = capacity + stashSize;
capacity = newSize;
threshold = (int)(newSize * loadFactor);
mask = newSize - 1;
hashShift = 31 - Integer.numberOfTrailingZeros(newSize);
stashCapacity = Math.max(3, (int)Math.ceil(Math.log(newSize)) * 2);
pushIterations = Math.max(Math.min(newSize, 8), (int)Math.sqrt(newSize) / 8);
int[] oldKeyTable = keyTable;
V[] oldValueTable = valueTable;
keyTable = new int[newSize + stashCapacity];
valueTable = (V[])new Object[newSize + stashCapacity];
size = hasZeroValue ? 1 : 0;
stashSize = 0;
for (int i = 0; i < oldEndIndex; i++) {
int key = oldKeyTable[i];
if (key != EMPTY) {
putResize(key, oldValueTable[i]);
}
}
}
private int hash2 (int h) {
h *= PRIME2;
return (h ^ h >>> hashShift) & mask;
}
private int hash3 (int h) {
h *= PRIME3;
return (h ^ h >>> hashShift) & mask;
}
@Override
public String toString () {
if (size == 0) {
return "[]";
}
StringBuilder buffer = new StringBuilder(32);
buffer.append('[');
int[] keyTable = this.keyTable;
V[] valueTable = this.valueTable;
int i = keyTable.length;
if (hasZeroValue) {
buffer.append("0=");
buffer.append(zeroValue);
} else {
while (i-- > 0) {
int key = keyTable[i];
if (key == EMPTY) {
continue;
}
buffer.append(key);
buffer.append('=');
buffer.append(valueTable[i]);
break;
}
}
while (i-- > 0) {
int key = keyTable[i];
if (key == EMPTY) {
continue;
}
buffer.append(", ");
buffer.append(key);
buffer.append('=');
buffer.append(valueTable[i]);
}
buffer.append(']');
return buffer.toString();
}
/** Returns an iterator for the entries in the map. Remove is supported. Note that the same iterator instance is returned each
* time this method is called. Use the {@link Entries} constructor for nested or multithreaded iteration. */
public Entries<V> entries () {
if (entries1 == null) {
entries1 = new Entries(this);
entries2 = new Entries(this);
}
if (!entries1.valid) {
entries1.reset();
entries1.valid = true;
entries2.valid = false;
return entries1;
}
entries2.reset();
entries2.valid = true;
entries1.valid = false;
return entries2;
}
/** Returns an iterator for the values in the map. Remove is supported. Note that the same iterator instance is returned each
* time this method is called. Use the {@link Entries} constructor for nested or multithreaded iteration. */
public Values<V> values () {
if (values1 == null) {
values1 = new Values(this);
values2 = new Values(this);
}
if (!values1.valid) {
values1.reset();
values1.valid = true;
values2.valid = false;
return values1;
}
values2.reset();
values2.valid = true;
values1.valid = false;
return values2;
}
/** Returns an iterator for the keys in the map. Remove is supported. Note that the same iterator instance is returned each time
* this method is called. Use the {@link Entries} constructor for nested or multithreaded iteration. */
public Keys keys () {
if (keys1 == null) {
keys1 = new Keys(this);
keys2 = new Keys(this);
}
if (!keys1.valid) {
keys1.reset();
keys1.valid = true;
keys2.valid = false;
return keys1;
}
keys2.reset();
keys2.valid = true;
keys1.valid = false;
return keys2;
}
static public class Entry<V> {
public int key;
public V value;
@Override
public String toString () {
return key + "=" + value;
}
}
static private class MapIterator<V> {
static final int INDEX_ILLEGAL = -2;
static final int INDEX_ZERO = -1;
public boolean hasNext;
final IntMap<V> map;
int nextIndex, currentIndex;
boolean valid = true;
public MapIterator (IntMap<V> map) {
this.map = map;
reset();
}
public void reset () {
currentIndex = INDEX_ILLEGAL;
nextIndex = INDEX_ZERO;
if (map.hasZeroValue) {
hasNext = true;
} else {
findNextIndex();
}
}
void findNextIndex () {
hasNext = false;
int[] keyTable = map.keyTable;
for (int n = map.capacity + map.stashSize; ++nextIndex < n;) {
if (keyTable[nextIndex] != EMPTY) {
hasNext = true;
break;
}
}
}
public void remove () {
if (currentIndex == INDEX_ZERO && map.hasZeroValue) {
map.zeroValue = null;
map.hasZeroValue = false;
} else if (currentIndex < 0) {
throw new IllegalStateException("next must be called before remove.");
} else if (currentIndex >= map.capacity) {
map.removeStashIndex(currentIndex);
} else {
map.keyTable[currentIndex] = EMPTY;
map.valueTable[currentIndex] = null;
}
currentIndex = INDEX_ILLEGAL;
map.size--;
}
}
static public class Entries<V> extends MapIterator<V> implements Iterable<Entry<V>>, Iterator<Entry<V>> {
private Entry<V> entry = new Entry();
public Entries (IntMap map) {
super(map);
}
/** Note the same entry instance is returned each time this method is called. */
@Override
public Entry<V> next () {
if (!hasNext) {
throw new NoSuchElementException();
}
if (!valid) {
throw new RuntimeException("#iterator() cannot be used nested.");
}
int[] keyTable = map.keyTable;
if (nextIndex == INDEX_ZERO) {
entry.key = 0;
entry.value = map.zeroValue;
} else {
entry.key = keyTable[nextIndex];
entry.value = map.valueTable[nextIndex];
}
currentIndex = nextIndex;
findNextIndex();
return entry;
}
@Override
public boolean hasNext () {
return hasNext;
}
@Override
public Iterator<Entry<V>> iterator () {
return this;
}
}
static public class Values<V> extends MapIterator<V> implements Iterable<V>, Iterator<V> {
public Values (IntMap<V> map) {
super(map);
}
@Override
public boolean hasNext () {
return hasNext;
}
@Override
public V next () {
if (!hasNext) {
throw new NoSuchElementException();
}
if (!valid) {
throw new RuntimeException("#iterator() cannot be used nested.");
}
V value;
if (nextIndex == INDEX_ZERO) {
value = map.zeroValue;
} else {
value = map.valueTable[nextIndex];
}
currentIndex = nextIndex;
findNextIndex();
return value;
}
@Override
public Iterator<V> iterator () {
return this;
}
/** Returns a new array containing the remaining values. */
// public Array<V> toArray () {
// Array array = new Array(true, map.size);
// while (hasNext) {
// array.add(next());
// }
// return array;
// }
}
static public class Keys extends MapIterator {
public Keys (IntMap map) {
super(map);
}
public int next () {
if (!hasNext) {
throw new NoSuchElementException();
}
if (!valid) {
throw new RuntimeException("#iterator() cannot be used nested.");
}
int key = nextIndex == INDEX_ZERO ? 0 : map.keyTable[nextIndex];
currentIndex = nextIndex;
findNextIndex();
return key;
}
/** Returns a new array containing the remaining keys. */
public IntArray toArray () {
IntArray array = new IntArray(true, map.size);
while (hasNext) {
array.add(next());
}
return array;
}
}
}

View File

@ -1,85 +0,0 @@
/*******************************************************************************
* Copyright 2011 See AUTHORS file.
*
* 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.
*/
// pruned/limited version from libGDX
package dorkbox.network.util.primativeCollections;
import java.util.Random;
public class MathUtils {
// ---
static public Random random = new Random();
/** Returns a random number between 0 (inclusive) and the specified value (inclusive). */
static public final int random (int range) {
return random.nextInt(range + 1);
}
/** Returns a random number between start (inclusive) and end (inclusive). */
static public final int random (int start, int end) {
return start + random.nextInt(end - start + 1);
}
/** Returns a random boolean value. */
static public final boolean randomBoolean () {
return random.nextBoolean();
}
/** Returns random number between 0.0 (inclusive) and 1.0 (exclusive). */
static public final float random () {
return random.nextFloat();
}
/** Returns a random number between 0 (inclusive) and the specified value (exclusive). */
static public final float random (float range) {
return random.nextFloat() * range;
}
/** Returns a random number between start (inclusive) and end (exclusive). */
static public final float random (float start, float end) {
return start + random.nextFloat() * (end - start);
}
// ---
/**
* Returns the next power of two. Returns the specified value if the value
* is already a power of two.
*/
public static int nextPowerOfTwo(int value) {
if (value == 0) {
return 1;
}
value--;
value |= value >> 1;
value |= value >> 2;
value |= value >> 4;
value |= value >> 8;
value |= value >> 16;
return value + 1;
}
public static boolean isPowerOfTwo(int value) {
return value != 0 && (value & value - 1) == 0;
}
}

View File

@ -14,7 +14,7 @@
* limitations under the License.
*
*/
package dorkbox.network.util;
package dorkbox.network.util.serializers;
import java.lang.reflect.Array;
import java.lang.reflect.Field;

View File

@ -0,0 +1,186 @@
package dorkbox.network.util.serializers;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.Serializer;
import com.esotericsoftware.kryo.factories.SerializerFactory;
import com.esotericsoftware.kryo.serializers.FieldSerializer;
/**
* A kryo {@link FieldSerializer} that allows to exclusively include or exclude fields that
* are attributed with user-specific annotations. This can be for example useful when serializing beans that carry
* references to a dependency injection framework. As an example for Spring:
* <p/>
* <pre>
* {@code
* Set<Class<? extends Annotation>> marks = new HashSet<>();
* marks.add(Autowired.class);
* SerializerFactory disregardingFactory = new FieldAnnotationAwareSerializer.Factory(marks, true);
* Kryo kryo = new Kryo();
* kryo.setDefaultSerializer(factory);
* }
* </pre>
* <p/>
* The resulting {@link Kryo} instance would ignore all fields that are annotated with Spring's {@code @Autowired}
* annotation.
* <p/>
* Similarly, it is possible to created a serializer which does the opposite such that the resulting serializer
* would only serialize fields that are annotated with the specified annotations.
*
* @author <a href="mailto:rafael.wth@web.de">Rafael Winterhalter</a>
* @author <a href="mailto:martin.grotzke@javakaffee.de">Martin Grotzke</a>
*/
public class FieldAnnotationAwareSerializer<T> extends FieldSerializer<T> {
/**
* A factory for creating instances of {@link FieldAnnotationAwareSerializer}.
*/
public static class Factory implements SerializerFactory {
private final Collection<Class<? extends Annotation>> marked;
private final boolean disregarding;
/**
* Creates a new factory. See {@link FieldAnnotationAwareSerializer#FieldAnnotationAwareSerializer(
*com.esotericsoftware.kryo.Kryo, Class, java.util.Collection, boolean)}
* for additional information on the constructor parameters.
*
* @param marked The annotations that will be considered of the resulting converter.
* @param disregarding If {@code true}, the serializer will ignore all annotated fields,
* if set to {@code false} it will exclusively look at annotated fields.
*/
public Factory(final Collection<Class<? extends Annotation>> marked, final boolean disregarding) {
this.marked = marked;
this.disregarding = disregarding;
}
@Override
public Serializer<?> makeSerializer(final Kryo kryo, final Class<?> type) {
return new FieldAnnotationAwareSerializer<Object>(kryo, type, this.marked, this.disregarding);
}
}
private final Set<Class<? extends Annotation>> marked;
/**
* Determines whether annotated fields should be excluded from serialization.
* <p/>
* {@code true} if annotated fields should be excluded from serialization,
* {@code false} if only annotated fields should be included from serialization.
*/
private final boolean disregarding;
/**
* Creates a new field annotation aware serializer.
*
* @param kryo The {@link Kryo} instace.
* @param type The type of the class being serialized.
* @param marked The annotations this serializer considers for its serialization process. Be aware tha
* a serializer with {@code disregarding} set to {@code false} will never be able to
* serialize fields that are not annotated with any of these annotations since it is not
* possible to add fields to a {@link FieldSerializer} once it is created. See the
* documentation to {@link FieldAnnotationAwareSerializer#addAnnotation(Class)} and
* {@link FieldAnnotationAwareSerializer#removeAnnotation(Class)} for further information.
* @param disregarding If {@code true}, the serializer will ignore all annotated fields,
* if set to {@code false} it will exclusively look at annotated fields.
*/
public FieldAnnotationAwareSerializer(final Kryo kryo,
final Class<?> type,
final Collection<Class<? extends Annotation>> marked,
final boolean disregarding) {
super(kryo, type);
this.disregarding = disregarding;
this.marked = new HashSet<Class<? extends Annotation>>(marked);
rebuildCachedFields();
}
@Override
protected void rebuildCachedFields() {
// In order to avoid rebuilding the cached fields twice, the super constructor's call
// to this method will be suppressed. This can be done by a simple check of the initialization
// state of a property of this subclass.
if (this.marked == null) {
return;
}
super.rebuildCachedFields();
removeFields();
}
private void removeFields() {
final CachedField<?>[] cachedFields = getFields();
for (final CachedField<?> cachedField : cachedFields) {
final Field field = cachedField.getField();
if (isRemove(field)) {
// if (TRACE) {
// trace("kryo", String.format("Ignoring field %s tag: %s", this.disregarding ? "without" : "with", cachedField));
// }
super.removeField(field.getName());
}
}
}
private boolean isRemove(final Field field) {
return !isMarked(field) ^ this.disregarding;
}
private boolean isMarked(final Field field) {
for (final Annotation annotation : field.getAnnotations()) {
final Class<? extends Annotation> annotationType = annotation.annotationType();
if (this.marked.contains(annotationType)) {
return true;
}
}
return false;
}
/**
* Adds an annotation to the annotations that are considered by this serializer.
* <p/>
* <b>Important</b>: This will not have an effect if the serializer was configured
* to exclusively serialize annotated fields by setting {@code disregarding} to
* {@code false}. This is similar to the contract of this serializer's superclass
* {@link FieldSerializer} which does not allow to add fields that were formerly
* removed. If this was possible, instances that were serialized before this field
* was added could not longer be properly deserialized. In order to make this contract
* break explicit, you need to create a new instance of this serializer if you want to
* include new fields to a serializer that exclusively serializes annotated fields.
*
* @param clazz The annotation class to be added.
* @return {@code true} if the method call had an effect.
*/
public boolean addAnnotation(final Class<? extends Annotation> clazz) {
if (this.disregarding && this.marked.add(clazz)) {
initializeCachedFields();
return true;
}
return false;
}
/**
* Removes an annotation to the annotations that are considered by this serializer.
* <p/>
* <b>Important</b>: This will not have an effect if the serializer was configured
* to not serialize annotated fields by setting {@code disregarding} to
* {@code true}. This is similar to the contract of this serializer's superclass
* {@link FieldSerializer} which does not allow to add fields that were formerly
* removed. If this was possible, instances that were serialized before this field
* was added could not longer be properly deserialized. In order to make this contract
* break explicit, you need to create a new instance of this serializer if you want to
* include new fields to a serializer that ignores annotated fields for serialization.
*
* @param clazz The annotation class to be removed.
* @return {@code true} if the method call had an effect.
*/
public boolean removeAnnotation(final Class<? extends Annotation> clazz) {
if (!this.disregarding && this.marked.remove(clazz)) {
initializeCachedFields();
return true;
}
return false;
}
}

View File

@ -14,7 +14,7 @@
* limitations under the License.
*
*/
package dorkbox.network.util;
package dorkbox.network.util.serializers;
import java.lang.reflect.Field;
import java.util.ArrayList;

View File

@ -6,7 +6,7 @@ import java.security.SecureRandom;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import dorkbox.network.util.SecurityException;
import dorkbox.network.util.exceptions.SecurityException;
public class NullSettingsStore extends SettingsStore {

View File

@ -6,7 +6,7 @@ import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import dorkbox.network.util.SecurityException;
import dorkbox.network.util.exceptions.SecurityException;
import dorkbox.util.Storage;
/**

View File

@ -18,9 +18,9 @@ import ch.qos.logback.classic.joran.JoranConfigurator;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.ConsoleAppender;
import dorkbox.network.connection.EndPoint;
import dorkbox.network.util.InitializationException;
import dorkbox.network.util.entropy.Entropy;
import dorkbox.network.util.entropy.SimpleEntropy;
import dorkbox.network.util.exceptions.InitializationException;
public abstract class BaseTest {

View File

@ -12,9 +12,9 @@ import org.junit.Test;
import dorkbox.network.connection.Connection;
import dorkbox.network.connection.Listener;
import dorkbox.network.util.InitializationException;
import dorkbox.network.util.SecurityException;
import dorkbox.network.util.SerializationManager;
import dorkbox.network.util.exceptions.InitializationException;
import dorkbox.network.util.exceptions.SecurityException;
public class BufferTest extends BaseTest {
private static final int OBJ_SIZE = 1024 * 10;

View File

@ -11,9 +11,9 @@ import org.junit.Test;
import dorkbox.network.connection.Connection;
import dorkbox.network.connection.Listener;
import dorkbox.network.util.InitializationException;
import dorkbox.network.util.SecurityException;
import dorkbox.network.util.SerializationManager;
import dorkbox.network.util.exceptions.InitializationException;
import dorkbox.network.util.exceptions.SecurityException;
public class ClientSendTest extends BaseTest {

View File

@ -10,8 +10,8 @@ import org.junit.Test;
import dorkbox.network.connection.Connection;
import dorkbox.network.connection.Listener;
import dorkbox.network.util.InitializationException;
import dorkbox.network.util.SecurityException;
import dorkbox.network.util.exceptions.InitializationException;
import dorkbox.network.util.exceptions.SecurityException;
public class ConnectionTest extends BaseTest {

View File

@ -10,8 +10,8 @@ import org.junit.Test;
import dorkbox.network.connection.Connection;
import dorkbox.network.connection.Listener;
import dorkbox.network.util.InitializationException;
import dorkbox.network.util.SecurityException;
import dorkbox.network.util.exceptions.InitializationException;
import dorkbox.network.util.exceptions.SecurityException;
public class DiscoverHostTest extends BaseTest {
volatile boolean connected = false;

View File

@ -16,9 +16,9 @@ import dorkbox.network.connection.Connection;
import dorkbox.network.connection.Listener;
import dorkbox.network.connection.idle.IdleBridge;
import dorkbox.network.connection.idle.InputStreamSender;
import dorkbox.network.util.InitializationException;
import dorkbox.network.util.SecurityException;
import dorkbox.network.util.SerializationManager;
import dorkbox.network.util.exceptions.InitializationException;
import dorkbox.network.util.exceptions.SecurityException;
@SuppressWarnings({"rawtypes"})
public class IdleTest extends BaseTest {

View File

@ -15,8 +15,8 @@ import org.junit.Test;
import dorkbox.network.connection.Connection;
import dorkbox.network.connection.ConnectionImpl;
import dorkbox.network.connection.Listener;
import dorkbox.network.util.InitializationException;
import dorkbox.network.util.SecurityException;
import dorkbox.network.util.exceptions.InitializationException;
import dorkbox.network.util.exceptions.SecurityException;
public class ListenerTest extends BaseTest {

View File

@ -10,8 +10,8 @@ import org.junit.Test;
import dorkbox.network.connection.Connection;
import dorkbox.network.connection.Listener;
import dorkbox.network.util.InitializationException;
import dorkbox.network.util.SecurityException;
import dorkbox.network.util.exceptions.InitializationException;
import dorkbox.network.util.exceptions.SecurityException;
public class MultipleServerTest extends BaseTest {
AtomicInteger received = new AtomicInteger();

View File

@ -15,8 +15,8 @@ import org.junit.Test;
import dorkbox.network.connection.Connection;
import dorkbox.network.connection.Listener;
import dorkbox.network.util.InitializationException;
import dorkbox.network.util.SecurityException;
import dorkbox.network.util.exceptions.InitializationException;
import dorkbox.network.util.exceptions.SecurityException;
public class MultipleThreadTest extends BaseTest {
AtomicInteger sent = new AtomicInteger(0);

View File

@ -11,9 +11,9 @@ import org.junit.Test;
import dorkbox.network.connection.Connection;
import dorkbox.network.connection.Listener;
import dorkbox.network.util.InitializationException;
import dorkbox.network.util.SecurityException;
import dorkbox.network.util.SerializationManager;
import dorkbox.network.util.exceptions.InitializationException;
import dorkbox.network.util.exceptions.SecurityException;
public class PingPongLocalTest extends BaseTest {
private volatile String fail;

View File

@ -14,9 +14,9 @@ import org.junit.Test;
import dorkbox.network.connection.Connection;
import dorkbox.network.connection.EndPoint;
import dorkbox.network.connection.Listener;
import dorkbox.network.util.InitializationException;
import dorkbox.network.util.SecurityException;
import dorkbox.network.util.SerializationManager;
import dorkbox.network.util.exceptions.InitializationException;
import dorkbox.network.util.exceptions.SecurityException;
public class PingPongTest extends BaseTest {
private volatile String fail;

View File

@ -11,8 +11,8 @@ import org.junit.Test;
import dorkbox.network.connection.Connection;
import dorkbox.network.connection.Listener;
import dorkbox.network.connection.ping.PingMessage;
import dorkbox.network.util.InitializationException;
import dorkbox.network.util.SecurityException;
import dorkbox.network.util.exceptions.InitializationException;
import dorkbox.network.util.exceptions.SecurityException;
public class PingTest extends BaseTest {

View File

@ -13,8 +13,8 @@ import org.junit.Test;
import dorkbox.network.connection.Connection;
import dorkbox.network.connection.Listener;
import dorkbox.network.util.InitializationException;
import dorkbox.network.util.SecurityException;
import dorkbox.network.util.exceptions.InitializationException;
import dorkbox.network.util.exceptions.SecurityException;
public class ReconnectTest extends BaseTest {

View File

@ -8,8 +8,8 @@ import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.junit.Test;
import dorkbox.network.util.InitializationException;
import dorkbox.network.util.SecurityException;
import dorkbox.network.util.exceptions.InitializationException;
import dorkbox.network.util.exceptions.SecurityException;
import dorkbox.network.util.store.SettingsStore;

View File

@ -11,8 +11,8 @@ import org.junit.Test;
import dorkbox.network.connection.Connection;
import dorkbox.network.connection.Listener;
import dorkbox.network.util.InitializationException;
import dorkbox.network.util.SecurityException;
import dorkbox.network.util.exceptions.InitializationException;
import dorkbox.network.util.exceptions.SecurityException;
public class ReuseTest extends BaseTest {
AtomicInteger serverCount;

View File

@ -14,8 +14,8 @@ import org.junit.Test;
import dorkbox.network.connection.Connection;
import dorkbox.network.connection.EndPoint;
import dorkbox.network.connection.Listener;
import dorkbox.network.util.InitializationException;
import dorkbox.network.util.SecurityException;
import dorkbox.network.util.exceptions.InitializationException;
import dorkbox.network.util.exceptions.SecurityException;
public class UnregisteredClassTest extends BaseTest {
private String fail;

View File

@ -13,9 +13,9 @@ import dorkbox.network.BaseTest;
import dorkbox.network.Server;
import dorkbox.network.connection.Connection;
import dorkbox.network.connection.Listener;
import dorkbox.network.util.InitializationException;
import dorkbox.network.util.SecurityException;
import dorkbox.network.util.SerializationManager;
import dorkbox.network.util.exceptions.InitializationException;
import dorkbox.network.util.exceptions.SecurityException;
public class RmiSendObjectTest extends BaseTest {
private RmiBridge serverRMI;

View File

@ -15,9 +15,9 @@ import dorkbox.network.BaseTest;
import dorkbox.network.Server;
import dorkbox.network.connection.Connection;
import dorkbox.network.connection.Listener;
import dorkbox.network.util.InitializationException;
import dorkbox.network.util.SecurityException;
import dorkbox.network.util.SerializationManager;
import dorkbox.network.util.exceptions.InitializationException;
import dorkbox.network.util.exceptions.SecurityException;
public class RmiTest extends BaseTest {