<commit_before>
package com.esotericsoftware.kryo;

import static com.esotericsoftware.minlog.Log.*;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.nio.ByteBuffer;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

import com.esotericsoftware.kryo.serialize.ArraySerializer;
import com.esotericsoftware.kryo.serialize.BooleanSerializer;
import com.esotericsoftware.kryo.serialize.ByteSerializer;
import com.esotericsoftware.kryo.serialize.CharSerializer;
import com.esotericsoftware.kryo.serialize.CollectionSerializer;
import com.esotericsoftware.kryo.serialize.CustomSerializer;
import com.esotericsoftware.kryo.serialize.DoubleSerializer;
import com.esotericsoftware.kryo.serialize.EnumSerializer;
import com.esotericsoftware.kryo.serialize.FieldSerializer;
import com.esotericsoftware.kryo.serialize.FloatSerializer;
import com.esotericsoftware.kryo.serialize.IntSerializer;
import com.esotericsoftware.kryo.serialize.LongSerializer;
import com.esotericsoftware.kryo.serialize.MapSerializer;
import com.esotericsoftware.kryo.serialize.ShortSerializer;
import com.esotericsoftware.kryo.serialize.StringSerializer;
import com.esotericsoftware.kryo.util.ShortHashMap;

// BOZO - Add multithreaded tests.

/**
 * Maps classes to serializers so object graphs can be serialized automatically.
 * @author <NAME> <<EMAIL>>
 */
public class Kryo {
	static private final byte ID_NULL_OBJECT = 0;

	static private ThreadLocal<Context> contextThreadLocal = new ThreadLocal<Context>() {
		protected Context initialValue () {
			return new Context();
		}
	};

	private final ShortHashMap<RegisteredClass> idToRegisteredClass = new ShortHashMap(64);
	private final HashMap<Class, RegisteredClass> classToRegisteredClass = new HashMap(64);
	private AtomicInteger nextClassID = new AtomicInteger(1);
	private Object listenerLock = new Object();
	private KryoListener[] listeners = {};

	private final CustomSerializer customSerializer = new CustomSerializer(this);
	private final FieldSerializer fieldSerializer = new FieldSerializer(this);
	private final ArraySerializer arraySerializer = new ArraySerializer(this);
	private final EnumSerializer enumSerializer = new EnumSerializer();
	private final CollectionSerializer collectionSerializer = new CollectionSerializer(this);
	private final MapSerializer mapSerializer = new MapSerializer(this);

	public Kryo () {
		Serializer serializer;
		// Primitives.
		register(boolean.class, new BooleanSerializer());
		register(byte.class, new ByteSerializer());
		register(char.class, new CharSerializer());
		register(short.class, new ShortSerializer());
		register(int.class, new IntSerializer());
		register(long.class, new LongSerializer());
		register(float.class, new FloatSerializer());
		register(double.class, new DoubleSerializer());
		// Primitive wrappers.
		register(Boolean.class, new BooleanSerializer());
		register(Byte.class, new ByteSerializer());
		register(Character.class, new CharSerializer());
		register(Short.class, new ShortSerializer());
		register(Integer.class, new IntSerializer());
		register(Long.class, new LongSerializer());
		register(Float.class, new FloatSerializer());
		register(Double.class, new DoubleSerializer());
		// Other.
		register(String.class, new StringSerializer());
	}

	/**
	 * Registers a class to be serialized. The exact same classes and serializers must be registered in exactly the same order when
	 * the class is deserialized.
	 * <p>
	 * By default primitive types, primitive wrappers, and java.lang.String are registered. To transfer ANY other classes over the
	 * network, those classes must be registered. Note that even JDK classes like ArrayList, HashMap, etc must be registered. Also,
	 * array classes such as "int[].class" or "short[][].class" must be registered.
	 * <p>
	 * The {@link Serializer} specified will be used to serialize and deserialize objects of the specified type. Note that a
	 * serializer can be wrapped with a {@link Compressor}.
	 * <p>
	 * A serializer may not be registered with more than one Kryo instance.
	 * @see #register(Class)
	 * @see Serializer
	 * @see Compressor
	 */
	public void register (Class type, Serializer serializer) {
		if (type == null) throw new IllegalArgumentException("type cannot be null.");
		if (serializer == null) throw new IllegalArgumentException("serializer cannot be null.");
		if (type.isPrimitive()) serializer.setCanBeNull(false);
		short id;
		RegisteredClass existingRegisteredClass = classToRegisteredClass.get(type);
		if (existingRegisteredClass != null)
			id = existingRegisteredClass.id;
		else
			id = (short)nextClassID.getAndIncrement();
		RegisteredClass registeredClass = new RegisteredClass(type, id, serializer);
		idToRegisteredClass.put(id, registeredClass);
		classToRegisteredClass.put(type, registeredClass);
		if (TRACE && id > 17) {
			String name = type.getName();
			if (type.isArray()) {
				Class elementClass = ArraySerializer.getElementClass(type);
				StringBuilder buffer = new StringBuilder(16);
				for (int i = 0, n = ArraySerializer.getDimensionCount(type); i < n; i++)
					buffer.append("[]");
				name = elementClass.getName() + buffer;
			}
			trace("kryo", "Registered class " + id + ": " + name + " (" + serializer.getClass().getName() + ")");
		}
	}

