001package squidpony; 002 003import squidpony.squidmath.Coord; 004 005import java.util.Arrays; 006import java.util.Iterator; 007 008/** 009 * Static methods useful to be GWT-compatible, and also methods useful for filling gaps in Java's support for arrays. 010 * You can think of the purpose of this class as "GWT, and Compatibility". There's a replacement for a Math method that 011 * isn't available on GWT, a quick way to get the first element in an Iterable, copying, inserting, and filling methods 012 * for 2D arrays of primitive types (char, int, double, and boolean), and also a method to easily clone a Coord array. 013 * 014 * @author smelC 015 * @author Tommy Ettinger 016 */ 017public class GwtCompatibility { 018 019 /** 020 * Gets an exact copy of an array of Coord. References are shared, which should be the case for all usage of Coord 021 * since they are immutable and thus don't need multiple variants on a Coord from the pool. 022 * @param input an array of Coord to copy 023 * @return A clone of {@code input}. 024 */ 025 public static Coord[] cloneCoords(Coord[] input) { 026 final Coord[] result = new Coord[input.length]; 027 //System.arraycopy, despite being cumbersome, is the fastest way to copy an array on the JVM. 028 System.arraycopy(input, 0, result, 0, input.length); 029 return result; 030 } 031 032 /** 033 * A replacement for Math.IEEEremainder, just because Math.IEEEremainder isn't GWT-compatible. 034 * Gets the remainder of op / d, which can be negative if any parameter is negative. 035 * @param op the operand/dividend 036 * @param d the divisor 037 * @return The remainder of {@code op / d}, as a double; can be negative 038 */ 039 /* smelC: because Math.IEEEremainder isn't GWT compatible */ 040 public static double IEEEremainder(double op, double d) { 041 final double div = Math.round(op / d); 042 return op - (div * d); 043 } 044 045 /** 046 * Gets the first item in an Iterable of T, or null if it is empty. Meant for collections like LinkedHashSet, which 047 * can promise a stable first element but don't provide a way to access it. Not exactly a GWT compatibility method, 048 * but more of a Java standard library stand-in. 049 * @param collection an Iterable of T; if collection is null or empty this returns null 050 * @param <T> any object type 051 * @return the first element in collection, or null if it is empty or null itself 052 */ 053 public static <T> T first(Iterable<T> collection) 054 { 055 if(collection == null) 056 return null; 057 Iterator<T> it = collection.iterator(); 058 if(it.hasNext()) 059 return it.next(); 060 return null; 061 } 062 063 /** 064 * Gets a copy of the 2D char array, source, that has the same data but shares no references with source. 065 * @param source a 2D char array 066 * @return a copy of source, or null if source is null 067 */ 068 public static char[][] copy2D(char[][] source) 069 { 070 if(source == null) 071 return null; 072 if(source.length < 1) 073 return new char[0][0]; 074 char[][] target = new char[source.length][source[0].length]; 075 for (int i = 0; i < source.length && i < target.length; i++) { 076 System.arraycopy(source[i], 0, target[i], 0, source[i].length); 077 } 078 return target; 079 } 080 081 /** 082 * Gets a copy of the 2D double array, source, that has the same data but shares no references with source. 083 * @param source a 2D double array 084 * @return a copy of source, or null if source is null 085 */ 086 public static double[][] copy2D(double[][] source) 087 { 088 if(source == null) 089 return null; 090 if(source.length < 1) 091 return new double[0][0]; 092 double[][] target = new double[source.length][source[0].length]; 093 for (int i = 0; i < source.length && i < target.length; i++) { 094 System.arraycopy(source[i], 0, target[i], 0, source[i].length); 095 } 096 return target; 097 } 098 099 /** 100 * Gets a copy of the 2D int array, source, that has the same data but shares no references with source. 101 * @param source a 2D int array 102 * @return a copy of source, or null if source is null 103 */ 104 public static int[][] copy2D(int[][] source) 105 { 106 if(source == null) 107 return null; 108 if(source.length < 1) 109 return new int[0][0]; 110 int[][] target = new int[source.length][source[0].length]; 111 for (int i = 0; i < source.length && i < target.length; i++) { 112 System.arraycopy(source[i], 0, target[i], 0, source[i].length); 113 } 114 return target; 115 } 116 117 /** 118 * Gets a copy of the 2D boolean array, source, that has the same data but shares no references with source. 119 * @param source a 2D boolean array 120 * @return a copy of source, or null if source is null 121 */ 122 public static boolean[][] copy2D(boolean[][] source) 123 { 124 if(source == null) 125 return null; 126 if(source.length < 1) 127 return new boolean[0][0]; 128 boolean[][] target = new boolean[source.length][source[0].length]; 129 for (int i = 0; i < source.length && i < target.length; i++) { 130 System.arraycopy(source[i], 0, target[i], 0, source[i].length); 131 } 132 return target; 133 } 134 135 /** 136 * Inserts as much of source into target at the given x,y position as target can hold or source can supply. 137 * Modifies target in-place and also returns target for chaining. 138 * Used primarily to place a smaller array into a different position in a larger array, often freshly allocated. 139 * @param source a 2D char array that will be copied and inserted into target 140 * @param target a 2D char array that will be modified by receiving as much of source as it can hold 141 * @param x the x position in target to receive the items from the first cell in source 142 * @param y the y position in target to receive the items from the first cell in source 143 * @return a modified copy of target with source inserted into it at the given position 144 */ 145 public static char[][] insert2D(char[][] source, char[][] target, int x, int y) 146 { 147 if(source == null || target == null) 148 return target; 149 if(source.length < 1 || source[0].length < 1) 150 return copy2D(target); 151 for (int i = 0; i < source.length && x + i < target.length; i++) { 152 System.arraycopy(source[i], 0, target[x + i], y, Math.min(source[i].length, target[x+i].length - y)); 153 } 154 return target; 155 } 156 /** 157 * Inserts as much of source into target at the given x,y position as target can hold or source can supply. 158 * Modifies target in-place and also returns target for chaining. 159 * Used primarily to place a smaller array into a different position in a larger array, often freshly allocated. 160 * @param source a 2D double array that will be copied and inserted into target 161 * @param target a 2D double array that will be modified by receiving as much of source as it can hold 162 * @param x the x position in target to receive the items from the first cell in source 163 * @param y the y position in target to receive the items from the first cell in source 164 * @return a modified copy of target with source inserted into it at the given position 165 */ 166 public static double[][] insert2D(double[][] source, double[][] target, int x, int y) 167 { 168 if(source == null || target == null) 169 return target; 170 if(source.length < 1 || source[0].length < 1) 171 return copy2D(target); 172 for (int i = 0; i < source.length && x + i < target.length; i++) { 173 System.arraycopy(source[i], 0, target[x + i], y, Math.min(source[i].length, target[x+i].length - y)); 174 } 175 return target; 176 } 177 /** 178 * Inserts as much of source into target at the given x,y position as target can hold or source can supply. 179 * Modifies target in-place and also returns target for chaining. 180 * Used primarily to place a smaller array into a different position in a larger array, often freshly allocated. 181 * @param source a 2D int array that will be copied and inserted into target 182 * @param target a 2D int array that will be modified by receiving as much of source as it can hold 183 * @param x the x position in target to receive the items from the first cell in source 184 * @param y the y position in target to receive the items from the first cell in source 185 * @return a modified copy of target with source inserted into it at the given position 186 */ 187 public static int[][] insert2D(int[][] source, int[][] target, int x, int y) 188 { 189 if(source == null || target == null) 190 return target; 191 if(source.length < 1 || source[0].length < 1) 192 return copy2D(target); 193 for (int i = 0; i < source.length && x + i < target.length; i++) { 194 System.arraycopy(source[i], 0, target[x + i], y, Math.min(source[i].length, target[x+i].length - y)); 195 } 196 return target; 197 } 198 /** 199 * Inserts as much of source into target at the given x,y position as target can hold or source can supply. 200 * Modifies target in-place and also returns target for chaining. 201 * Used primarily to place a smaller array into a different position in a larger array, often freshly allocated. 202 * @param source a 2D boolean array that will be copied and inserted into target 203 * @param target a 2D boolean array that will be modified by receiving as much of source as it can hold 204 * @param x the x position in target to receive the items from the first cell in source 205 * @param y the y position in target to receive the items from the first cell in source 206 * @return a modified copy of target with source inserted into it at the given position 207 */ 208 public static boolean[][] insert2D(boolean[][] source, boolean[][] target, int x, int y) 209 { 210 if(source == null || target == null) 211 return target; 212 if(source.length < 1 || source[0].length < 1) 213 return copy2D(target); 214 for (int i = 0; i < source.length && x + i < target.length; i++) { 215 System.arraycopy(source[i], 0, target[x + i], y, Math.min(source[i].length, target[x+i].length - y)); 216 } 217 return target; 218 } 219 220 /** 221 * Creates a 2D array of the given width and height, filled with entirely with the value contents. 222 * @param contents the value to fill the array with 223 * @param width the desired width 224 * @param height the desired height 225 * @return a freshly allocated 2D array of the requested dimensions, filled entirely with contents 226 */ 227 public static char[][] fill2D(char contents, int width, int height) 228 { 229 char[][] next = new char[width][height]; 230 for (int x = 0; x < width; x++) { 231 Arrays.fill(next[x], contents); 232 } 233 return next; 234 } 235 /** 236 * Creates a 2D array of the given width and height, filled with entirely with the value contents. 237 * @param contents the value to fill the array with 238 * @param width the desired width 239 * @param height the desired height 240 * @return a freshly allocated 2D array of the requested dimensions, filled entirely with contents 241 */ 242 public static double[][] fill2D(double contents, int width, int height) 243 { 244 double[][] next = new double[width][height]; 245 for (int x = 0; x < width; x++) { 246 Arrays.fill(next[x], contents); 247 } 248 return next; 249 } 250 /** 251 * Creates a 2D array of the given width and height, filled with entirely with the value contents. 252 * @param contents the value to fill the array with 253 * @param width the desired width 254 * @param height the desired height 255 * @return a freshly allocated 2D array of the requested dimensions, filled entirely with contents 256 */ 257 public static int[][] fill2D(int contents, int width, int height) 258 { 259 int[][] next = new int[width][height]; 260 for (int x = 0; x < width; x++) { 261 Arrays.fill(next[x], contents); 262 } 263 return next; 264 } 265 /** 266 * Creates a 2D array of the given width and height, filled with entirely with the value contents. 267 * @param contents the value to fill the array with 268 * @param width the desired width 269 * @param height the desired height 270 * @return a freshly allocated 2D array of the requested dimensions, filled entirely with contents 271 */ 272 public static boolean[][] fill2D(boolean contents, int width, int height) 273 { 274 boolean[][] next = new boolean[width][height]; 275 if(contents) { 276 for (int x = 0; x < width; x++) { 277 Arrays.fill(next[x], true); 278 } 279 } 280 return next; 281 } 282}