propane 3.4.2-java → 3.8.0-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. checksums.yaml +4 -4
  2. data/.mvn/extensions.xml +1 -1
  3. data/.mvn/wrapper/MavenWrapperDownloader.java +2 -2
  4. data/.mvn/wrapper/maven-wrapper.properties +2 -2
  5. data/.travis.yml +1 -1
  6. data/CHANGELOG.md +9 -1
  7. data/Gemfile +2 -0
  8. data/README.md +7 -10
  9. data/Rakefile +10 -11
  10. data/bin/propane +3 -1
  11. data/lib/propane.rb +4 -2
  12. data/lib/propane/app.rb +5 -1
  13. data/lib/propane/creators/sketch_class.rb +7 -1
  14. data/lib/propane/creators/sketch_factory.rb +4 -2
  15. data/lib/propane/creators/sketch_writer.rb +1 -0
  16. data/lib/propane/helper_methods.rb +22 -23
  17. data/lib/propane/helpers/numeric.rb +2 -0
  18. data/lib/propane/helpers/version_error.rb +1 -0
  19. data/lib/propane/library.rb +5 -1
  20. data/lib/propane/library_loader.rb +2 -0
  21. data/lib/propane/native_folder.rb +10 -9
  22. data/lib/propane/native_loader.rb +3 -0
  23. data/lib/propane/runner.rb +20 -14
  24. data/lib/propane/version.rb +2 -1
  25. data/library/boids/boids.rb +21 -11
  26. data/library/color_group/color_group.rb +2 -0
  27. data/library/control_panel/control_panel.rb +8 -5
  28. data/library/dxf/dxf.rb +2 -0
  29. data/library/file_chooser/chooser.rb +10 -9
  30. data/library/file_chooser/file_chooser.rb +10 -9
  31. data/library/library_proxy/library_proxy.rb +2 -0
  32. data/library/net/net.rb +2 -0
  33. data/library/slider/slider.rb +23 -22
  34. data/library/vector_utils/vector_utils.rb +4 -0
  35. data/library/video_event/video_event.rb +2 -0
  36. data/pom.rb +37 -36
  37. data/pom.xml +7 -7
  38. data/propane.gemspec +13 -9
  39. data/src/main/java/japplemenubar/JAppleMenuBar.java +3 -3
  40. data/src/main/java/monkstone/ColorUtil.java +1 -3
  41. data/src/main/java/monkstone/MathToolModule.java +1 -1
  42. data/src/main/java/monkstone/PropaneLibrary.java +2 -2
  43. data/src/main/java/monkstone/fastmath/DegLutTables.java +111 -0
  44. data/src/main/java/monkstone/fastmath/Deglut.java +6 -56
  45. data/src/main/java/monkstone/filechooser/Chooser.java +1 -1
  46. data/src/main/java/monkstone/noise/Noise.java +116 -0
  47. data/src/main/java/monkstone/noise/NoiseGenerator.java +63 -0
  48. data/src/main/java/monkstone/noise/NoiseMode.java +15 -0
  49. data/src/main/java/monkstone/noise/SimplexNoise.java +137 -103
  50. data/src/main/java/monkstone/noise/ValueNoise.java +170 -0
  51. data/src/main/java/monkstone/slider/CustomHorizontalSlider.java +1 -1
  52. data/src/main/java/monkstone/slider/CustomVerticalSlider.java +1 -1
  53. data/src/main/java/monkstone/slider/SimpleHorizontalSlider.java +1 -1
  54. data/src/main/java/monkstone/slider/SimpleVerticalSlider.java +1 -1
  55. data/src/main/java/monkstone/slider/SliderBar.java +1 -1
  56. data/src/main/java/monkstone/slider/SliderGroup.java +1 -1
  57. data/src/main/java/monkstone/slider/WheelHandler.java +1 -1
  58. data/src/main/java/monkstone/vecmath/package-info.java +1 -1
  59. data/src/main/java/monkstone/vecmath/vec2/Vec2.java +1 -1
  60. data/src/main/java/monkstone/vecmath/vec3/Vec3.java +1 -2
  61. data/src/main/java/monkstone/videoevent/CaptureEvent.java +1 -1
  62. data/src/main/java/monkstone/videoevent/MovieEvent.java +1 -1
  63. data/src/main/java/monkstone/videoevent/package-info.java +1 -1
  64. data/src/main/java/processing/awt/PGraphicsJava2D.java +781 -285
  65. data/src/main/java/processing/awt/PImageAWT.java +377 -0
  66. data/src/main/java/processing/awt/PShapeJava2D.java +56 -52
  67. data/src/main/java/processing/awt/PSurfaceAWT.java +308 -208
  68. data/src/main/java/processing/awt/ShimAWT.java +581 -0
  69. data/src/main/java/processing/core/PApplet.java +13142 -13883
  70. data/src/main/java/processing/core/PConstants.java +477 -447
  71. data/src/main/java/processing/core/PFont.java +914 -880
  72. data/src/main/java/processing/core/PGraphics.java +152 -136
  73. data/src/main/java/processing/core/PImage.java +275 -372
  74. data/src/main/java/processing/core/PMatrix.java +172 -159
  75. data/src/main/java/processing/core/PMatrix2D.java +478 -415
  76. data/src/main/java/processing/core/PMatrix3D.java +762 -735
  77. data/src/main/java/processing/core/PShape.java +2887 -2651
  78. data/src/main/java/processing/core/PShapeOBJ.java +97 -92
  79. data/src/main/java/processing/core/PShapeSVG.java +1705 -1490
  80. data/src/main/java/processing/core/PStyle.java +40 -37
  81. data/src/main/java/processing/core/PSurface.java +139 -97
  82. data/src/main/java/processing/core/PSurfaceNone.java +296 -218
  83. data/src/main/java/processing/core/PVector.java +995 -963
  84. data/src/main/java/processing/core/ThinkDifferent.java +12 -8
  85. data/src/main/java/processing/data/DoubleDict.java +756 -710
  86. data/src/main/java/processing/data/DoubleList.java +749 -696
  87. data/src/main/java/processing/data/FloatDict.java +748 -702
  88. data/src/main/java/processing/data/FloatList.java +751 -697
  89. data/src/main/java/processing/data/IntDict.java +720 -673
  90. data/src/main/java/processing/data/IntList.java +699 -633
  91. data/src/main/java/processing/data/JSONArray.java +931 -873
  92. data/src/main/java/processing/data/JSONObject.java +1262 -1165
  93. data/src/main/java/processing/data/JSONTokener.java +351 -341
  94. data/src/main/java/processing/data/LongDict.java +710 -663
  95. data/src/main/java/processing/data/LongList.java +701 -635
  96. data/src/main/java/processing/data/Sort.java +37 -41
  97. data/src/main/java/processing/data/StringDict.java +525 -486
  98. data/src/main/java/processing/data/StringList.java +626 -580
  99. data/src/main/java/processing/data/Table.java +3690 -3510
  100. data/src/main/java/processing/data/TableRow.java +182 -183
  101. data/src/main/java/processing/data/XML.java +957 -883
  102. data/src/main/java/processing/event/Event.java +87 -67
  103. data/src/main/java/processing/event/KeyEvent.java +48 -41
  104. data/src/main/java/processing/event/MouseEvent.java +88 -113
  105. data/src/main/java/processing/event/TouchEvent.java +10 -6
  106. data/src/main/java/processing/javafx/PGraphicsFX2D.java +20 -345
  107. data/src/main/java/processing/javafx/PSurfaceFX.java +149 -121
  108. data/src/main/java/processing/net/Client.java +20 -20
  109. data/src/main/java/processing/net/Server.java +9 -9
  110. data/src/main/java/processing/opengl/FontTexture.java +286 -266
  111. data/src/main/java/processing/opengl/FrameBuffer.java +389 -377
  112. data/src/main/java/processing/opengl/LinePath.java +132 -89
  113. data/src/main/java/processing/opengl/LineStroker.java +588 -581
  114. data/src/main/java/processing/opengl/PGL.java +660 -567
  115. data/src/main/java/processing/opengl/PGraphics2D.java +408 -315
  116. data/src/main/java/processing/opengl/PGraphics3D.java +107 -72
  117. data/src/main/java/processing/opengl/PGraphicsOpenGL.java +12378 -12075
  118. data/src/main/java/processing/opengl/PJOGL.java +1753 -1670
  119. data/src/main/java/processing/opengl/PShader.java +369 -461
  120. data/src/main/java/processing/opengl/PShapeOpenGL.java +4678 -4580
  121. data/src/main/java/processing/opengl/PSurfaceJOGL.java +1114 -1027
  122. data/src/main/java/processing/opengl/Texture.java +1492 -1401
  123. data/src/main/java/processing/opengl/VertexBuffer.java +57 -55
  124. data/test/create_test.rb +21 -20
  125. data/test/deglut_spec_test.rb +4 -2
  126. data/test/helper_methods_test.rb +49 -20
  127. data/test/math_tool_test.rb +39 -32
  128. data/test/native_folder.rb +47 -0
  129. data/test/respond_to_test.rb +3 -2
  130. data/test/sketches/key_event.rb +2 -2
  131. data/test/sketches/library/my_library/my_library.rb +3 -0
  132. data/test/test_helper.rb +2 -0
  133. data/test/vecmath_spec_test.rb +35 -22
  134. data/vendors/Rakefile +35 -40
  135. metadata +47 -23
  136. data/library/simplex_noise/simplex_noise.rb +0 -3
  137. data/src/main/java/processing/opengl/shaders/LightVert-brcm.glsl +0 -154
  138. data/src/main/java/processing/opengl/shaders/LightVert-vc4.glsl +0 -154
  139. data/src/main/java/processing/opengl/shaders/TexLightVert-brcm.glsl +0 -160
  140. data/src/main/java/processing/opengl/shaders/TexLightVert-vc4.glsl +0 -160