	/**
	 * Registers the class, automatically determining the serializer to use. A serializer will be chosen according to this table:
	 * <p>
	 * <table>
	 * <tr>
	 * <th>Type</th>
	 * <th>Serializer</th>
	 * </tr>
	 * <tr>
	 * <td>array (any number of dimensions)</td>
	 * <td>{@link ArraySerializer}</td>
	 * </tr>
	 * <tr>
	 * <td>{@link Enum}</td>
	 * <td>{@link EnumSerializer}</td>
	 * </tr>
	 * <tr>
	 * <td>{@link Collection}</td>
	 * <td>{@link CollectionSerializer}</td>
	 * </tr>
	 * <tr>
	 * <td>{@link Map}</td>
	 * <td>{@link MapSerializer}</td>
	 * </tr>
	 * <tr>
	 * <td>{@link CustomSerialization}</td>
	 * <td>{@link CustomSerializer}</td>
	 * </tr>
	 * <tr>
	 * <td>any other class</td>
	 * <td>{@link FieldSerializer}</td>
	 * </tr>
	 * </table>
	 * <p>
	 * Note that some serializers allow additional information to be specified to make serialization more efficient in some cases
	 * (eg, {@link FieldSerializer#getField(Class, String)}).
	 * @see #register(Class, Serializer)
	 */
	public void register (Class type) {
		if (type == null) throw new IllegalArgumentException("type cannot be null.");
		Serializer serializer;
		if (type.isArray())
			serializer = arraySerializer;
		else if (CustomSerialization.class.isAssignableFrom(type))
			serializer = customSerializer;
		else if (Collection.class.isAssignableFrom(type))
			serializer = collectionSerializer;
		else if (Map.class.isAssignableFrom(type))
			serializer = mapSerializer;
		else if (Enum.class.isAssignableFrom(type))
			serializer = enumSerializer;
		else {<commit_msg>Fixed incorrectly registering String or a primitive type.<commit_after>
package com.esotericsoftware.kryo;

import static com.esotericsoftware.minlog.Log.*;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.nio.ByteBuffer;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

import com.esotericsoftware.kryo.serialize.ArraySerializer;
import com.esotericsoftware.kryo.serialize.BooleanSerializer;
import com.esotericsoftware.kryo.serialize.ByteSerializer;
import com.esotericsoftware.kryo.serialize.CharSerializer;
import com.esotericsoftware.kryo.serialize.CollectionSerializer;
import com.esotericsoftware.kryo.serialize.CustomSerializer;
import com.esotericsoftware.kryo.serialize.DoubleSerializer;
import com.esotericsoftware.kryo.serialize.EnumSerializer;
import com.esotericsoftware.kryo.serialize.FieldSerializer;
import com.esotericsoftware.kryo.serialize.FloatSerializer;
import com.esotericsoftware.kryo.serialize.IntSerializer;
import com.esotericsoftware.kryo.serialize.LongSerializer;
import com.esotericsoftware.kryo.serialize.MapSerializer;
import com.esotericsoftware.kryo.serialize.ShortSerializer;
import com.esotericsoftware.kryo.serialize.StringSerializer;
import com.esotericsoftware.kryo.util.ShortHashMap;

// BOZO - Add multithreaded tests.

/**
 * Maps classes to serializers so object graphs can be serialized automatically.
 * @author <NAME> <<EMAIL>>
 */
public class Kryo {
	static private final byte ID_NULL_OBJECT = 0;

	static private ThreadLocal<Context> contextThreadLocal = new ThreadLocal<Context>() {
		protected Context initialValue () {
			return new Context();
		}
	};

	private final ShortHashMap<RegisteredClass> idToRegisteredClass = new ShortHashMap(64);
	private final HashMap<Class, RegisteredClass> classToRegisteredClass = new HashMap(64);
	private AtomicInteger nextClassID = new AtomicInteger(1);
	private Object listenerLock = new Object();
	private KryoListener[] listeners = {};

	private final CustomSerializer customSerializer = new CustomSerializer(this);
	private final FieldSerializer fieldSerializer = new FieldSerializer(this);
	private final ArraySerializer arraySerializer = new ArraySerializer(this);
	private final EnumSerializer enumSerializer = new EnumSerializer();
	private final CollectionSerializer collectionSerializer = new CollectionSerializer(this);
	private final MapSerializer mapSerializer = new MapSerializer(this);

	public Kryo () {
		Serializer serializer;
		// Primitives.
		register(boolean.class, new BooleanSerializer());
		register(byte.class, new ByteSerializer());
		register(char.class, new CharSerializer());
		register(short.class, new ShortSerializer());
		register(int.class, new IntSerializer());
		register(long.class, new LongSerializer());
		register(float.class, new FloatSerializer());
		register(double.class, new DoubleSerializer());
		// Primitive wrappers.
		register(Boolean.class, new BooleanSerializer());
		register(Byte.class, new ByteSerializer());
		register(Character.class, new CharSerializer());
		register(Short.class, new ShortSerializer());
		register(Integer.class, new IntSerializer());
		register(Long.class, new LongSerializer());
		register(Float.class, new FloatSerializer());
		register(Double.class, new DoubleSerializer());
		// Other.
		register(String.class, new StringSerializer());
	}

	/**
	 * Registers a class to be serialized. The exact same classes and serializers must be registered in exactly the same order when
	 * the class is deserialized.
	 * <p>
	 * By default primitive types, primitive wrappers, and java.lang.String are registered. To transfer ANY other classes over the
	 * network, those classes must be registered. Note that even JDK classes like ArrayList, HashMap, etc must be registered. Also,
	 * array classes such as "int[].class" or "short[][].class" must be registered.
	 * <p>
	 * The {@link Serializer} specified will be used to serialize and deserialize objects of the specified type. Note that a
	 * serializer can be wrapped with a {@link Compressor}.
	 * <p>
	 * If the class is already registered, the serializer will be changed.
	 * @see #register(Class)
	 * @see Serializer
	 * @see Compressor
	 */
	public void register (Class type, Serializer serializer) {
		if (type == null) throw new IllegalArgumentException("type cannot be null.");
		if (serializer == null) throw new IllegalArgumentException("serializer cannot be null.");
		if (type.isPrimitive()) serializer.setCanBeNull(false);
		short id;
		RegisteredClass existingRegisteredClass = classToRegisteredClass.get(type);
		if (existingRegisteredClass != null)
			id = existingRegisteredClass.id;
		else
			id = (short)nextClassID.getAndIncrement();
		RegisteredClass registeredClass = new RegisteredClass(type, id, serializer);
		idToRegisteredClass.put(id, registeredClass);
		classToRegisteredClass.put(type, registeredClass);
		if (TRACE && id > 17) {
			String name = type.getName();
			if (type.isArray()) {
				Class elementClass = ArraySerializer.getElementClass(type);
				StringBuilder buffer = new StringBuilder(16);
				for (int i = 0, n = ArraySerializer.getDimensionCount(type); i < n; i++)
					buffer.append("[]");
				name = elementClass.getName() + buffer;
			}
			trace("kryo", "Registered class " + id + ": " + name + " (" + serializer.getClass().getName() + ")");
		}
	}

	/**
	 * Registers the class, automatically determining the serializer to use. A serializer will be chosen according to this table:
	 * <p>
	 * <table>
	 * <tr>
	 * <th>Type</th>
	 * <th>Serializer</th>
	 * </tr>
	 * <tr>
	 * <td>array (any number of dimensions)</td>
	 * <td>{@link ArraySerializer}</td>
	 * </tr>
	 * <tr>
	 * <td>{@link Enum}</td>
	 * <td>{@link EnumSerializer}</td>
	 * </tr>
	 * <tr>
	 * <td>{@link Collection}</td>
	 * <td>{@link CollectionSerializer}</td>
	 * </tr>
	 * <tr>
	 * <td>{@link Map}</td>
	 * <td>{@link MapSerializer}</td>
	 * </tr>
	 * <tr>
	 * <td>{@link CustomSerialization}</td>
	 * <td>{@link CustomSerializer}</td>
	 * </tr>
	 * <tr>
	 * <td>any other class</td>
	 * <td>{@link FieldSerializer}</td>
	 * </tr>
	 * </table>
	 * <p>
	 * Note that some serializers allow additional information to be specified to make serialization more efficient in some cases
	 * (eg, {@link FieldSerializer#getField(Class, String)}).
	 * @see #register(Class, Serializer)
	 */
	public void register (Class type) {
		if (type == null) throw new IllegalArgumentException("type cannot be null.");
		RegisteredClass existingRegisteredClass = classToRegisteredClass.get(type);
		if (existingRegisteredClass != null && existingRegisteredClass.id >= 1 && existingRegisteredClass.id <= 17) {
			if (WARN) warn("Registration unnecessary, class is registered by default: " + type.getName());
			return;
		}
		Serializer serializer;
		if (type.isArray())
			serializer = arraySerializer;
		else if (CustomSerialization.class.isAssignableFrom(type))
			serializer = customSerializer;
		else if (Collection.class.isAssignableFrom(type))
			serializer = collectionSerializer;
		else if (Map.class.isAssignableFrom(type))
			serializer = mapSerializer;
		else if (Enum.class.isAssignableFrom(type))
			serializer = enumSerializer;
		else {
{'fraction_non_alphanumeric': 0.11801548205489092, 'fraction_numerical': 0.0017593244194229415, 'mean_word_length': 5.044661846022969, 'pattern_counts': {'":': 2, '<': 118, '<?xml version=': 0, '>': 118, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2125211', 'n_tokens_mistral': 4306, 'n_tokens_neox': 3987, 'n_words': 1131}