View Javadoc
1   package io.jawk.jrt;
2   
3   /*-
4    * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
5    * Jawk
6    * ჻჻჻჻჻჻
7    * Copyright (C) 2006 - 2026 MetricsHub
8    * ჻჻჻჻჻჻
9    * This program is free software: you can redistribute it and/or modify
10   * it under the terms of the GNU Lesser General Public License as
11   * published by the Free Software Foundation, either version 3 of the
12   * License, or (at your option) any later version.
13   *
14   * This program is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   * GNU General Lesser Public License for more details.
18   *
19   * You should have received a copy of the GNU General Lesser Public
20   * License along with this program.  If not, see
21   * <http://www.gnu.org/licenses/lgpl-3.0.html>.
22   * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
23   */
24  
25  import java.util.HashMap;
26  
27  /**
28   * An AWK associative array backed by a {@link HashMap}.
29   * <p>
30   * Keys are not kept in any particular order. This is the default implementation
31   * used when sorted keys are not required.
32   * </p>
33   *
34   * @author MetricsHub
35   */
36  public class HashAssocArray extends HashMap<Object, Object> implements AssocArray {
37  
38  	private static final long serialVersionUID = 1L;
39  
40  	/**
41  	 * Creates an empty associative array.
42  	 */
43  	public HashAssocArray() {
44  		// An AWK array starts out empty; keys are created on first access.
45  	}
46  
47  	/**
48  	 * Returns the value to which the specified key is mapped, normalizing the key
49  	 * first. If the key does not exist, a blank ({@link io.jawk.intermediate.UninitializedObject})
50  	 * is inserted and returned, as required by AWK semantics.
51  	 *
52  	 * @param key the key whose associated value is to be returned
53  	 * @return the value associated with the key, or a blank value if not found
54  	 */
55  	@Override
56  	public Object get(Object key) {
57  		key = AssocArray.normalizeKey(key);
58  		Object result = super.get(key);
59  		if (result != null) {
60  			return result;
61  		}
62  		Long lKey = AssocArray.toLongKey(key);
63  		if (lKey != null) {
64  			result = super.get(lKey);
65  			if (result != null) {
66  				return result;
67  			}
68  			key = lKey;
69  		}
70  		result = UNTYPED;
71  		super.put(key, result);
72  		return result;
73  	}
74  
75  	/**
76  	 * Associates the specified value with the specified key, normalizing the key
77  	 * to a {@code Long} when the key is a valid integer string.
78  	 *
79  	 * @param key the key
80  	 * @param value the value
81  	 * @return the previous value associated with the key, or {@code null}
82  	 */
83  	@Override
84  	public Object put(Object key, Object value) {
85  		key = AssocArray.normalizeKey(key);
86  		Long lKey = AssocArray.toLongKey(key);
87  		// null has no meaning in an AWK array: store the untyped marker so
88  		// callers never have to special-case it
89  		return super.put(lKey != null ? lKey : key, value == null ? UNTYPED : value);
90  	}
91  
92  	/**
93  	 * Removes the mapping for the specified key, trying both the original and its
94  	 * {@code Long} equivalent.
95  	 *
96  	 * @param key the key whose mapping is to be removed
97  	 * @return the previous value associated with the key, or {@code null}
98  	 */
99  	@Override
100 	public Object remove(Object key) {
101 		key = AssocArray.normalizeKey(key);
102 		Object result = super.remove(key);
103 		if (result != null) {
104 			return result;
105 		}
106 		Long lKey = AssocArray.toLongKey(key);
107 		return lKey != null ? super.remove(lKey) : null;
108 	}
109 
110 	/**
111 	 * Returns the specification version of the underlying {@link HashMap} class.
112 	 *
113 	 * @return the specification version string, or {@code null} if unavailable
114 	 */
115 	@Override
116 	public String getMapVersion() {
117 		return HashMap.class.getPackage().getSpecificationVersion();
118 	}
119 
120 	/**
121 	 * {@inheritDoc}
122 	 *
123 	 * @throws AwkRuntimeException always, to prevent accidental use of
124 	 *         {@link HashMap#toString()} in an AWK evaluation
125 	 *         context
126 	 */
127 	@Override
128 	public String toString() {
129 		throw new AwkRuntimeException("Attempting to use an array in a scalar context.");
130 	}
131 }