All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.antlr.v4.runtime.dfa.ArrayEdgeMap Maven / Gradle / Ivy

There is a newer version: 4.9.0
Show newest version
/*
 * Copyright (c) 2012 The ANTLR Project. All rights reserved.
 * Use of this file is governed by the BSD-3-Clause license that
 * can be found in the LICENSE.txt file in the project root.
 */
package org.antlr.v4.runtime.dfa;

import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicIntegerArray;
import java.util.concurrent.atomic.AtomicReferenceArray;

/**
 *
 * @author Sam Harwell
 */
public final class ArrayEdgeMap extends AbstractEdgeMap {

	private final AtomicReferenceArray arrayData;
	private final AtomicInteger size;

	@SuppressWarnings("unchecked")
	public ArrayEdgeMap(int minIndex, int maxIndex) {
		super(minIndex, maxIndex);
		arrayData = new AtomicReferenceArray(maxIndex - minIndex + 1);
		size = new AtomicInteger();
	}

	@Override
	public int size() {
		return size.get();
	}

	@Override
	public boolean isEmpty() {
		return size() == 0;
	}

	@Override
	public boolean containsKey(int key) {
		return get(key) != null;
	}

	@Override
	public T get(int key) {
		if (key < minIndex || key > maxIndex) {
			return null;
		}

		return arrayData.get(key - minIndex);
	}

	@Override
	public ArrayEdgeMap put(int key, T value) {
		if (key >= minIndex && key <= maxIndex) {
			T existing = arrayData.getAndSet(key - minIndex, value);
			if (existing == null && value != null) {
				size.incrementAndGet();
			} else if (existing != null && value == null) {
				size.decrementAndGet();
			}
		}

		return this;
	}

	@Override
	public ArrayEdgeMap remove(int key) {
		return put(key, null);
	}

	@Override
	@SuppressWarnings("deprecation")
	public ArrayEdgeMap putAll(EdgeMap m) {
		if (m.isEmpty()) {
			return this;
		}

		if (m instanceof HashEdgeMap) {
			HashEdgeMap other = (HashEdgeMap)m;
			AtomicIntegerArray keys = other.getKeys();
			T[] values = other.getValues();
			ArrayEdgeMap result = this;
			for (int i = 0; i < values.length; i++) {
				T value = values[i];
				if (value != null) {
					result = result.put(keys.get(i), value);
				}
			}

			return result;
		} else if (m instanceof ArrayEdgeMap) {
			ArrayEdgeMap other = (ArrayEdgeMap)m;
			int minOverlap = Math.max(minIndex, other.minIndex);
			int maxOverlap = Math.min(maxIndex, other.maxIndex);
			ArrayEdgeMap result = this;
			for (int i = minOverlap; i <= maxOverlap; i++) {
				result = result.put(i, m.get(i));
			}

			return result;
		} else if (m instanceof SingletonEdgeMap) {
			SingletonEdgeMap other = (SingletonEdgeMap)m;
			assert !other.isEmpty();
			return put(other.getKey(), other.getValue());
		} else if (m instanceof SparseEdgeMap) {
			SparseEdgeMap other = (SparseEdgeMap)m;
			synchronized (other) {
				int[] keys = other.getKeys();
				List values = other.getValues();
				ArrayEdgeMap result = this;
				for (int i = 0; i < values.size(); i++) {
					result = result.put(keys[i], values.get(i));
				}
				return result;
			}
		} else {
			throw new UnsupportedOperationException(String.format("EdgeMap of type %s is supported yet.", m.getClass().getName()));
		}
	}

	@Override
	public EmptyEdgeMap clear() {
		return new EmptyEdgeMap(minIndex, maxIndex);
	}

	@Override
	public Map toMap() {
		if (isEmpty()) {
			return Collections.emptyMap();
		}

		Map result = new LinkedHashMap();
		for (int i = 0; i < arrayData.length(); i++) {
			T element = arrayData.get(i);
			if (element == null) {
				continue;
			}

			result.put(i + minIndex, element);
		}

		return result;
	}

	@Override
	public Set> entrySet() {
		return new EntrySet();
	}

	private class EntrySet extends AbstractEntrySet {
		@Override
		public Iterator> iterator() {
			return new EntryIterator();
		}
	}

	private class EntryIterator implements Iterator> {
		private int currentIndex = -1;

		@Override
		public boolean hasNext() {
			return currentIndex < arrayData.length() - 1;
		}

		@Override
		public Map.Entry next() {
			T element = null;
			while (element == null && currentIndex < arrayData.length() - 1) {
				currentIndex++;
				element = arrayData.get(currentIndex);
			}

			if (element == null) {
				throw new NoSuchElementException();
			}

			currentIndex++;
			final T currentElement = element;
			return new Map.Entry() {
				private final int key = minIndex + currentIndex - 1;
				private final T value = currentElement;

				@Override
				public Integer getKey() {
					return key;
				}

				@Override
				public T getValue() {
					return value;
				}

				@Override
				public T setValue(T value) {
					throw new UnsupportedOperationException("Not supported yet.");
				}
			};
		}

		@Override
		public void remove() {
			throw new UnsupportedOperationException("Not supported yet.");
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy