picrate 0.8.0-java → 0.9.0-java

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,388 @@
1
+ /* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2
+
3
+ /*
4
+ * RawDXF - Code to write DXF files with beginRaw/endRaw
5
+ * An extension for the Processing project - http://processing.org
6
+ * <p/>
7
+ * This library is free software; you can redistribute it and/or
8
+ * modify it under the terms of the GNU Lesser General Public
9
+ * License as published by the Free Software Foundation; either
10
+ * version 2.1 of the License, or (at your option) any later version.
11
+ * <p/>
12
+ * This library is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
+ * Lesser General Public License for more details.
16
+ * <p/>
17
+ * You should have received a copy of the GNU Lesser General
18
+ * Public License along with the Processing project; if not,
19
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
20
+ * Suite 330, Boston, MA 02111-1307 USA
21
+ */
22
+ package processing.dxf;
23
+
24
+ import java.io.File;
25
+ import java.io.FileWriter;
26
+ import java.io.IOException;
27
+ import java.io.PrintWriter;
28
+ import processing.core.PGraphics;
29
+
30
+ /**
31
+ * A simple library to write DXF files with Processing. Because this is used
32
+ * with beginRaw() and endRaw(), only individual triangles and (discontinuous)
33
+ * line segments will be written to the file.
34
+ * <p>
35
+ * Use something like a keyPressed() in PApplet to trigger it, to avoid writing
36
+ * a bazillion .dxf files.
37
+ * <p>
38
+ * Usually, the file will be saved to the sketch's folder. Use Sketch &rarr;
39
+ * Show Sketch Folder to see it from the PDE.
40
+ * <p>
41
+ * A simple example of how to use:
42
+ * <PRE>
43
+ * import processing.dxf.*;
44
+ *
45
+ * boolean record;
46
+ *
47
+ * void setup() {
48
+ * size(500, 500, P3D);
49
+ * }
50
+ *
51
+ * void keyPressed() {
52
+ * // use a key press so that it doesn't make a million files
53
+ * if (key == 'r') record = true;
54
+ * }
55
+ *
56
+ * void draw() {
57
+ * if (record) {
58
+ * beginRaw(DXF, "output.dxf");
59
+ * }
60
+ *
61
+ * // do all your drawing here
62
+ *
63
+ * if (record) {
64
+ * endRaw();
65
+ * record = false;
66
+ * }
67
+ * }
68
+ * </PRE> or to use it and be able to control the current layer:
69
+ * <PRE>
70
+ * import processing.dxf.*;
71
+ *
72
+ * boolean record;
73
+ * RawDXF dxf;
74
+ *
75
+ * void setup() {
76
+ * size(500, 500, P3D);
77
+ * }
78
+ *
79
+ * void keyPressed() {
80
+ * // use a key press so that it doesn't make a million files
81
+ * if (key == 'r') record = true;
82
+ * }
83
+ *
84
+ * void draw() {
85
+ * if (record) {
86
+ * dxf = (RawDXF) createGraphics(width, height, DXF, "output.dxf");
87
+ * beginRaw(dxf);
88
+ * }
89
+ *
90
+ * // do all your drawing here, and to set the layer, call:
91
+ * // if (record) {
92
+ * // dxf.setLayer(num);
93
+ * // }
94
+ * // where 'num' is an integer.
95
+ * // the default is zero, or you can set it to whatever.
96
+ *
97
+ * if (record) {
98
+ * endRaw();
99
+ * record = false;
100
+ * dxf = null;
101
+ * }
102
+ * }
103
+ * </PRE> Note that even though this class is a subclass of PGraphics, it only
104
+ * implements the parts of the API that are necessary for beginRaw/endRaw.
105
+ * <p>
106
+ * Based on the original DXF writer from Simon Greenwold, February 2004. Updated
107
+ * for Processing 0070 by Ben Fry in September 2004, and again for Processing
108
+ * beta in April 2005. Rewritten to support beginRaw/endRaw by Ben Fry in
109
+ * February 2006. Updated again for inclusion as a core library in March 2006.
110
+ * Constructor modifications in September 2008 as we approach 1.0.
111
+ */
112
+ public class RawDXF extends PGraphics {
113
+
114
+ File file;
115
+ PrintWriter writer;
116
+ int currentLayer;
117
+
118
+ public RawDXF() {
119
+ }
120
+
121
+ @Override
122
+ public void setPath(String path) {
123
+ this.path = path;
124
+ if (path != null) {
125
+ file = new File(path);
126
+ if (!file.isAbsolute()) {
127
+ file = null;
128
+ }
129
+ }
130
+ if (file == null) {
131
+ throw new RuntimeException("DXF export requires an absolute path "
132
+ + "for the location of the output file.");
133
+ }
134
+ }
135
+
136
+ // ..............................................................
137
+ protected void allocate() {
138
+ /*
139
+ for (int i = 0; i < MAX_TRI_LAYERS; i++) {
140
+ layerList[i] = NO_LAYER;
141
+ }
142
+ */
143
+ setLayer(0);
144
+ }
145
+
146
+ @Override
147
+ public void dispose() {
148
+ writeFooter();
149
+
150
+ writer.flush();
151
+ writer.close();
152
+ writer = null;
153
+ }
154
+
155
+ @Override
156
+ public boolean displayable() {
157
+ return false; // just in case someone wants to use this on its own
158
+ }
159
+
160
+ @Override
161
+ public boolean is2D() {
162
+ return false;
163
+ }
164
+
165
+ @Override
166
+ public boolean is3D() {
167
+ return true;
168
+ }
169
+
170
+ // ..............................................................
171
+ @Override
172
+ public void beginDraw() {
173
+ // have to create file object here, because the name isn't yet
174
+ // available in allocate()
175
+ if (writer == null) {
176
+ try {
177
+ writer = new PrintWriter(new FileWriter(file));
178
+ } catch (IOException e) {
179
+ throw new RuntimeException(e); // java 1.4+
180
+ }
181
+ writeHeader();
182
+ }
183
+ }
184
+
185
+ @Override
186
+ public void endDraw() {
187
+ writer.flush();
188
+ }
189
+
190
+ // ..............................................................
191
+ /**
192
+ * Set the current layer being used in the DXF file.The default is zero.
193
+ *
194
+ * @param layer
195
+ */
196
+ public void setLayer(int layer) {
197
+ currentLayer = layer;
198
+ }
199
+
200
+ // ..............................................................
201
+ private void writeHeader() {
202
+ writer.println("0");
203
+ writer.println("SECTION");
204
+ writer.println("2");
205
+ writer.println("ENTITIES");
206
+ }
207
+
208
+ private void writeFooter() {
209
+ writer.println("0");
210
+ writer.println("ENDSEC");
211
+ writer.println("0");
212
+ writer.println("EOF");
213
+ }
214
+
215
+ /**
216
+ * Write a command on one line (as a String), then start a new line and
217
+ * write out a formatted float.Available for anyone who wants to insert
218
+ * additional commands into the DXF stream.
219
+ *
220
+ * @param cmd
221
+ * @param val
222
+ */
223
+ public void write(String cmd, float val) {
224
+ writer.println(cmd);
225
+ // Don't number format, will cause trouble on systems that aren't en-US
226
+ // http://dev.processing.org/bugs/show_bug.cgi?id=495
227
+ writer.println(val);
228
+ }
229
+
230
+ /**
231
+ * Write a line to the dxf file.Available for anyone who wants to insert
232
+ * additional commands into the DXF stream.
233
+ *
234
+ * @param what
235
+ */
236
+ public void println(String what) {
237
+ writer.println(what);
238
+ }
239
+
240
+ protected void writeLine(int index1, int index2) {
241
+ writer.println("0");
242
+ writer.println("LINE");
243
+
244
+ // write out the layer
245
+ writer.println("8");
246
+ writer.println(String.valueOf(currentLayer));
247
+
248
+ write("10", vertices[index1][X]);
249
+ write("20", vertices[index1][Y]);
250
+ write("30", vertices[index1][Z]);
251
+
252
+ write("11", vertices[index2][X]);
253
+ write("21", vertices[index2][Y]);
254
+ write("31", vertices[index2][Z]);
255
+ }
256
+
257
+
258
+ /*
259
+ protected void writeLineStrip() {
260
+ writeLine();
261
+ // shift the last vertex to be the first vertex
262
+ System.arraycopy(vertices[1], 0, vertices[0], 0, vertices[1].length);
263
+ vertexCount = 1;
264
+ }
265
+ */
266
+ protected void writeTriangle() {
267
+ writer.println("0");
268
+ writer.println("3DFACE");
269
+
270
+ // write out the layer
271
+ writer.println("8");
272
+ /*
273
+ if (i < MAX_TRI_LAYERS) {
274
+ if (layerList[i] >= 0) {
275
+ currentLayer = layerList[i];
276
+ }
277
+ }
278
+ */
279
+ writer.println(String.valueOf(currentLayer));
280
+
281
+ write("10", vertices[0][X]);
282
+ write("20", vertices[0][Y]);
283
+ write("30", vertices[0][Z]);
284
+
285
+ write("11", vertices[1][X]);
286
+ write("21", vertices[1][Y]);
287
+ write("31", vertices[1][Z]);
288
+
289
+ write("12", vertices[2][X]);
290
+ write("22", vertices[2][Y]);
291
+ write("32", vertices[2][Z]);
292
+
293
+ // Without adding EPSILON, Rhino kinda freaks out.
294
+ // A face is actually a quad, not a triangle,
295
+ // so instead kinda fudging the final point here.
296
+ write("13", vertices[2][X] + EPSILON);
297
+ write("23", vertices[2][Y] + EPSILON);
298
+ write("33", vertices[2][Z] + EPSILON);
299
+
300
+ vertexCount = 0;
301
+ }
302
+
303
+ // ..............................................................
304
+ @Override
305
+ public void beginShape(int kind) {
306
+ shape = kind;
307
+
308
+ if ((shape != LINES)
309
+ && (shape != TRIANGLES)
310
+ && (shape != POLYGON)) {
311
+ String err
312
+ = "RawDXF can only be used with beginRaw(), "
313
+ + "because it only supports lines and triangles";
314
+ throw new RuntimeException(err);
315
+ }
316
+
317
+ if ((shape == POLYGON) && fill) {
318
+ throw new RuntimeException("DXF Export only supports non-filled shapes.");
319
+ }
320
+
321
+ vertexCount = 0;
322
+ }
323
+
324
+ @Override
325
+ public void vertex(float x, float y) {
326
+ vertex(x, y, 0);
327
+ }
328
+
329
+ @Override
330
+ public void vertex(float x, float y, float z) {
331
+ float vertex[] = vertices[vertexCount];
332
+
333
+ vertex[X] = x; // note: not mx, my, mz like PGraphics3
334
+ vertex[Y] = y;
335
+ vertex[Z] = z;
336
+
337
+ if (fill) {
338
+ vertex[R] = fillR;
339
+ vertex[G] = fillG;
340
+ vertex[B] = fillB;
341
+ vertex[A] = fillA;
342
+ }
343
+
344
+ if (stroke) {
345
+ vertex[SR] = strokeR;
346
+ vertex[SG] = strokeG;
347
+ vertex[SB] = strokeB;
348
+ vertex[SA] = strokeA;
349
+ vertex[SW] = strokeWeight;
350
+ }
351
+
352
+ if (textureImage != null) { // for the future?
353
+ vertex[U] = textureU;
354
+ vertex[V] = textureV;
355
+ }
356
+ vertexCount++;
357
+
358
+ if ((shape == LINES) && (vertexCount == 2)) {
359
+ writeLine(0, 1);
360
+ vertexCount = 0;
361
+
362
+ /*
363
+ } else if ((shape == LINE_STRIP) && (vertexCount == 2)) {
364
+ writeLineStrip();
365
+ */
366
+ } else if ((shape == TRIANGLES) && (vertexCount == 3)) {
367
+ writeTriangle();
368
+ }
369
+ }
370
+
371
+ @Override
372
+ public void endShape(int mode) {
373
+ if (shape == POLYGON) {
374
+ for (int i = 0; i < vertexCount - 1; i++) {
375
+ writeLine(i, i + 1);
376
+ }
377
+ if (mode == CLOSE) {
378
+ writeLine(vertexCount - 1, 0);
379
+ }
380
+ }
381
+ /*
382
+ if ((vertexCount != 0) &&
383
+ ((shape != LINE_STRIP) && (vertexCount != 1))) {
384
+ System.err.println("Extra vertex boogers found.");
385
+ }
386
+ */
387
+ }
388
+ }
@@ -0,0 +1,756 @@
1
+ /* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2
+
3
+ /*
4
+ Client - basic network client implementation
5
+ Part of the Processing project - http://processing.org
6
+
7
+ Copyright (c) 2004-2007 Ben Fry and Casey Reas
8
+ The previous version of this code was developed by Hernando Barragan
9
+
10
+ This library is free software; you can redistribute it and/or
11
+ modify it under the terms of the GNU Lesser General Public
12
+ License as published by the Free Software Foundation; either
13
+ version 2.1 of the License, or (at your option) any later version.
14
+
15
+ This library is distributed in the hope that it will be useful,
16
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
17
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18
+ Lesser General Public License for more details.
19
+
20
+ You should have received a copy of the GNU Lesser General
21
+ Public License along with this library; if not, write to the
22
+ Free Software Foundation, Inc., 59 Temple Place, Suite 330,
23
+ Boston, MA 02111-1307 USA
24
+ */
25
+ package processing.net;
26
+
27
+ import java.io.IOException;
28
+ import java.io.InputStream;
29
+ import java.io.OutputStream;
30
+ import java.lang.reflect.InvocationTargetException;
31
+ import java.lang.reflect.Method;
32
+ import java.net.Socket;
33
+ import java.net.SocketException;
34
+ import processing.core.PApplet;
35
+
36
+ /**
37
+ * ( begin auto-generated from Client.xml )
38
+ *
39
+ * A client connects to a server and sends data back and forth. If anything goes
40
+ * wrong with the connection, for example the host is not there or is listening
41
+ * on a different port, an exception is thrown.
42
+ *
43
+ * ( end auto-generated )
44
+ *
45
+ * @webref net
46
+ * @brief The client class is used to create client Objects which connect to a
47
+ * server to exchange data.
48
+ * @instanceName client any variable of type Client
49
+ * @usage Application
50
+ * @see_external LIB_net/clientEvent
51
+ */
52
+ public class Client implements Runnable {
53
+
54
+ protected static final int MAX_BUFFER_SIZE = 1 << 27; // 128 MB
55
+
56
+ PApplet parent;
57
+ Method clientEventMethod;
58
+ Method disconnectEventMethod;
59
+
60
+ volatile Thread thread;
61
+ Socket socket;
62
+ int port;
63
+ String host;
64
+
65
+ public InputStream input;
66
+ public OutputStream output;
67
+
68
+ final Object bufferLock = new Object[0];
69
+
70
+ byte buffer[] = new byte[32768];
71
+ int bufferIndex;
72
+ int bufferLast;
73
+
74
+ boolean disposeRegistered = false;
75
+
76
+ /**
77
+ * @param parent typically use "this"
78
+ * @param host address of the server
79
+ * @param port port to read/write from on the server
80
+ */
81
+ public Client(PApplet parent, String host, int port) {
82
+ this.parent = parent;
83
+ this.host = host;
84
+ this.port = port;
85
+
86
+ try {
87
+ socket = new Socket(this.host, this.port);
88
+ input = socket.getInputStream();
89
+ output = socket.getOutputStream();
90
+
91
+ thread = new Thread(this);
92
+ thread.start();
93
+
94
+ parent.registerMethod("dispose", this);
95
+ disposeRegistered = true;
96
+
97
+ // reflection to check whether host sketch has a call for
98
+ // public void clientEvent(processing.net.Client)
99
+ // which would be called each time an event comes in
100
+ try {
101
+ clientEventMethod
102
+ = parent.getClass().getMethod("clientEvent", Client.class);
103
+ } catch (NoSuchMethodException | SecurityException e) {
104
+ // no such method, or an error.. which is fine, just ignore
105
+ }
106
+ // do the same for disconnectEvent(Client c);
107
+ try {
108
+ disconnectEventMethod
109
+ = parent.getClass().getMethod("disconnectEvent", Client.class);
110
+ } catch (NoSuchMethodException | SecurityException e) {
111
+ // no such method, or an error.. which is fine, just ignore
112
+ }
113
+
114
+ } catch (IOException e) {
115
+ dispose();
116
+ }
117
+ }
118
+
119
+ /**
120
+ * @param socket any object of type
121
+ * @param parent
122
+ * @throws IOException
123
+ */
124
+ public Client(PApplet parent, Socket socket) throws IOException {
125
+ this.parent = parent;
126
+ this.socket = socket;
127
+
128
+ input = socket.getInputStream();
129
+ output = socket.getOutputStream();
130
+
131
+ thread = new Thread(this);
132
+ thread.start();
133
+
134
+ // reflection to check whether host sketch has a call for
135
+ // public void clientEvent(processing.net.Client)
136
+ // which would be called each time an event comes in
137
+ try {
138
+ clientEventMethod
139
+ = parent.getClass().getMethod("clientEvent", Client.class);
140
+ } catch (NoSuchMethodException | SecurityException e) {
141
+ // no such method, or an error.. which is fine, just ignore
142
+ }
143
+ // do the same for disconnectEvent(Client c);
144
+ try {
145
+ disconnectEventMethod
146
+ = parent.getClass().getMethod("disconnectEvent", Client.class);
147
+ } catch (NoSuchMethodException | SecurityException e) {
148
+ // no such method, or an error.. which is fine, just ignore
149
+ }
150
+ }
151
+
152
+ /**
153
+ * ( begin auto-generated from Client_stop.xml )
154
+ *
155
+ * Disconnects from the server. Use to shut the connection when you're
156
+ * finished with the Client.
157
+ *
158
+ * ( end auto-generated )
159
+ *
160
+ * @webref client:client
161
+ * @brief Disconnects from the server
162
+ * @usage application
163
+ */
164
+ public void stop() {
165
+ if (disconnectEventMethod != null && thread != null) {
166
+ try {
167
+ disconnectEventMethod.invoke(parent, this);
168
+ } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
169
+ Throwable cause = e;
170
+ // unwrap the exception if it came from the user code
171
+ if (e instanceof InvocationTargetException && e.getCause() != null) {
172
+ cause = e.getCause();
173
+ }
174
+ disconnectEventMethod = null;
175
+ }
176
+ }
177
+ if (disposeRegistered) {
178
+ parent.unregisterMethod("dispose", this);
179
+ disposeRegistered = false;
180
+ }
181
+ dispose();
182
+ }
183
+
184
+ /**
185
+ * Disconnect from the server: internal use only.
186
+ * <P>
187
+ * This should only be called by the internal functions in PApplet, use
188
+ * stop() instead from within your own applets.
189
+ */
190
+ public void dispose() {
191
+ thread = null;
192
+ try {
193
+ if (input != null) {
194
+ input.close();
195
+ input = null;
196
+ }
197
+ } catch (IOException e) {
198
+ }
199
+
200
+ try {
201
+ if (output != null) {
202
+ output.close();
203
+ output = null;
204
+ }
205
+ } catch (IOException e) {
206
+ }
207
+
208
+ try {
209
+ if (socket != null) {
210
+ socket.close();
211
+ socket = null;
212
+ }
213
+ } catch (IOException e) {
214
+ }
215
+ }
216
+
217
+ @Override
218
+ public void run() {
219
+ byte[] readBuffer;
220
+ { // make the read buffer same size as socket receive buffer so that
221
+ // we don't waste cycles calling listeners when there is more data waiting
222
+ int readBufferSize = 1 << 16; // 64 KB (default socket receive buffer size)
223
+ try {
224
+ readBufferSize = socket.getReceiveBufferSize();
225
+ } catch (SocketException ignore) {
226
+ }
227
+ readBuffer = new byte[readBufferSize];
228
+ }
229
+ while (Thread.currentThread() == thread) {
230
+ try {
231
+ while (input != null) {
232
+ int readCount;
233
+
234
+ // try to read a byte using a blocking read.
235
+ // An exception will occur when the sketch is exits.
236
+ try {
237
+ readCount = input.read(readBuffer, 0, readBuffer.length);
238
+ } catch (SocketException e) {
239
+ System.err.println("Client SocketException: " + e.getMessage());
240
+ // the socket had a problem reading so don't try to read from it again.
241
+ stop();
242
+ return;
243
+ }
244
+
245
+ // read returns -1 if end-of-stream occurs (for example if the host disappears)
246
+ if (readCount == -1) {
247
+ System.err.println("Client got end-of-stream.");
248
+ stop();
249
+ return;
250
+ }
251
+
252
+ synchronized (bufferLock) {
253
+ int freeBack = buffer.length - bufferLast;
254
+ if (readCount > freeBack) {
255
+ // not enough space at the back
256
+ int bufferLength = bufferLast - bufferIndex;
257
+ byte[] targetBuffer = buffer;
258
+ if (bufferLength + readCount > buffer.length) {
259
+ // can't fit even after compacting, resize the buffer
260
+ // find the next power of two which can fit everything in
261
+ int newSize = Integer.highestOneBit(bufferLength + readCount - 1) << 1;
262
+ if (newSize > MAX_BUFFER_SIZE) {
263
+ // buffer is full because client is not reading (fast enough)
264
+ System.err.println("Client: can't receive more data, buffer is full. "
265
+ + "Make sure you read the data from the client.");
266
+ stop();
267
+ return;
268
+ }
269
+ targetBuffer = new byte[newSize];
270
+ }
271
+ // compact the buffer (either in-place or into the new bigger buffer)
272
+ System.arraycopy(buffer, bufferIndex, targetBuffer, 0, bufferLength);
273
+ bufferLast -= bufferIndex;
274
+ bufferIndex = 0;
275
+ buffer = targetBuffer;
276
+ }
277
+ // copy all newly read bytes into the buffer
278
+ System.arraycopy(readBuffer, 0, buffer, bufferLast, readCount);
279
+ bufferLast += readCount;
280
+ }
281
+
282
+ // now post an event
283
+ if (clientEventMethod != null) {
284
+ try {
285
+ clientEventMethod.invoke(parent, this);
286
+ } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
287
+ System.err.println("error, disabling clientEvent() for " + host);
288
+ Throwable cause = e;
289
+ // unwrap the exception if it came from the user code
290
+ if (e instanceof InvocationTargetException && e.getCause() != null) {
291
+ cause = e.getCause();
292
+ }
293
+ clientEventMethod = null;
294
+ }
295
+ }
296
+ }
297
+ } catch (IOException e) {
298
+ //errorMessage("run", e);
299
+
300
+ }
301
+ }
302
+ }
303
+
304
+ /**
305
+ * ( begin auto-generated from Client_active.xml )
306
+ *
307
+ * Returns true if this client is still active and hasn't run into any
308
+ * trouble.( end auto-generated )
309
+ *
310
+ *
311
+ * @return
312
+ * @webref client:client
313
+ * @brief Returns true if this client is still active
314
+ * @usage application
315
+ */
316
+ public boolean active() {
317
+ return (thread != null);
318
+ }
319
+
320
+ /**
321
+ * ( begin auto-generated from Client_ip.xml )
322
+ *
323
+ * Returns the IP address of the computer to which the Client is attached.(
324
+ * end auto-generated )
325
+ *
326
+ *
327
+ * @return
328
+ * @webref client:client
329
+ * @usage application
330
+ * @brief Returns the IP address of the machine as a String
331
+ */
332
+ public String ip() {
333
+ if (socket != null) {
334
+ return socket.getInetAddress().getHostAddress();
335
+ }
336
+ return null;
337
+ }
338
+
339
+ /**
340
+ * ( begin auto-generated from Client_available.xml )
341
+ *
342
+ * Returns the number of bytes available.When any client has bytes available
343
+ * from the server, it returns the number of bytes. ( end auto-generated )
344
+ *
345
+ * @return
346
+ * @webref client:client
347
+ * @usage application
348
+ * @brief Returns the number of bytes in the buffer waiting to be read
349
+ */
350
+ public int available() {
351
+ synchronized (bufferLock) {
352
+ return (bufferLast - bufferIndex);
353
+ }
354
+ }
355
+
356
+ /**
357
+ * ( begin auto-generated from Client_clear.xml )
358
+ *
359
+ * Empty the buffer, removes all the data stored there.
360
+ *
361
+ * ( end auto-generated )
362
+ *
363
+ * @webref client:client
364
+ * @usage application
365
+ * @brief Clears the buffer
366
+ */
367
+ public void clear() {
368
+ synchronized (bufferLock) {
369
+ bufferLast = 0;
370
+ bufferIndex = 0;
371
+ }
372
+ }
373
+
374
+ /**
375
+ * ( begin auto-generated from Client_read.xml )
376
+ *
377
+ * Returns a number between 0 and 255 for the next byte that's waiting in
378
+ * the buffer.Returns -1 if there is no byte, although this should be
379
+ * avoided by first cheacking <b>available()</b> to see if any data is
380
+ * available. ( end auto-generated )
381
+ *
382
+ * @return
383
+ * @webref client:client
384
+ * @usage application
385
+ * @brief Returns a value from the buffer
386
+ */
387
+ public int read() {
388
+ synchronized (bufferLock) {
389
+ if (bufferIndex == bufferLast) {
390
+ return -1;
391
+ }
392
+
393
+ int outgoing = buffer[bufferIndex++] & 0xff;
394
+ if (bufferIndex == bufferLast) { // rewind
395
+ bufferIndex = 0;
396
+ bufferLast = 0;
397
+ }
398
+ return outgoing;
399
+ }
400
+ }
401
+
402
+ /**
403
+ * ( begin auto-generated from Client_readChar.xml )
404
+ *
405
+ * Returns the next byte in the buffer as a char.Returns -1 or 0xffff if
406
+ * nothing is there. ( end auto-generated )
407
+ *
408
+ * @return
409
+ * @webref client:client
410
+ * @usage application
411
+ * @brief Returns the next byte in the buffer as a char
412
+ */
413
+ public char readChar() {
414
+ synchronized (bufferLock) {
415
+ if (bufferIndex == bufferLast) {
416
+ return (char) (-1);
417
+ }
418
+ return (char) read();
419
+ }
420
+ }
421
+
422
+ /**
423
+ * ( begin auto-generated from Client_readBytes.xml )
424
+ *
425
+ * Reads a group of bytes from the buffer.The version with no parameters
426
+ * returns a byte array of all data in the buffer. This is not efficient,
427
+ * but is easy to use. The version with the <b>byteBuffer</b> parameter is
428
+ * more memory and time efficient. It grabs the data in the buffer and puts
429
+ * it into the byte array passed in and returns an int value for the number
430
+ * of bytes read. If more bytes are available than can fit into the
431
+ * <b>byteBuffer</b>, only those that fit are read.
432
+ *
433
+ * ( end auto-generated )
434
+ * <h3>Advanced</h3>
435
+ * Return a byte array of anything that's in the serial buffer. Not
436
+ * particularly memory/speed efficient, because it creates a byte array on
437
+ * each read, but it's easier to use than readBytes(byte b[]) (see below).
438
+ *
439
+ * @return
440
+ * @webref client:client
441
+ * @usage application
442
+ * @brief Reads everything in the buffer
443
+ */
444
+ public byte[] readBytes() {
445
+ synchronized (bufferLock) {
446
+ if (bufferIndex == bufferLast) {
447
+ return null;
448
+ }
449
+
450
+ int length = bufferLast - bufferIndex;
451
+ byte outgoing[] = new byte[length];
452
+ System.arraycopy(buffer, bufferIndex, outgoing, 0, length);
453
+
454
+ bufferIndex = 0; // rewind
455
+ bufferLast = 0;
456
+ return outgoing;
457
+ }
458
+ }
459
+
460
+ /**
461
+ * <h3>Advanced</h3>
462
+ * Return a byte array of anything that's in the serial buffer up to the
463
+ * specified maximum number of bytes. Not particularly memory/speed
464
+ * efficient, because it creates a byte array on each read, but it's easier
465
+ * to use than readBytes(byte b[]) (see below).
466
+ *
467
+ * @param max the maximum number of bytes to read
468
+ * @return
469
+ */
470
+ public byte[] readBytes(int max) {
471
+ synchronized (bufferLock) {
472
+ if (bufferIndex == bufferLast) {
473
+ return null;
474
+ }
475
+
476
+ int length = bufferLast - bufferIndex;
477
+ if (length > max) {
478
+ length = max;
479
+ }
480
+ byte outgoing[] = new byte[length];
481
+ System.arraycopy(buffer, bufferIndex, outgoing, 0, length);
482
+
483
+ bufferIndex += length;
484
+ if (bufferIndex == bufferLast) {
485
+ bufferIndex = 0; // rewind
486
+ bufferLast = 0;
487
+ }
488
+
489
+ return outgoing;
490
+ }
491
+ }
492
+
493
+ /**
494
+ * <h3>Advanced</h3>
495
+ * Grab whatever is in the serial buffer, and stuff it into a byte buffer
496
+ * passed in by the user. This is more memory/time efficient than
497
+ * readBytes() returning a byte[] array.
498
+ *
499
+ * Returns an int for how many bytes were read. If more bytes are available
500
+ * than can fit into the byte array, only those that will fit are read.
501
+ *
502
+ * @param bytebuffer passed in byte array to be altered
503
+ * @return
504
+ */
505
+ public int readBytes(byte bytebuffer[]) {
506
+ synchronized (bufferLock) {
507
+ if (bufferIndex == bufferLast) {
508
+ return 0;
509
+ }
510
+
511
+ int length = bufferLast - bufferIndex;
512
+ if (length > bytebuffer.length) {
513
+ length = bytebuffer.length;
514
+ }
515
+ System.arraycopy(buffer, bufferIndex, bytebuffer, 0, length);
516
+
517
+ bufferIndex += length;
518
+ if (bufferIndex == bufferLast) {
519
+ bufferIndex = 0; // rewind
520
+ bufferLast = 0;
521
+ }
522
+ return length;
523
+ }
524
+ }
525
+
526
+ /**
527
+ * ( begin auto-generated from Client_readBytesUntil.xml )
528
+ *
529
+ * Reads from the port into a buffer of bytes up to and including a
530
+ * particular character.If the character isn't in the buffer, 'null' is
531
+ * returned. The version with no <b>byteBuffer</b> parameter returns a byte
532
+ * array of all data up to and including the <b>interesting</b> byte. This
533
+ * is not efficient, but is easy to use. The version with the
534
+ * <b>byteBuffer</b> parameter is more memory and time efficient. It grabs
535
+ * the data in the buffer and puts it into the byte array passed in and
536
+ * returns an int value for the number of bytes read. If the byte buffer is
537
+ * not large enough, -1 is returned and an error is printed to the message
538
+ * area. If nothing is in the buffer, 0 is returned.
539
+ *
540
+ * ( end auto-generated )
541
+ *
542
+ * @return
543
+ * @webref client:client
544
+ * @usage application
545
+ * @brief Reads from the buffer of bytes up to and including a particular
546
+ * character
547
+ * @param interesting character designated to mark the end of the data
548
+ */
549
+ public byte[] readBytesUntil(int interesting) {
550
+ byte what = (byte) interesting;
551
+
552
+ synchronized (bufferLock) {
553
+ if (bufferIndex == bufferLast) {
554
+ return null;
555
+ }
556
+
557
+ int found = -1;
558
+ for (int k = bufferIndex; k < bufferLast; k++) {
559
+ if (buffer[k] == what) {
560
+ found = k;
561
+ break;
562
+ }
563
+ }
564
+ if (found == -1) {
565
+ return null;
566
+ }
567
+
568
+ int length = found - bufferIndex + 1;
569
+ byte outgoing[] = new byte[length];
570
+ System.arraycopy(buffer, bufferIndex, outgoing, 0, length);
571
+
572
+ bufferIndex += length;
573
+ if (bufferIndex == bufferLast) {
574
+ bufferIndex = 0; // rewind
575
+ bufferLast = 0;
576
+ }
577
+ return outgoing;
578
+ }
579
+ }
580
+
581
+ /**
582
+ * <h3>Advanced</h3>
583
+ * Reads from the serial port into a buffer of bytes until a particular
584
+ * character. If the character isn't in the serial buffer, then 'null' is
585
+ * returned.
586
+ *
587
+ * If outgoing[] is not big enough, then -1 is returned, and an error
588
+ * message is printed on the console. If nothing is in the buffer, zero is
589
+ * returned. If 'interesting' byte is not in the buffer, then 0 is returned.
590
+ *
591
+ * @param interesting
592
+ * @param byteBuffer passed in byte array to be altered
593
+ * @return
594
+ */
595
+ public int readBytesUntil(int interesting, byte byteBuffer[]) {
596
+ byte what = (byte) interesting;
597
+
598
+ synchronized (bufferLock) {
599
+ if (bufferIndex == bufferLast) {
600
+ return 0;
601
+ }
602
+
603
+ int found = -1;
604
+ for (int k = bufferIndex; k < bufferLast; k++) {
605
+ if (buffer[k] == what) {
606
+ found = k;
607
+ break;
608
+ }
609
+ }
610
+ if (found == -1) {
611
+ return 0;
612
+ }
613
+
614
+ int length = found - bufferIndex + 1;
615
+ if (length > byteBuffer.length) {
616
+ System.err.println("readBytesUntil() byte buffer is"
617
+ + " too small for the " + length
618
+ + " bytes up to and including char " + interesting);
619
+ return -1;
620
+ }
621
+ //byte outgoing[] = new byte[length];
622
+ System.arraycopy(buffer, bufferIndex, byteBuffer, 0, length);
623
+
624
+ bufferIndex += length;
625
+ if (bufferIndex == bufferLast) {
626
+ bufferIndex = 0; // rewind
627
+ bufferLast = 0;
628
+ }
629
+ return length;
630
+ }
631
+ }
632
+
633
+ /**
634
+ * ( begin auto-generated from Client_readString.xml )
635
+ *
636
+ * Returns the all the data from the buffer as a String.This method assumes
637
+ * the incoming characters are ASCII. If you want to transfer Unicode data,
638
+ * first convert the String to a byte stream in the representation of your
639
+ * choice (i.e. UTF8 or two-byte Unicode data), and send it as a byte array.
640
+ *
641
+ * ( end auto-generated )
642
+ *
643
+ * @return
644
+ * @webref client:client
645
+ * @usage application
646
+ * @brief Returns the buffer as a String
647
+ */
648
+ public String readString() {
649
+ byte b[] = readBytes();
650
+ if (b == null) {
651
+ return null;
652
+ }
653
+ return new String(b);
654
+ }
655
+
656
+ /**
657
+ * ( begin auto-generated from Client_readStringUntil.xml )
658
+ *
659
+ * Combination of <b>readBytesUntil()</b> and <b>readString()</b>.Returns
660
+ * <b>null</b> if it doesn't find what you're looking for. ( end
661
+ * auto-generated )
662
+ * <h3>Advanced</h3>
663
+ *
664
+ * If you want to move Unicode data, you can first convert the String to a
665
+ * byte stream in the representation of your choice (i.e. UTF8 or two-byte
666
+ * Unicode data), and send it as a byte array.
667
+ *
668
+ * @return
669
+ * @webref client:client
670
+ * @usage application
671
+ * @brief Returns the buffer as a String up to and including a particular
672
+ * character
673
+ * @param interesting character designated to mark the end of the data
674
+ */
675
+ public String readStringUntil(int interesting) {
676
+ byte b[] = readBytesUntil(interesting);
677
+ if (b == null) {
678
+ return null;
679
+ }
680
+ return new String(b);
681
+ }
682
+
683
+ /**
684
+ * ( begin auto-generated from Client_write.xml )
685
+ *
686
+ * Writes data to a server specified when constructing the client.
687
+ *
688
+ * ( end auto-generated )
689
+ *
690
+ * @webref client:client
691
+ * @usage application
692
+ * @brief Writes bytes, chars, ints, bytes[], Strings
693
+ * @param data data to write
694
+ */
695
+ public void write(int data) { // will also cover char
696
+ try {
697
+ output.write(data & 0xff); // for good measure do the &
698
+ output.flush(); // hmm, not sure if a good idea
699
+
700
+ } catch (IOException e) { // null pointer or serial port dead
701
+ //errorMessage("write", e);
702
+ //e.printStackTrace();
703
+ //dispose();
704
+ //disconnect(e);
705
+ stop();
706
+ }
707
+ }
708
+
709
+ public void write(byte data[]) {
710
+ try {
711
+ output.write(data);
712
+ output.flush(); // hmm, not sure if a good idea
713
+
714
+ } catch (IOException e) { // null pointer or serial port dead
715
+ stop();
716
+ }
717
+ }
718
+
719
+ /**
720
+ * <h3>Advanced</h3>
721
+ * Write a String to the output. Note that this doesn't account for Unicode
722
+ * (two bytes per char), nor will it send UTF8 characters.. It assumes that
723
+ * you mean to send a byte buffer (most often the case for networking and
724
+ * serial i/o) and will only use the bottom 8 bits of each char in the
725
+ * string. (Meaning that internally it uses String.getBytes)
726
+ *
727
+ * If you want to move Unicode data, you can first convert the String to a
728
+ * byte stream in the representation of your choice (i.e. UTF8 or two-byte
729
+ * Unicode data), and send it as a byte array.
730
+ *
731
+ * @param data
732
+ */
733
+ public void write(String data) {
734
+ write(data.getBytes());
735
+ }
736
+
737
+ /**
738
+ * Handle disconnect due to an Exception being thrown.
739
+ */
740
+ /*
741
+ protected void disconnect(Exception e) {
742
+ dispose();
743
+ if (e != null) {
744
+ e.printStackTrace();
745
+ }
746
+ }
747
+ */
748
+ /**
749
+ * General error reporting, all corralled here just in case I think of
750
+ * something slightly more intelligent to do.
751
+ */
752
+ //public void errorMessage(String where, Exception e) {
753
+ //parent.die("Error inside Client." + where + "()", e);
754
+ //e.printStackTrace(System.err);
755
+ //}
756
+ }