@@ -3,753 +3,800 @@ package processing.data;
3
3
  import java.io.*;
4
4
  import java.util.HashMap;
5
5
  import java.util.Iterator;
6
+ import java.util.NoSuchElementException;
6
7
 
7
8
  import processing.core.PApplet;
8
9
 
10
+
9
11
  /**
10
12
  * A simple class to use a String as a lookup for an int value.
11
13
  *
12
- * @webref data:composite
14
+ * @nowebref
13
15
  * @see FloatDict
14
16
  * @see StringDict
15
17
  */
16
18
  public class LongDict {
17
19
 
18
- /**
19
- * Number of elements in the table
20
- */
21
- protected int count;
22
-
23
- protected String[] keys;
24
- protected long[] values;
25
-
26
- /**
27
- * Internal implementation for faster lookups
28
- */
29
- private HashMap<String, Integer> indices = new HashMap<>();
30
-
31
- public LongDict() {
32
- count = 0;
33
- keys = new String[10];
34
- values = new long[10];
35
- }
36
-
37
- /**
38
- * Create a new lookup with a specific size. This is more efficient than not
39
- * specifying a size. Use it when you know the rough size of the thing
40
- * you're creating.
41
- *
42
- * @nowebref
43
- */
44
- public LongDict(int length) {
45
- count = 0;
46
- keys = new String[length];
47
- values = new long[length];
48
- }
49
-
50
- /**
51
- * Read a set of entries from a Reader that has each key/value pair on a
52
- * single line, separated by a tab.
53
- *
54
- * @nowebref
55
- */
56
- public LongDict(BufferedReader reader) {
57
- String[] lines = PApplet.loadStrings(reader);
58
- keys = new String[lines.length];
59
- values = new long[lines.length];
60
-
61
- for (int i = 0; i < lines.length; i++) {
62
- String[] pieces = PApplet.split(lines[i], '\t');
63
- if (pieces.length == 2) {
64
- keys[count] = pieces[0];
65
- values[count] = PApplet.parseInt(pieces[1]);
66
- indices.put(pieces[0], count);
67
- count++;
68
- }
69
- }
20
+ /** Number of elements in the table */
21
+ protected int count;
22
+
23
+ protected String[] keys;
24
+ protected long[] values;
25
+
26
+ /** Internal implementation for faster lookups */
27
+ private HashMap<String, Integer> indices = new HashMap<>();
28
+
29
+
30
+ public LongDict() {
31
+ count = 0;
32
+ keys = new String[10];
33
+ values = new long[10];
34
+ }
35
+
36
+
37
+ /**
38
+ * Create a new lookup with a specific size. This is more efficient than not
39
+ * specifying a size. Use it when you know the rough size of the thing you're creating.
40
+ *
41
+ * @nowebref
42
+ */
43
+ public LongDict(int length) {
44
+ count = 0;
45
+ keys = new String[length];
46
+ values = new long[length];
47
+ }
48
+
49
+
50
+ /**
51
+ * Read a set of entries from a Reader that has each key/value pair on
52
+ * a single line, separated by a tab.
53
+ *
54
+ * @nowebref
55
+ */
56
+ public LongDict(BufferedReader reader) {
57
+ String[] lines = PApplet.loadStrings(reader);
58
+ keys = new String[lines.length];
59
+ values = new long[lines.length];
60
+
61
+ for (int i = 0; i < lines.length; i++) {
62
+ String[] pieces = PApplet.split(lines[i], '\t');
63
+ if (pieces.length == 2) {
64
+ keys[count] = pieces[0];
65
+ values[count] = PApplet.parseInt(pieces[1]);
66
+ indices.put(pieces[0], count);
67
+ count++;
68
+ }
69
+ }
70
+ }
71
+
72
+ /**
73
+ * @nowebref
74
+ */
75
+ public LongDict(String[] keys, long[] values) {
76
+ if (keys.length != values.length) {
77
+ throw new IllegalArgumentException("key and value arrays must be the same length");
70
78
  }
79
+ this.keys = keys;
80
+ this.values = values;
81
+ count = keys.length;
82
+ for (int i = 0; i < count; i++) {
83
+ indices.put(keys[i], i);
84
+ }
85
+ }
71
86
 
72
- /**
73
- * @nowebref
74
- */
75
- public LongDict(String[] keys, long[] values) {
76
- if (keys.length != values.length) {
77
- throw new IllegalArgumentException("key and value arrays must be the same length");
78
- }
79
- this.keys = keys;
80
- this.values = values;
81
- count = keys.length;
82
- for (int i = 0; i < count; i++) {
83
- indices.put(keys[i], i);
84
- }
85
- }
86
87
 
87
- /**
88
- * Constructor to allow (more intuitive) inline initialization, e.g.:
89
- * <pre>
90
- * new FloatDict(new Object[][] {
91
- * { "key1", 1 },
92
- * { "key2", 2 }
93
- * });
94
- * </pre>
95
- */
96
- public LongDict(Object[][] pairs) {
97
- count = pairs.length;
98
- this.keys = new String[count];
99
- this.values = new long[count];
100
- for (int i = 0; i < count; i++) {
101
- keys[i] = (String) pairs[i][0];
102
- values[i] = (Integer) pairs[i][1];
103
- indices.put(keys[i], i);
104
- }
105
- }
88
+ /**
89
+ * Constructor to allow (more intuitive) inline initialization, e.g.:
90
+ * <pre>
91
+ * new FloatDict(new Object[][] {
92
+ * { "key1", 1 },
93
+ * { "key2", 2 }
94
+ * });
95
+ * </pre>
96
+ */
97
+ public LongDict(Object[][] pairs) {
98
+ count = pairs.length;
99
+ this.keys = new String[count];
100
+ this.values = new long[count];
101
+ for (int i = 0; i < count; i++) {
102
+ keys[i] = (String) pairs[i][0];
103
+ values[i] = (Integer) pairs[i][1];
104
+ indices.put(keys[i], i);
105
+ }
106
+ }
107
+
106
108
 
107
- /**
108
- * Returns the number of key/value pairs
109
- *
110
- * @webref intdict:method
111
- * @brief Returns the number of key/value pairs
112
- */
113
- public int size() {
114
- return count;
115
- }
109
+ /**
110
+ * Returns the number of key/value pairs
111
+ *
112
+ * @webref intdict:method
113
+ * @brief Returns the number of key/value pairs
114
+ */
115
+ public int size() {
116
+ return count;
117
+ }
116
118
 
117
- /**
118
- * Resize the internal data, this can only be used to shrink the list.
119
- * Helpful for situations like sorting and then grabbing the top 50 entries.
120
- */
121
- public void resize(int length) {
122
- if (length > count) {
123
- throw new IllegalArgumentException("resize() can only be used to shrink the dictionary");
124
- }
125
- if (length < 1) {
126
- throw new IllegalArgumentException("resize(" + length + ") is too small, use 1 or higher");
127
- }
128
119
 
129
- String[] newKeys = new String[length];
130
- long[] newValues = new long[length];
131
- PApplet.arrayCopy(keys, newKeys, length);
132
- PApplet.arrayCopy(values, newValues, length);
133
- keys = newKeys;
134
- values = newValues;
135
- count = length;
136
- resetIndices();
137
- }
138
-
139
- /**
140
- * Remove all entries.
141
- *
142
- * @webref intdict:method
143
- * @brief Remove all entries
144
- */
145
- public void clear() {
146
- count = 0;
147
- indices = new HashMap<>();
148
- }
149
-
150
- private void resetIndices() {
151
- indices = new HashMap<>(count);
152
- for (int i = 0; i < count; i++) {
153
- indices.put(keys[i], i);
154
- }
120
+ /**
121
+ * Resize the internal data, this can only be used to shrink the list.
122
+ * Helpful for situations like sorting and then grabbing the top 50 entries.
123
+ */
124
+ public void resize(int length) {
125
+ if (length > count) {
126
+ throw new IllegalArgumentException("resize() can only be used to shrink the dictionary");
127
+ }
128
+ if (length < 1) {
129
+ throw new IllegalArgumentException("resize(" + length + ") is too small, use 1 or higher");
155
130
  }
156
131
 
157
- // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
158
- public class Entry {
132
+ String[] newKeys = new String[length];
133
+ long[] newValues = new long[length];
134
+ PApplet.arrayCopy(keys, newKeys, length);
135
+ PApplet.arrayCopy(values, newValues, length);
136
+ keys = newKeys;
137
+ values = newValues;
138
+ count = length;
139
+ resetIndices();
140
+ }
159
141
 
160
- public String key;
161
- public long value;
162
142
 
163
- Entry(String key, long value) {
164
- this.key = key;
165
- this.value = value;
166
- }
167
- }
143
+ /**
144
+ * Remove all entries.
145
+ *
146
+ * @webref intdict:method
147
+ * @brief Remove all entries
148
+ */
149
+ public void clear() {
150
+ count = 0;
151
+ indices = new HashMap<>();
152
+ }
168
153
 
169
- public Iterable<Entry> entries() {
170
- return new Iterable<Entry>() {
171
154
 
172
- public Iterator<Entry> iterator() {
173
- return entryIterator();
174
- }
175
- };
155
+ private void resetIndices() {
156
+ indices = new HashMap<>(count);
157
+ for (int i = 0; i < count; i++) {
158
+ indices.put(keys[i], i);
176
159
  }
160
+ }
177
161
 
178
- public Iterator<Entry> entryIterator() {
179
- return new Iterator<Entry>() {
180
- int index = -1;
181
162
 
182
- public void remove() {
183
- removeIndex(index);
184
- index--;
185
- }
163
+ // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
186
164
 
187
- public Entry next() {
188
- ++index;
189
- Entry e = new Entry(keys[index], values[index]);
190
- return e;
191
- }
192
165
 
193
- public boolean hasNext() {
194
- return index + 1 < size();
195
- }
196
- };
197
- }
166
+ public class Entry {
167
+ public String key;
168
+ public long value;
198
169
 
199
- // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
200
- public String key(int index) {
201
- return keys[index];
170
+ Entry(String key, long value) {
171
+ this.key = key;
172
+ this.value = value;
202
173
  }
174
+ }
203
175
 
204
- protected void crop() {
205
- if (count != keys.length) {
206
- keys = PApplet.subset(keys, 0, count);
207
- values = PApplet.subset(values, 0, count);
208
- }
209
- }
210
176
 
211
- public Iterable<String> keys() {
212
- return new Iterable<String>() {
177
+ public Iterable<Entry> entries() {
178
+ return new Iterable<Entry>() {
213
179
 
214
- @Override
215
- public Iterator<String> iterator() {
216
- return keyIterator();
217
- }
218
- };
219
- }
180
+ public Iterator<Entry> iterator() {
181
+ return entryIterator();
182
+ }
183
+ };
184
+ }
220
185
 
221
- // Use this to iterate when you want to be able to remove elements along the way
222
- public Iterator<String> keyIterator() {
223
- return new Iterator<String>() {
224
- int index = -1;
225
186
 
226
- public void remove() {
227
- removeIndex(index);
228
- index--;
229
- }
187
+ public Iterator<Entry> entryIterator() {
188
+ return new Iterator<Entry>() {
189
+ int index = -1;
230
190
 
231
- public String next() {
232
- return key(++index);
233
- }
191
+ public void remove() {
192
+ removeIndex(index);
193
+ index--;
194
+ }
234
195
 
235
- public boolean hasNext() {
236
- return index + 1 < size();
237
- }
238
- };
239
- }
196
+ public Entry next() {
197
+ ++index;
198
+ Entry e = new Entry(keys[index], values[index]);
199
+ return e;
200
+ }
240
201
 
241
- /**
242
- * Return a copy of the internal keys array. This array can be modified.
243
- *
244
- * @webref intdict:method
245
- * @brief Return a copy of the internal keys array
246
- */
247
- public String[] keyArray() {
248
- crop();
249
- return keyArray(null);
250
- }
202
+ public boolean hasNext() {
203
+ return index+1 < size();
204
+ }
205
+ };
206
+ }
251
207
 
252
- public String[] keyArray(String[] outgoing) {
253
- if (outgoing == null || outgoing.length != count) {
254
- outgoing = new String[count];
255
- }
256
- System.arraycopy(keys, 0, outgoing, 0, count);
257
- return outgoing;
258
- }
259
-
260
- public long value(int index) {
261
- return values[index];
262
- }
263
-
264
- /**
265
- * @webref intdict:method
266
- * @brief Return the internal array being used to store the values
267
- */
268
- public Iterable<Long> values() {
269
- return new Iterable<Long>() {
270
-
271
- @Override
272
- public Iterator<Long> iterator() {
273
- return valueIterator();
274
- }
275
- };
276
- }
277
-
278
- public Iterator<Long> valueIterator() {
279
- return new Iterator<Long>() {
280
- int index = -1;
281
-
282
- public void remove() {
283
- removeIndex(index);
284
- index--;
285
- }
286
-
287
- public Long next() {
288
- return value(++index);
289
- }
290
-
291
- public boolean hasNext() {
292
- return index + 1 < size();
293
- }
294
- };
295
- }
296
-
297
- /**
298
- * Create a new array and copy each of the values into it.
299
- *
300
- * @webref intdict:method
301
- * @brief Create a new array and copy each of the values into it
302
- */
303
- public int[] valueArray() {
304
- crop();
305
- return valueArray(null);
306
- }
307
-
308
- /**
309
- * Fill an already-allocated array with the values (more efficient than
310
- * creating a new array each time). If 'array' is null, or not the same size
311
- * as the number of values, a new array will be allocated and returned.
312
- *
313
- * @param array values to copy into the array
314
- */
315
- public int[] valueArray(int[] array) {
316
- if (array == null || array.length != size()) {
317
- array = new int[count];
318
- }
319
- System.arraycopy(values, 0, array, 0, count);
320
- return array;
321
- }
322
-
323
- /**
324
- * Return a value for the specified key.
325
- *
326
- * @webref intdict:method
327
- * @brief Return a value for the specified key
328
- */
329
- public long get(String key) {
330
- int index = index(key);
331
- if (index == -1) {
332
- throw new IllegalArgumentException("No key named '" + key + "'");
333
- }
334
- return values[index];
335
- }
336
208
 
337
- public long get(String key, long alternate) {
338
- int index = index(key);
339
- if (index == -1) {
340
- return alternate;
341
- }
342
- return values[index];
343
- }
344
-
345
- /**
346
- * Create a new key/value pair or change the value of one.
347
- *
348
- * @webref intdict:method
349
- * @brief Create a new key/value pair or change the value of one
350
- */
351
- public void set(String key, long amount) {
352
- int index = index(key);
353
- if (index == -1) {
354
- create(key, amount);
355
- } else {
356
- values[index] = amount;
357
- }
358
- }
209
+ // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
359
210
 
360
- public void setIndex(int index, String key, long value) {
361
- if (index < 0 || index >= count) {
362
- throw new ArrayIndexOutOfBoundsException(index);
363
- }
364
- keys[index] = key;
365
- values[index] = value;
366
- }
367
-
368
- /**
369
- * @webref intdict:method
370
- * @brief Check if a key is a part of the data structure
371
- */
372
- public boolean hasKey(String key) {
373
- return index(key) != -1;
374
- }
375
-
376
- /**
377
- * Increase the value associated with a specific key by 1.
378
- *
379
- * @webref intdict:method
380
- * @brief Increase the value of a specific key value by 1
381
- */
382
- public void increment(String key) {
383
- add(key, 1);
384
- }
385
-
386
- /**
387
- * Merge another dictionary into this one. Calling this increment() since it
388
- * doesn't make sense in practice for the other dictionary types, even
389
- * though it's technically an add().
390
- */
391
- public void increment(LongDict dict) {
392
- for (int i = 0; i < dict.count; i++) {
393
- add(dict.key(i), dict.value(i));
394
- }
395
- }
396
211
 
397
- /**
398
- * @webref intdict:method
399
- * @brief Add to a value
400
- */
401
- public void add(String key, long amount) {
402
- int index = index(key);
403
- if (index == -1) {
404
- create(key, amount);
405
- } else {
406
- values[index] += amount;
407
- }
408
- }
212
+ public String key(int index) {
213
+ return keys[index];
214
+ }
409
215
 
410
- /**
411
- * @webref intdict:method
412
- * @brief Subtract from a value
413
- */
414
- public void sub(String key, long amount) {
415
- add(key, -amount);
416
- }
417
216
 
418
- /**
419
- * @webref intdict:method
420
- * @brief Multiply a value
421
- */
422
- public void mult(String key, long amount) {
423
- int index = index(key);
424
- if (index != -1) {
425
- values[index] *= amount;
426
- }
217
+ protected void crop() {
218
+ if (count != keys.length) {
219
+ keys = PApplet.subset(keys, 0, count);
220
+ values = PApplet.subset(values, 0, count);
427
221
  }
222
+ }
428
223
 
429
- /**
430
- * @webref intdict:method
431
- * @brief Divide a value
432
- */
433
- public void div(String key, long amount) {
434
- int index = index(key);
435
- if (index != -1) {
436
- values[index] /= amount;
437
- }
438
- }
439
224
 
440
- private void checkMinMax(String functionName) {
441
- if (count == 0) {
442
- String msg
443
- = String.format("Cannot use %s() on an empty %s.",
444
- functionName, getClass().getSimpleName());
445
- throw new RuntimeException(msg);
446
- }
225
+ public Iterable<String> keys() {
226
+ return new Iterable<String>() {
227
+
228
+ @Override
229
+ public Iterator<String> iterator() {
230
+ return keyIterator();
231
+ }
232
+ };
233
+ }
234
+
235
+
236
+ // Use this to iterate when you want to be able to remove elements along the way
237
+ public Iterator<String> keyIterator() {
238
+ return new Iterator<String>() {
239
+ int index = -1;
240
+
241
+ public void remove() {
242
+ removeIndex(index);
243
+ index--;
244
+ }
245
+
246
+ public String next() {
247
+ return key(++index);
248
+ }
249
+
250
+ public boolean hasNext() {
251
+ return index+1 < size();
252
+ }
253
+ };
254
+ }
255
+
256
+
257
+ /**
258
+ * Return a copy of the internal keys array. This array can be modified.
259
+ *
260
+ * @webref intdict:method
261
+ * @brief Return a copy of the internal keys array
262
+ */
263
+ public String[] keyArray() {
264
+ crop();
265
+ return keyArray(null);
266
+ }
267
+
268
+
269
+ public String[] keyArray(String[] outgoing) {
270
+ if (outgoing == null || outgoing.length != count) {
271
+ outgoing = new String[count];
447
272
  }
273
+ System.arraycopy(keys, 0, outgoing, 0, count);
274
+ return outgoing;
275
+ }
276
+
277
+
278
+ public long value(int index) {
279
+ return values[index];
280
+ }
281
+
282
+
283
+ /**
284
+ * @webref intdict:method
285
+ * @brief Return the internal array being used to store the values
286
+ */
287
+ public Iterable<Long> values() {
288
+ return new Iterable<Long>() {
289
+
290
+ @Override
291
+ public Iterator<Long> iterator() {
292
+ return valueIterator();
293
+ }
294
+ };
295
+ }
296
+
297
+
298
+ public Iterator<Long> valueIterator() {
299
+ return new Iterator<Long>() {
300
+ int index = -1;
448
301
 
449
- // return the index of the minimum value
450
- public int minIndex() {
451
- //checkMinMax("minIndex");
452
- if (count == 0) {
453
- return -1;
454
- }
302
+ public void remove() {
303
+ removeIndex(index);
304
+ index--;
305
+ }
455
306
 
456
- int index = 0;
457
- long value = values[0];
458
- for (int i = 1; i < count; i++) {
459
- if (values[i] < value) {
460
- index = i;
461
- value = values[i];
462
- }
463
- }
464
- return index;
307
+ public Long next() {
308
+ return value(++index);
309
+ }
310
+
311
+ public boolean hasNext() {
312
+ return index+1 < size();
313
+ }
314
+ };
315
+ }
316
+
317
+
318
+ /**
319
+ * Create a new array and copy each of the values into it.
320
+ *
321
+ * @webref intdict:method
322
+ * @brief Create a new array and copy each of the values into it
323
+ */
324
+ public int[] valueArray() {
325
+ crop();
326
+ return valueArray(null);
327
+ }
328
+
329
+
330
+ /**
331
+ * Fill an already-allocated array with the values (more efficient than
332
+ * creating a new array each time). If 'array' is null, or not the same
333
+ * size as the number of values, a new array will be allocated and returned.
334
+ *
335
+ * @param array values to copy into the array
336
+ */
337
+ public int[] valueArray(int[] array) {
338
+ if (array == null || array.length != size()) {
339
+ array = new int[count];
340
+ }
341
+ System.arraycopy(values, 0, array, 0, count);
342
+ return array;
343
+ }
344
+
345
+
346
+ /**
347
+ * Return a value for the specified key.
348
+ *
349
+ * @webref intdict:method
350
+ * @brief Return a value for the specified key
351
+ */
352
+ public long get(String key) {
353
+ int index = index(key);
354
+ if (index == -1) {
355
+ throw new IllegalArgumentException("No key named '" + key + "'");
356
+ }
357
+ return values[index];
358
+ }
359
+
360
+
361
+ public long get(String key, long alternate) {
362
+ int index = index(key);
363
+ if (index == -1) return alternate;
364
+ return values[index];
365
+ }
366
+
367
+
368
+ /**
369
+ * Create a new key/value pair or change the value of one.
370
+ *
371
+ * @webref intdict:method
372
+ * @brief Create a new key/value pair or change the value of one
373
+ */
374
+ public void set(String key, long amount) {
375
+ int index = index(key);
376
+ if (index == -1) {
377
+ create(key, amount);
378
+ } else {
379
+ values[index] = amount;
380
+ }
381
+ }
382
+
383
+
384
+ public void setIndex(int index, String key, long value) {
385
+ if (index < 0 || index >= count) {
386
+ throw new ArrayIndexOutOfBoundsException(index);
387
+ }
388
+ keys[index] = key;
389
+ values[index] = value;
390
+ }
391
+
392
+
393
+ /**
394
+ * @webref intdict:method
395
+ * @brief Check if a key is a part of the data structure
396
+ */
397
+ public boolean hasKey(String key) {
398
+ return index(key) != -1;
399
+ }
400
+
401
+
402
+ /**
403
+ * Increase the value associated with a specific key by 1.
404
+ *
405
+ * @webref intdict:method
406
+ * @brief Increase the value of a specific key value by 1
407
+ */
408
+ public void increment(String key) {
409
+ add(key, 1);
410
+ }
411
+
412
+
413
+ /**
414
+ * Merge another dictionary into this one. Calling this increment()
415
+ * since it doesn't make sense in practice for the other dictionary types,
416
+ * even though it's technically an add().
417
+ */
418
+ public void increment(LongDict dict) {
419
+ for (int i = 0; i < dict.count; i++) {
420
+ add(dict.key(i), dict.value(i));
421
+ }
422
+ }
423
+
424
+
425
+ /**
426
+ * @webref intdict:method
427
+ * @brief Add to a value
428
+ */
429
+ public void add(String key, long amount) {
430
+ int index = index(key);
431
+ if (index == -1) {
432
+ create(key, amount);
433
+ } else {
434
+ values[index] += amount;
435
+ }
436
+ }
437
+
438
+
439
+ /**
440
+ * @webref intdict:method
441
+ * @brief Subtract from a value
442
+ */
443
+ public void sub(String key, long amount) {
444
+ add(key, -amount);
445
+ }
446
+
447
+
448
+ /**
449
+ * @webref intdict:method
450
+ * @brief Multiply a value
451
+ */
452
+ public void mult(String key, long amount) {
453
+ int index = index(key);
454
+ if (index != -1) {
455
+ values[index] *= amount;
465
456
  }
457
+ }
466
458
 
467
- // return the key for the minimum value
468
- public String minKey() {
469
- checkMinMax("minKey");
470
- int index = minIndex();
471
- if (index == -1) {
472
- return null;
473
- }
474
- return keys[index];
459
+
460
+ /**
461
+ * @webref intdict:method
462
+ * @brief Divide a value
463
+ */
464
+ public void div(String key, long amount) {
465
+ int index = index(key);
466
+ if (index != -1) {
467
+ values[index] /= amount;
475
468
  }
469
+ }
470
+
476
471
 
477
- // return the minimum value, or throw an error if there are no values
478
- public long minValue() {
479
- checkMinMax("minValue");
480
- return values[minIndex()];
472
+ private void checkMinMax(String functionName) {
473
+ if (count == 0) {
474
+ String msg =
475
+ String.format("Cannot use %s() on an empty %s.",
476
+ functionName, getClass().getSimpleName());
477
+ throw new RuntimeException(msg);
481
478
  }
479
+ }
482
480
 
483
- // return the index of the max value
484
- public int maxIndex() {
485
- //checkMinMax("maxIndex");
486
- if (count == 0) {
487
- return -1;
488
- }
489
- int index = 0;
490
- long value = values[0];
491
- for (int i = 1; i < count; i++) {
492
- if (values[i] > value) {
493
- index = i;
494
- value = values[i];
495
- }
496
- }
497
- return index;
481
+
482
+ // return the index of the minimum value
483
+ public int minIndex() {
484
+ //checkMinMax("minIndex");
485
+ if (count == 0) return -1;
486
+
487
+ int index = 0;
488
+ long value = values[0];
489
+ for (int i = 1; i < count; i++) {
490
+ if (values[i] < value) {
491
+ index = i;
492
+ value = values[i];
493
+ }
498
494
  }
495
+ return index;
496
+ }
499
497
 
500
- /**
501
- * return the key corresponding to the maximum value or null if no entries
502
- */
503
- public String maxKey() {
504
- //checkMinMax("maxKey");
505
- int index = maxIndex();
506
- if (index == -1) {
507
- return null;
508
- }
509
- return keys[index];
498
+
499
+ // return the key for the minimum value
500
+ public String minKey() {
501
+ checkMinMax("minKey");
502
+ int index = minIndex();
503
+ if (index == -1) {
504
+ return null;
510
505
  }
506
+ return keys[index];
507
+ }
508
+
509
+
510
+ // return the minimum value, or throw an error if there are no values
511
+ public long minValue() {
512
+ checkMinMax("minValue");
513
+ return values[minIndex()];
514
+ }
515
+
511
516
 
512
- // return the maximum value or throw an error if zero length
513
- public long maxValue() {
514
- checkMinMax("maxIndex");
515
- return values[maxIndex()];
517
+ // return the index of the max value
518
+ public int maxIndex() {
519
+ //checkMinMax("maxIndex");
520
+ if (count == 0) {
521
+ return -1;
516
522
  }
523
+ int index = 0;
524
+ long value = values[0];
525
+ for (int i = 1; i < count; i++) {
526
+ if (values[i] > value) {
527
+ index = i;
528
+ value = values[i];
529
+ }
530
+ }
531
+ return index;
532
+ }
517
533
 
518
- public long sum() {
519
- long sum = 0;
520
- for (int i = 0; i < count; i++) {
521
- sum += values[i];
522
- }
523
- return sum;
534
+
535
+ /** return the key corresponding to the maximum value or null if no entries */
536
+ public String maxKey() {
537
+ //checkMinMax("maxKey");
538
+ int index = maxIndex();
539
+ if (index == -1) {
540
+ return null;
524
541
  }
542
+ return keys[index];
543
+ }
544
+
525
545
 
526
- public int index(String what) {
527
- Integer found = indices.get(what);
528
- return (found == null) ? -1 : found.intValue();
546
+ // return the maximum value or throw an error if zero length
547
+ public long maxValue() {
548
+ checkMinMax("maxIndex");
549
+ return values[maxIndex()];
550
+ }
551
+
552
+
553
+ public long sum() {
554
+ long sum = 0;
555
+ for (int i = 0; i < count; i++) {
556
+ sum += values[i];
529
557
  }
558
+ return sum;
559
+ }
530
560
 
531
- protected void create(String what, long much) {
532
- if (count == keys.length) {
533
- keys = PApplet.expand(keys);
534
- values = PApplet.expand(values);
535
- }
536
- indices.put(what, Integer.valueOf(count));
537
- keys[count] = what;
538
- values[count] = much;
539
- count++;
561
+
562
+ public int index(String what) {
563
+ Integer found = indices.get(what);
564
+ return (found == null) ? -1 : found.intValue();
565
+ }
566
+
567
+
568
+ protected void create(String what, long much) {
569
+ if (count == keys.length) {
570
+ keys = PApplet.expand(keys);
571
+ values = PApplet.expand(values);
540
572
  }
573
+ indices.put(what, Integer.valueOf(count));
574
+ keys[count] = what;
575
+ values[count] = much;
576
+ count++;
577
+ }
541
578
 
542
- /**
543
- * @webref intdict:method
544
- * @brief Remove a key/value pair
545
- */
546
- public int remove(String key) {
547
- int index = index(key);
548
- if (index != -1) {
549
- removeIndex(index);
550
- }
551
- return index;
579
+
580
+ /**
581
+ * @webref intdict:method
582
+ * @brief Remove a key/value pair
583
+ */
584
+ public long remove(String key) {
585
+ int index = index(key);
586
+ if (index == -1) {
587
+ throw new NoSuchElementException("'" + key + "' not found");
552
588
  }
589
+ long value = values[index];
590
+ removeIndex(index);
591
+ return value;
592
+ }
553
593
 
554
- public String removeIndex(int index) {
555
- if (index < 0 || index >= count) {
556
- throw new ArrayIndexOutOfBoundsException(index);
557
- }
558
- //System.out.println("index is " + which + " and " + keys[which]);
559
- String key = keys[index];
560
- indices.remove(keys[index]);
561
- for (int i = index; i < count - 1; i++) {
562
- keys[i] = keys[i + 1];
563
- values[i] = values[i + 1];
564
- indices.put(keys[i], i);
565
- }
566
- count--;
567
- keys[count] = null;
568
- values[count] = 0;
569
- return key;
594
+
595
+ public long removeIndex(int index) {
596
+ if (index < 0 || index >= count) {
597
+ throw new ArrayIndexOutOfBoundsException(index);
598
+ }
599
+ long value = values[index];
600
+ indices.remove(keys[index]);
601
+ for (int i = index; i < count-1; i++) {
602
+ keys[i] = keys[i+1];
603
+ values[i] = values[i+1];
604
+ indices.put(keys[i], i);
570
605
  }
606
+ count--;
607
+ keys[count] = null;
608
+ values[count] = 0;
609
+ return value;
610
+ }
571
611
 
572
- public void swap(int a, int b) {
573
- String tkey = keys[a];
574
- long tvalue = values[a];
575
- keys[a] = keys[b];
576
- values[a] = values[b];
577
- keys[b] = tkey;
578
- values[b] = tvalue;
612
+
613
+ public void swap(int a, int b) {
614
+ String tkey = keys[a];
615
+ long tvalue = values[a];
616
+ keys[a] = keys[b];
617
+ values[a] = values[b];
618
+ keys[b] = tkey;
619
+ values[b] = tvalue;
579
620
 
580
621
  // indices.put(keys[a], Integer.valueOf(a));
581
622
  // indices.put(keys[b], Integer.valueOf(b));
582
- }
583
-
584
- /**
585
- * Sort the keys alphabetically (ignoring case). Uses the value as a
586
- * tie-breaker (only really possible with a key that has a case change).
587
- *
588
- * @webref intdict:method
589
- * @brief Sort the keys alphabetically
590
- */
591
- public void sortKeys() {
592
- sortImpl(true, false, true);
593
- }
594
-
595
- /**
596
- * Sort the keys alphabetically in reverse (ignoring case). Uses the value
597
- * as a tie-breaker (only really possible with a key that has a case
598
- * change).
599
- *
600
- * @webref intdict:method
601
- * @brief Sort the keys alphabetically in reverse
602
- */
603
- public void sortKeysReverse() {
604
- sortImpl(true, true, true);
605
- }
606
-
607
- /**
608
- * Sort by values in ascending order. The smallest value will be at [0].
609
- *
610
- * @webref intdict:method
611
- * @brief Sort by values in ascending order
612
- */
613
- public void sortValues() {
614
- sortValues(true);
615
- }
616
-
617
- /**
618
- * Set true to ensure that the order returned is identical. Slightly slower
619
- * because the tie-breaker for identical values compares the keys.
620
- *
621
- * @param stable
622
- */
623
- public void sortValues(boolean stable) {
624
- sortImpl(false, false, stable);
625
- }
626
-
627
- /**
628
- * Sort by values in descending order. The largest value will be at [0].
629
- *
630
- * @webref intdict:method
631
- * @brief Sort by values in descending order
632
- */
633
- public void sortValuesReverse() {
634
- sortValuesReverse(true);
635
- }
636
-
637
- public void sortValuesReverse(boolean stable) {
638
- sortImpl(false, true, stable);
639
- }
640
-
641
- protected void sortImpl(final boolean useKeys, final boolean reverse,
642
- final boolean stable) {
643
- Sort s = new Sort() {
644
- @Override
645
- public int size() {
646
- return count;
647
- }
648
-
649
- @Override
650
- public int compare(int a, int b) {
651
- long diff = 0;
652
- if (useKeys) {
653
- diff = keys[a].compareToIgnoreCase(keys[b]);
654
- if (diff == 0) {
655
- diff = values[a] - values[b];
656
- }
657
- } else { // sort values
658
- diff = values[a] - values[b];
659
- if (diff == 0 && stable) {
660
- diff = keys[a].compareToIgnoreCase(keys[b]);
661
- }
662
- }
663
- if (diff == 0) {
664
- return 0;
665
- } else if (reverse) {
666
- return diff < 0 ? 1 : -1;
667
- } else {
668
- return diff < 0 ? -1 : 1;
669
- }
670
- }
671
-
672
- @Override
673
- public void swap(int a, int b) {
674
- LongDict.this.swap(a, b);
675
- }
676
- };
677
- s.run();
678
-
679
- // Set the indices after sort/swaps (performance fix 160411)
680
- resetIndices();
681
- }
682
-
683
- /**
684
- * Sum all of the values in this dictionary, then return a new FloatDict of
685
- * each key, divided by the total sum. The total for all values will be
686
- * ~1.0.
687
- *
688
- * @return an IntDict with the original keys, mapped to their pct of the
689
- * total
690
- */
691
- public FloatDict getPercent() {
692
- double sum = sum(); // a little more accuracy
693
- FloatDict outgoing = new FloatDict();
694
- for (int i = 0; i < size(); i++) {
695
- double percent = value(i) / sum;
696
- outgoing.set(key(i), (float) percent);
697
- }
698
- return outgoing;
699
- }
700
-
701
- /**
702
- * Returns a duplicate copy of this object.
703
- */
704
- public LongDict copy() {
705
- LongDict outgoing = new LongDict(count);
706
- System.arraycopy(keys, 0, outgoing.keys, 0, count);
707
- System.arraycopy(values, 0, outgoing.values, 0, count);
708
- for (int i = 0; i < count; i++) {
709
- outgoing.indices.put(keys[i], i);
623
+ }
624
+
625
+
626
+ /**
627
+ * Sort the keys alphabetically (ignoring case). Uses the value as a
628
+ * tie-breaker (only really possible with a key that has a case change).
629
+ *
630
+ * @webref intdict:method
631
+ * @brief Sort the keys alphabetically
632
+ */
633
+ public void sortKeys() {
634
+ sortImpl(true, false, true);
635
+ }
636
+
637
+ /**
638
+ * Sort the keys alphabetically in reverse (ignoring case). Uses the value as a
639
+ * tie-breaker (only really possible with a key that has a case change).
640
+ *
641
+ * @webref intdict:method
642
+ * @brief Sort the keys alphabetically in reverse
643
+ */
644
+ public void sortKeysReverse() {
645
+ sortImpl(true, true, true);
646
+ }
647
+
648
+
649
+ /**
650
+ * Sort by values in ascending order. The smallest value will be at [0].
651
+ *
652
+ * @webref intdict:method
653
+ * @brief Sort by values in ascending order
654
+ */
655
+ public void sortValues() {
656
+ sortValues(true);
657
+ }
658
+
659
+
660
+ /**
661
+ * Set true to ensure that the order returned is identical. Slightly
662
+ * slower because the tie-breaker for identical values compares the keys.
663
+ * @param stable
664
+ */
665
+ public void sortValues(boolean stable) {
666
+ sortImpl(false, false, stable);
667
+ }
668
+
669
+
670
+ /**
671
+ * Sort by values in descending order. The largest value will be at [0].
672
+ *
673
+ * @webref intdict:method
674
+ * @brief Sort by values in descending order
675
+ */
676
+ public void sortValuesReverse() {
677
+ sortValuesReverse(true);
678
+ }
679
+
680
+
681
+ public void sortValuesReverse(boolean stable) {
682
+ sortImpl(false, true, stable);
683
+ }
684
+
685
+
686
+ protected void sortImpl(final boolean useKeys, final boolean reverse,
687
+ final boolean stable) {
688
+ Sort s = new Sort() {
689
+ @Override
690
+ public int size() {
691
+ return count;
692
+ }
693
+
694
+ @Override
695
+ public int compare(int a, int b) {
696
+ long diff = 0;
697
+ if (useKeys) {
698
+ diff = keys[a].compareToIgnoreCase(keys[b]);
699
+ if (diff == 0) {
700
+ diff = values[a] - values[b];
701
+ }
702
+ } else { // sort values
703
+ diff = values[a] - values[b];
704
+ if (diff == 0 && stable) {
705
+ diff = keys[a].compareToIgnoreCase(keys[b]);
706
+ }
707
+ }
708
+ if (diff == 0) {
709
+ return 0;
710
+ } else if (reverse) {
711
+ return diff < 0 ? 1 : -1;
712
+ } else {
713
+ return diff < 0 ? -1 : 1;
710
714
  }
711
- outgoing.count = count;
712
- return outgoing;
713
- }
715
+ }
714
716
 
715
- public void print() {
716
- for (int i = 0; i < size(); i++) {
717
- System.out.println(keys[i] + " = " + values[i]);
718
- }
717
+ @Override
718
+ public void swap(int a, int b) {
719
+ LongDict.this.swap(a, b);
720
+ }
721
+ };
722
+ s.run();
723
+
724
+ // Set the indices after sort/swaps (performance fix 160411)
725
+ resetIndices();
726
+ }
727
+
728
+
729
+ /**
730
+ * Sum all of the values in this dictionary, then return a new FloatDict of
731
+ * each key, divided by the total sum. The total for all values will be ~1.0.
732
+ * @return an IntDict with the original keys, mapped to their pct of the total
733
+ */
734
+ public FloatDict getPercent() {
735
+ double sum = sum(); // a little more accuracy
736
+ FloatDict outgoing = new FloatDict();
737
+ for (int i = 0; i < size(); i++) {
738
+ double percent = value(i) / sum;
739
+ outgoing.set(key(i), (float) percent);
719
740
  }
741
+ return outgoing;
742
+ }
743
+
720
744
 
721
- /**
722
- * Save tab-delimited entries to a file (TSV format, UTF-8 encoding)
723
- */
724
- public void save(File file) {
725
- PrintWriter writer = PApplet.createWriter(file);
726
- write(writer);
727
- writer.close();
745
+ /** Returns a duplicate copy of this object. */
746
+ public LongDict copy() {
747
+ LongDict outgoing = new LongDict(count);
748
+ System.arraycopy(keys, 0, outgoing.keys, 0, count);
749
+ System.arraycopy(values, 0, outgoing.values, 0, count);
750
+ for (int i = 0; i < count; i++) {
751
+ outgoing.indices.put(keys[i], i);
728
752
  }
753
+ outgoing.count = count;
754
+ return outgoing;
755
+ }
729
756
 
730
- /**
731
- * Write tab-delimited entries to a PrintWriter
732
- */
733
- public void write(PrintWriter writer) {
734
- for (int i = 0; i < count; i++) {
735
- writer.println(keys[i] + "\t" + values[i]);
736
- }
737
- writer.flush();
757
+
758
+ public void print() {
759
+ for (int i = 0; i < size(); i++) {
760
+ System.out.println(keys[i] + " = " + values[i]);
738
761
  }
762
+ }
739
763
 
740
- /**
741
- * Return this dictionary as a String in JSON format.
742
- */
743
- public String toJSON() {
744
- StringList items = new StringList();
745
- for (int i = 0; i < count; i++) {
746
- items.append(JSONObject.quote(keys[i]) + ": " + values[i]);
747
- }
748
- return "{ " + items.join(", ") + " }";
764
+
765
+ /**
766
+ * Save tab-delimited entries to a file (TSV format, UTF-8 encoding)
767
+ */
768
+ public void save(File file) {
769
+ PrintWriter writer = PApplet.createWriter(file);
770
+ write(writer);
771
+ writer.close();
772
+ }
773
+
774
+
775
+ /**
776
+ * Write tab-delimited entries to a PrintWriter
777
+ */
778
+ public void write(PrintWriter writer) {
779
+ for (int i = 0; i < count; i++) {
780
+ writer.println(keys[i] + "\t" + values[i]);
749
781
  }
782
+ writer.flush();
783
+ }
750
784
 
751
- @Override
752
- public String toString() {
753
- return getClass().getSimpleName() + " size=" + size() + " " + toJSON();
785
+
786
+ /**
787
+ * Return this dictionary as a String in JSON format.
788
+ */
789
+ public String toJSON() {
790
+ StringList items = new StringList();
791
+ for (int i = 0; i < count; i++) {
792
+ items.append(JSONObject.quote(keys[i])+ ": " + values[i]);
754
793
  }
794
+ return "{ " + items.join(", ") + " }";
795
+ }
796
+
797
+
798
+ @Override
799
+ public String toString() {
800
+ return getClass().getSimpleName() + " size=" + size() + " " + toJSON();
801
+ }
755
802
  }