Revision 1190

View differences:

tags/org.gvsig.dwg-2.0.248/org.gvsig.dwg.lib/src/main/java/org/gvsig/dwg/lib/IDwg2FMap.java
1
/*
2
 * Created on 09-ene-2007
3
 *
4
 * gvSIG. Sistema de Informaci�n Geogr�fica de la Generalitat Valenciana
5
 *
6
 * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
7
 *
8
 * This program is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU General Public License
10
 * as published by the Free Software Foundation; either version 2
11
 * of the License, or (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program; if not, write to the Free Software
20
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
21
 *
22
 * For more information, contact:
23
 *
24
 *  Generalitat Valenciana
25
 *   Conselleria d'Infraestructures i Transport
26
 *   Av. Blasco Ib��ez, 50
27
 *   46010 VALENCIA
28
 *   SPAIN
29
 *
30
 *      +34 963862235
31
 *   gvsig@gva.es
32
 *      www.gvsig.gva.es
33
 *
34
 *    or
35
 *
36
 *   IVER T.I. S.A
37
 *   Salamanca 50
38
 *   46005 Valencia
39
 *   Spain
40
 *
41
 *   +34 963163400
42
 *   dac@iver.es
43
 */
44

  
45
/* CVS MESSAGES:
46
*
47
* $Id: IDwg2FMap.java 29001 2009-05-26 15:32:46Z jmvivo $
48
* $Log$
49
* Revision 1.2.2.2  2007-03-21 19:49:16  azabala
50
* implementation of dwg 12, 13, 14.
51
*
52
* Revision 1.3  2007/03/20 19:55:27  azabala
53
* source code cleaning
54
*
55
* Revision 1.2  2007/01/18 13:35:22  azabala
56
* Refactoring general para evitar dar tantas pasadas en la carga, y para incrementar
57
* la legibilidad del codigo (demasiados if-else-if en vez de usar polimorfismo)
58
*
59
* Revision 1.1  2007/01/12 19:29:58  azabala
60
* first version in cvs
61
*
62
*
63
*/
64
package org.gvsig.dwg.lib;
65

  
66
import org.gvsig.fmap.geom.Geometry;
67
import org.gvsig.fmap.geom.exception.CreateGeometryException;
68

  
69
/**
70
 * All dwg objects that are drawing entities
71
 * and that can be converted to a fmap geometry
72
 * implements this interface.
73
 *
74
 * */
75
/*
76
 * TODO
77
 * Esta solucion tiene el problema de que es mas simple
78
 * (cada entidad dwg se ocupa de su conversion a fmap),pero acopla
79
 * libDwg con fmap
80
 * (una clase Dwg2FMap lo desacoplar�a, pero llenar�a el codigo de
81
 * infinitos if(dwg instanceof ...) else if.....
82
 *
83
 * */
84
public interface IDwg2FMap {
85
	public Geometry toFMapGeometry(boolean is3DFile) throws CreateGeometryException;
86
	public String toFMapString(boolean is3DFile);
87
	public int getGeometryType();
88
	public int getGeometrySubType(boolean is3DFile);
89
	public String toString();
90
}
91

  
tags/org.gvsig.dwg-2.0.248/org.gvsig.dwg.lib/src/main/java/org/gvsig/dwg/lib/DwgFile.java
1
/* jdwglib. Java Library for reading Dwg files.
2
 *
3
 * Author: Jose Morell Rama (jose.morell@gmail.com).
4
 * Port from the Pythoncad Dwg library by Art Haas.
5
 *
6
 * Copyright (C) 2005 Jose Morell, IVER TI S.A. and Generalitat Valenciana
7
 *
8
 * This program is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU General Public License
10
 * as published by the Free Software Foundation; either version 2
11
 * of the License, or (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program; if not, write to the Free Software
20
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
21
 *
22
 * For more information, contact:
23
 *
24
 * Jose Morell (jose.morell@gmail.com)
25
 *
26
 * or
27
 *
28
 * IVER TI S.A.
29
 *  C/Salamanca, 50
30
 *  46005 Valencia
31
 *  Spain
32
 *  +34 963163400
33
 *  dac@iver.es
34
 */
35
package org.gvsig.dwg.lib;
36

  
37
import java.awt.geom.Point2D;
38
import java.io.File;
39
import java.io.FileInputStream;
40
import java.io.IOException;
41
import java.nio.ByteBuffer;
42
import java.nio.channels.FileChannel;
43
import java.util.ArrayList;
44
import java.util.HashMap;
45
import java.util.Iterator;
46
import java.util.List;
47
import java.util.Map;
48

  
49
import org.gvsig.dwg.lib.objects.DwgBlockHeader;
50
import org.gvsig.dwg.lib.objects.DwgInsert;
51
import org.gvsig.dwg.lib.objects.DwgLayer;
52
import org.gvsig.dwg.lib.readers.DwgFileV12Reader;
53
import org.gvsig.dwg.lib.readers.DwgFileV14Reader;
54
import org.gvsig.dwg.lib.readers.DwgFileV15Reader;
55
import org.gvsig.dwg.lib.readers.DwgFileVR2004Reader;
56
import org.gvsig.dwg.lib.readers.IDwgFileReader;
57
import org.slf4j.Logger;
58
import org.slf4j.LoggerFactory;
59

  
60

  
61
/**
62
 * The DwgFile class provides a revision-neutral interface for reading and handling
63
 * DWG files
64
 * Reading methods are useful for reading DWG files, and handling methods like
65
 * calculateDwgPolylines() are useful for handling more complex
66
 * objects in the DWG file
67
 *
68
 * @author jmorell
69
 * @author azabala
70
 */
71
public class DwgFile {
72
	/**
73
	 * It has all known DWG version's header.
74
	 * Extracted from Autodesk web.
75
	 */
76
	private static HashMap acadVersions = new HashMap();
77
	static{
78
		acadVersions.put("AC1004", "Autocad R9");
79
		acadVersions.put("AC1006", "Autocad R10");
80
		acadVersions.put("AC1007", "Autocad pre-R11");
81
		acadVersions.put("AC1007", "Autocad pre-R11");
82
		acadVersions.put("AC1008", "Autocad pre-R11b");
83
		acadVersions.put("AC1009", "Autocad R12");
84
		acadVersions.put("AC1010", "Autocad pre-R13 a");
85
		acadVersions.put("AC1011", "Autocad pre-R13 b");
86
		acadVersions.put("AC1012", "Autocad R13");
87
		acadVersions.put("AC1013", "Autocad pre-R14");
88
		acadVersions.put("AC1014", "Autocad R14");
89
		acadVersions.put("AC1500", "Autocad pre-2000");
90
		acadVersions.put("AC1015", "Autocad R2000, R2000i, R2002");
91
		acadVersions.put("AC402a", "Autocad pre-2004a");
92
		acadVersions.put("AC402b", "Autocad pre-2004b");
93
		acadVersions.put("AC1018", "Autocad R2004, R2005, R2006");
94
		acadVersions.put("AC1021", "Autocad R2007");
95

  
96
	}
97

  
98
	private static Logger logger = LoggerFactory.getLogger(DwgFile.class.getName());
99
	/**
100
	 * Path and name of the dwg file
101
	 * */
102
	private String fileName;
103
	/**
104
	 * DWG version of the file (AC1013, AC1018, etc.)
105
	 * */
106
	private String dwgVersion;
107

  
108
	/**
109
	 * Offsets to the DWG sections
110
	 */
111
	private ArrayList dwgSectionOffsets;
112
	/**
113
	 * Header vars readed from the HEADER section of the DWG file
114
	 * */
115
	private Map headerVars;
116

  
117
	/**
118
	 * This list contains what in OpenDWG specification is called
119
	 * the object map ( a collection of entries where each entry contains
120
	 * the seek of each object, and its size)
121
	 * */
122
	private ArrayList dwgObjectOffsets;
123

  
124
	/**
125
	 * For each entry in dwgObjectOffsets, we have an instance of
126
	 * DwgObject in the dwgObjects collection
127
	 *
128
	 * */
129
	private List dwgObjects;
130
	private HashMap handle_objects;
131

  
132

  
133
	private ArrayList dwgClasses;
134

  
135

  
136
	/**
137
	 * hash map that indexes all DwgLayer objects
138
	 * by its handle property
139
	 * */
140
	private HashMap layerTable;
141

  
142
	/**
143
	 * Specific reader of the DWG file version (12, 13, 14, 2000, etc., each
144
	 * version will have an specific reader)
145
	 * */
146
	private IDwgFileReader dwgReader;
147
	private boolean dwg3DFile = false;
148
	/**
149
	 * Memory mapped byte buffer of the whole DWG file
150
	 * */
151
	private ByteBuffer bb;
152

  
153
	/*
154
	 * Optimizaciones para evitar leer el fichero completo en cada
155
	 * pasada.
156
	 * */
157
	/**
158
	 * Contains all IDwgPolyline implementations
159
	 * */
160
	private List dwgPolylines;
161
	/**
162
	 * Contains all INSERT entities of the dwg file
163
	 * (these entities must be processed in a second pass)
164
	 *
165
	 * */
166
	private List insertList;
167

  
168
	private List blockList;
169

  
170

  
171
	/**
172
	 * Constructor.
173
	 * @param fileName an absolute path to the DWG file
174
	 */
175
	public DwgFile(String fileName) {
176
		this.fileName = fileName;
177

  
178
		dwgSectionOffsets = new ArrayList();
179
		dwgObjectOffsets = new ArrayList();
180
		headerVars = new HashMap();
181

  
182
		dwgClasses = new ArrayList();
183

  
184
		dwgObjects = new ArrayList();
185
		handle_objects = new HashMap();
186

  
187
		layerTable = new HashMap();
188

  
189
		dwgPolylines = new ArrayList();
190
		insertList = new ArrayList();
191

  
192
		blockList = new ArrayList();
193

  
194
	}
195

  
196
	public String getDwgVersion() {
197
		return dwgVersion;
198
	}
199

  
200
	/**
201
	 * Reads a DWG file and put its objects in the dwgObjects Vector
202
	 * This method is version independent
203
	 *
204
	 * @throws IOException If the file location is wrong
205
	 */
206
	public void read() throws IOException,
207
				DwgVersionNotSupportedException
208
	{
209
		setDwgVersion();
210
		if (dwgVersion.equalsIgnoreCase("Autocad R2000, R2000i, R2002")) {
211
			dwgReader = new DwgFileV15Reader();
212
		}else if (dwgVersion.equalsIgnoreCase("Autocad pre-R14")||
213
				dwgVersion.equalsIgnoreCase("Autocad R14") ||
214
				dwgVersion.equalsIgnoreCase("Autocad R13")) {
215
			dwgReader = new DwgFileV14Reader();
216
		}else if (dwgVersion.equalsIgnoreCase("Autocad R2004, R2005, R2006")){
217
			dwgReader = new DwgFileVR2004Reader();
218
		} else if (dwgVersion.equalsIgnoreCase("Autocad R12")||
219
				dwgVersion.equalsIgnoreCase("Autocad pre-R13 a") ||
220
				dwgVersion.equalsIgnoreCase("Autocad pre-R13 b")) {
221

  
222
			boolean isR13 = true;
223
			if(dwgVersion.equalsIgnoreCase("Autocad R12"))
224
					isR13 = false;
225
			dwgReader = new DwgFileV12Reader(isR13);
226
		}else {
227
			DwgVersionNotSupportedException exception =
228
				new DwgVersionNotSupportedException("Version de DWG no soportada");
229
			exception.setDwgVersion(dwgVersion);
230
			throw exception;
231
		}
232
		try{
233
		dwgReader.read(this, bb);
234
		}catch(Throwable t){
235
			t.printStackTrace();
236
			throw new IOException("Error leyendo dwg");
237
		}
238
	}
239

  
240
	private void setDwgVersion() throws IOException {
241
		File file = new File(fileName);
242
		FileInputStream fileInputStream = new FileInputStream(file);
243
		FileChannel fileChannel = fileInputStream.getChannel();
244
		long channelSize = fileChannel.size();
245
		bb = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0, channelSize);
246
		byte[] versionBytes = {bb.get(0),
247
								bb.get(1),
248
								bb.get(2),
249
								bb.get(3),
250
								bb.get(4),
251
								bb.get(5)};
252
		ByteBuffer versionByteBuffer = ByteBuffer.wrap(versionBytes);
253
		String[] bs = new String[versionByteBuffer.capacity()];
254
		String versionString = "";
255
		for (int i=0; i<versionByteBuffer.capacity(); i++) {
256
			bs[i] = new String(new byte[]{(byte)(versionByteBuffer.get(i))});
257
			versionString = versionString + bs[i];
258
		}
259
		String version = (String) acadVersions.get(versionString);
260
		if(version == null)
261
			version = "Unknown Dwg format";
262
		this.dwgVersion = version;
263
	}
264

  
265
	public void setHeader(String key, Object value){
266
		headerVars.put(key, value);
267
	}
268

  
269
	public Object getHeader(String key){
270
		return headerVars.get(key);
271
	}
272

  
273
	/*
274
	 * A DwgLayer is a DWG drawing entity, so all DwgLayer objects are
275
	 * saved in dwgObjects collection.
276
	 * Instead of iterate over the full collection, is faster check every object
277
	 * and save all the DwgLayer instances in their own collection.
278
	 *
279
	 */
280
	protected void addDwgLayer(DwgLayer dwgLayer){
281
		layerTable.put(new Integer(dwgLayer.getHandle().getOffset()),
282
				dwgLayer);
283
	}
284

  
285
	private void printInfoOfAObject (DwgObject entity){
286
		logger.info("index = "+entity.getIndex() + " entity.type = " + entity.type + " entityClassName = "+ entity.getClass().getName());
287
		logger.info("handleCode = "+entity.getHandle().getCode());
288
		logger.info("entityLayerHandle = "+entity.getHandle().getOffset());
289
		if(entity.hasLayerHandle()){
290
			logger.info("layerHandleCode = "+entity.getLayerHandle().getCode());
291
			logger.info("layerHandle = "+entity.getLayerHandle().getOffset());
292
		}
293
		if(entity.hasSubEntityHandle()){
294
			logger.info("subEntityHandleCode = "+entity.getSubEntityHandle().getCode());
295
			logger.info("subEntityHandle = "+entity.getSubEntityHandle().getOffset());
296
		}
297
		if(entity.hasNextHandle()){
298
			logger.info("nextHandleCode = "+entity.getNextHandle().getCode());
299
			logger.info("nextHandle = "+entity.getNextHandle().getOffset());
300
		}
301
		if(entity.hasPreviousHandle()){
302
			logger.info ("previousHandleCode = "+entity.getPreviousHandle().getCode());
303
			logger.info ("previousHandle = "+entity.getPreviousHandle().getOffset());
304
		}
305
		if(entity.hasXDicObjHandle()){
306
			logger.info ("xDicObjHandleCode = "+entity.getXDicObjHandle());
307
			logger.info ("xDicObjHandle = "+entity.getXDicObjHandle());
308
		}
309
		if(entity.hasReactorsHandles()){
310
			ArrayList reactorsHandles = entity.getReactorsHandles();
311
			int size = reactorsHandles.size();
312
			logger.info ("NUMERO DE reactors = "+size);
313
			DwgHandleReference hr;
314
			for(int i=0; i<size; i++){
315
				hr=(DwgHandleReference)reactorsHandles.get(i);
316
				logger.info ("reactorHandleCode = "+hr.getCode());
317
				logger.info (" reactorHandle = "+hr.getOffset());
318
			}
319
		}
320

  
321
	}
322
	public DwgLayer getDwgLayer(DwgObject entity){
323
		DwgHandleReference handle = entity.getLayerHandle();
324
		if(handle == null){
325
			return null;
326
		}
327
		int	handleCode = handle.getCode();
328
		int	entityLayerHandle = entity.getLayerHandle().getOffset();
329
		int layerHandle = -1;
330

  
331
		int entityRecord;
332
		DwgObject object;
333

  
334

  
335
		/*
336
		 * OpenDWG spec, v3, page 11. HANDLE REFERENCES
337
		 *
338
		 * A handle is formed by this fields:
339
		 * a) CODE (4 bits)
340
		 * b) COUNTER (4 bits)
341
		 * c) OFFSET of the object (handle itself).
342
		 *
343
		 * CODE could take these values:
344
		 * 1) 0x2, 0x3, 0x4, 0x5 -> offset is the handle of the layer
345
		 * 2) 0x6 -> offset is the next object handle
346
		 * 3) 0x8 -> offset is the previous object handle
347
		 * 4) 0xA -> result is reference handle plus offset
348
 		 * 5) 0xC -> result is reference handle minus offset
349
		 *
350
		 * */
351

  
352
		// FIXME: Esto no esta terminado. Falta considerar los codigo
353
		// 0x2, 0x3, 0x6, 0xA que no han aparecido en los archivos de prueba.
354
		switch(handleCode){
355
		case 0x4:
356
			if (entity.hasNextHandle()){
357
				int nextHandleCode = entity.getNextHandle().getCode();
358
				if (nextHandleCode == 0x5) {
359
					layerHandle = entity.getNextHandle().getOffset();
360
				} else {
361
					//TODO: No se han previsto nextHandleCode != 0x5
362
//					System.out.println ("DwgFile.getDwgLayer: handleCode "+handleCode+
363
//							" con nextHandleCode "+ nextHandleCode +" no implementado.");
364
				}
365
			} else {
366
				layerHandle = entity.getLayerHandle().getOffset();
367
			}
368
			break;
369
		case 0x5:
370
			layerHandle = entity.getLayerHandle().getOffset();
371
			break;
372
		case 0x8:
373
			if (entity.hasNextHandle()){
374
				int nextHandleCode = entity.getNextHandle().getCode();
375
				if (nextHandleCode == 0x5) {
376
					layerHandle = entity.getNextHandle().getOffset();
377
				} else {
378
					//TODO No se han previsto nextHandleCode != 0x5
379
//					System.out.println ("DwgFile.getDwgLayer: handleCode "+handleCode+
380
//							" con nextHandleCode "+ nextHandleCode +" no implementado.");
381
				}
382
			} else {
383
				layerHandle = entity.getHandle().getOffset() - 1;
384
			}
385
			break;
386
		case 0xC:
387
			if (entity.hasNextHandle()){
388
				int nextHandleCode = entity.getNextHandle().getCode();
389
				if (nextHandleCode == 0x5) {
390
					layerHandle = entity.getNextHandle().getOffset();
391
				} else {
392
					//TODO: No se han previsto nextHandleCode != 0x5
393
//					System.out.println ("DwgFile.getDwgLayer: handleCode "+handleCode+
394
//							" con nextHandleCode "+ nextHandleCode +" no implementado.");
395
				}
396
			} else {
397
				layerHandle = entity.getHandle().getOffset() - entity.getLayerHandle().getOffset() + 1;
398
			}
399
			break;
400
		default:
401
//			System.out.println ("DwgFile.getDwgLayer: handleCode "+handleCode+" no implementado. entityLayerHandle="+entityLayerHandle);
402
		}
403

  
404
		if(layerHandle != -1){
405
			Iterator lyrIterator = layerTable.values().iterator();
406
			while(lyrIterator.hasNext()){
407
				DwgLayer lyr = (DwgLayer) lyrIterator.next();
408
				int lyrHdl = lyr.getHandle().getOffset();
409
				if (lyrHdl == layerHandle){
410
					return lyr;
411
				}
412
			}
413
		}
414
//		System.out.println("NO SE HA ENCONTRADO UNA CAPA CON HANDLE " + layerHandle);
415
//		printInfoOfAObject(entity);
416
		return null;
417
	}
418

  
419
	public DwgObject getDwgSuperEntity(DwgObject entity) {
420
		if(entity.hasSubEntityHandle()){
421
			int handleCode = entity.subEntityHandle.getCode();
422
			int offset = entity.subEntityHandle.getOffset();
423
			int handle = -1;
424

  
425
			DwgObject object;
426

  
427
			switch(handleCode){
428
			// TODO: case 0x2:
429
			// TODO: case 0x3:
430
			case 0x4:
431
			case 0x5:
432
				handle = offset;
433
				break;
434
			// TODO: case 0x6:
435
			case 0x8:
436
				handle=entity.getHandle().getOffset() - 1;
437
				break;
438
			case 0xA:
439
				handle = entity.getHandle().getOffset() + offset;
440
				break;
441
			case 0xC:
442
				handle = entity.getHandle().getOffset() - offset;
443
				break;
444
			default:
445
				logger.warn ("DwgObject.getDwgSuperEntity: handleCode "+handleCode+" no implementado. offset = "+offset);
446
			}
447
			if(handle != -1){
448
				object = getDwgObjectFromHandle(handle);
449
				if(object != null)
450
					return object;
451
			}
452
		}
453
		return null;
454
	}
455

  
456
	public String getLayerName(DwgObject entity) {
457
		DwgLayer dwgLayer = getDwgLayer(entity);
458
		if(dwgLayer == null){
459
			return "";
460
		}else{
461
			return dwgLayer.getName();
462
		}
463
	}
464

  
465
	/**
466
     * Returns the color of the layer of a DWG object
467
	 *
468
     * @param entity DWG object which we want to know its layer color
469
	 * @return int Layer color of the DWG object in the Autocad color code
470
	 */
471
	public int getColorByLayer(DwgObject entity) {
472
		int colorByLayer;
473
		DwgLayer dwgLyr = getDwgLayer(entity);
474
		if(dwgLyr == null)
475
			colorByLayer = 0;
476
		else
477
			colorByLayer = dwgLyr.getColor();
478
		return colorByLayer;
479
	}
480
	/**
481
	 * Configure the geometry of the polylines in a DWG file from the vertex list in
482
	 * this DWG file. This geometry is given by an array of Points.
483
	 * Besides, manage closed polylines and polylines with bulges in a GIS Data model.
484
     * It means that the arcs of the polylines will be done through a set of points and
485
     * a distance between these points.
486
	 */
487
	public void calculateGisModelDwgPolylines() {
488
		/*
489
		 * In Dwg 12 format, all vertices of a polyline are between polyline entity
490
		 * and endsec entity. Also, polylines dont save any handle of their vertices (first and last).
491
		 *
492
		 * After Dwg 12 version, we have the opposite case: polylines have handles/pointers to their
493
		 * first and last vertices.
494
		 *
495
		 * If dwg file is not V12, we must look for all polyline vertices (and we must to wait until
496
		 * all entities are readed).
497
		 * If dwg file is V12, all polylines already have their vertices.
498
		 * */
499
		if(! (dwgReader instanceof DwgFileV12Reader)){
500
			for (int i = 0; i < dwgPolylines.size(); i++){
501
				DwgObject pol = (DwgObject)dwgPolylines.get(i);
502
				if (pol instanceof IDwgPolyline) {
503
					((IDwgPolyline)pol).calculateGisModel(this);
504
				}//if
505
			}//for
506
		}
507
	}
508

  
509
    /**
510
     * Configure the geometry of the polylines in a DWG file from the vertex list in
511
     * this DWG file. This geometry is given by an array of Points
512
     * Besides, manage closed polylines and polylines with bulges in a GIS Data model.
513
     * It means that the arcs of the polylines will be done through a curvature
514
     * parameter called bulge associated with the points of the polyline.
515
     */
516
	//TODO Refactorizar para que solo se aplique a las Polilineas
517

  
518
//	public void calculateCadModelDwgPolylines() {
519
//		for (int i=0;i<dwgObjects.size();i++) {
520
//			DwgObject pol = (DwgObject)dwgObjects.get(i);
521
//			if (pol instanceof DwgPolyline2D) {
522
//				int flags = ((DwgPolyline2D)pol).getFlags();
523
//				int firstHandle = ((DwgPolyline2D)pol).getFirstVertexHandle().getOffset();
524
//				int lastHandle = ((DwgPolyline2D)pol).getLastVertexHandle().getOffset();
525
//				ArrayList pts = new ArrayList();
526
//				ArrayList bulges = new ArrayList();
527
//				double[] pt = new double[3];
528
//				for (int j=0;j<dwgObjects.size();j++) {
529
//					DwgObject firstVertex = (DwgObject)dwgObjects.get(j);
530
//					if (firstVertex instanceof DwgVertex2D) {
531
//						int vertexHandle = firstVertex.getHandle().getOffset();
532
//						if (vertexHandle==firstHandle) {
533
//							int k=0;
534
//							while (true) {
535
//								DwgObject vertex = (DwgObject)dwgObjects.get(j+k);
536
//								int vHandle = vertex.getHandle().getOffset();
537
//								if (vertex instanceof DwgVertex2D) {
538
//									pt = ((DwgVertex2D)vertex).getPoint();
539
//									pts.add(new Point2D.Double(pt[0], pt[1]));
540
//									double bulge = ((DwgVertex2D)vertex).getBulge();
541
//									bulges.add(new Double(bulge));
542
//									k++;
543
//									if (vHandle==lastHandle && vertex instanceof DwgVertex2D) {
544
//										break;
545
//									}
546
//								} else if (vertex instanceof DwgSeqend) {
547
//									break;
548
//								}
549
//							}
550
//						}
551
//					}
552
//				}
553
//				if (pts.size()>0) {
554
//					/*Point2D[] newPts = new Point2D[pts.size()];
555
//					if ((flags & 0x1)==0x1) {
556
//						newPts = new Point2D[pts.size()+1];
557
//						for (int j=0;j<pts.size();j++) {
558
//							newPts[j] = (Point2D)pts.get(j);
559
//						}
560
//						newPts[pts.size()] = (Point2D)pts.get(0);
561
//						bulges.add(new Double(0));
562
//					} else {
563
//						for (int j=0;j<pts.size();j++) {
564
//							newPts[j] = (Point2D)pts.get(j);
565
//						}
566
//					}*/
567
//					double[] bs = new double[bulges.size()];
568
//					for (int j=0;j<bulges.size();j++) {
569
//						bs[j] = ((Double)bulges.get(j)).doubleValue();
570
//					}
571
//					((DwgPolyline2D)pol).setBulges(bs);
572
//					//Point2D[] points = GisModelCurveCalculator.calculateGisModelBulge(newPts, bs);
573
//					Point2D[] points = new Point2D[pts.size()];
574
//					for (int j=0;j<pts.size();j++) {
575
//					    points[j] = (Point2D)pts.get(j);
576
//					}
577
//					((DwgPolyline2D)pol).setPts(points);
578
//				} else {
579
////					System.out.println("Encontrada polil�nea sin puntos ...");
580
//					// TODO: No se debe mandar nunca una polil�nea sin puntos, si esto
581
//					// ocurre es porque existe un error que hay que corregir ...
582
//				}
583
//			} else if (pol instanceof DwgPolyline3D) {
584
//			} else if (pol instanceof DwgLwPolyline && ((DwgLwPolyline)pol).getVertices()!=null) {
585
//			}
586
//		}
587
//	}
588

  
589
	/*
590
	 * TODO Revisar los bloques que son XREF
591
	 * */
592
	public void blockManagement2(){
593
		Iterator it = null;
594

  
595

  
596
		//dwg v12 blocks already has their entities added
597
		//for the rest of versions, we add block entities to their owner block
598
		if(! (dwgReader instanceof DwgFileV12Reader)){
599
			//once we have read all dwg entities, we look for all of them
600
			//that has a superentity that is a block (to fill in the entity list
601
			//of each block
602
			it = dwgObjects.iterator();
603
			int i = 0;
604
			while(it.hasNext()){
605
				DwgObject entity = (DwgObject)it.next();
606
				DwgObject superEnt = getDwgSuperEntity(entity);
607
				if(superEnt instanceof DwgBlockHeader){
608
					DwgBlockHeader blk = (DwgBlockHeader)superEnt;
609
					blk.addObject(entity);
610
					it.remove();//TODO Creo que esto es lento, mejor
611
					//el metodo original (en java solo se duplican las referencias)
612
					i++;
613
				}
614
			}//while
615
		}//if dwgfilev12
616

  
617
		//after that, we process the INSERTs
618
		it = insertList.iterator();
619
		while(it.hasNext()){
620
			DwgInsert insert = (DwgInsert) it.next();
621
			if(insert.isProcessed()){
622
				//It has been processed nexted to other insert
623
				continue;
624
			}
625
			insert.setProcessed(true);
626
			double[] p = insert.getInsertionPoint();
627
			Point2D point = new Point2D.Double(p[0], p[1]);
628
			double[] scale = insert.getScale();
629
			double rot = insert.getRotation();
630
			int blockHandle = insert.getBlockHeaderHandle().getOffset();
631
			manageInsert2(point, scale,
632
					rot, blockHandle,
633
					dwgObjects, handle_objects);
634
		}
635

  
636
}
637

  
638

  
639

  
640
	public void manageInsert2(Point2D insPoint, double[] scale,
641
			double rot, int bHandle,
642
			List dwgObjectsWithoutBlocks,
643
			Map handleObjectsWithoutBlocks) {
644

  
645
		DwgObject object = (DwgObject) handle_objects.get(new Integer(bHandle));
646
		if(object == null){
647
			logger.error("No hemos encontrado el BlockHeader cuyo handle es "+bHandle);
648
			return;
649
		}else if(! (object instanceof DwgBlockHeader)){
650
			//Hay un problema con la asignaci�n de handle
651
			//Un INSERT tiene como handle de Block una entidad que no es block
652
			logger.error("handle incorrecto." + object.getClass().getName() + " no es un blockheader");
653
			return;
654
		}
655

  
656
		DwgBlockHeader blockHeader = (DwgBlockHeader)object;
657
		double[] bPoint = blockHeader.getBasePoint();
658
		String bname = blockHeader.getName();
659
		if (bname.startsWith("*"))
660
			return;
661

  
662
		//TODO Cambiar por List. Done.
663
		List entities = blockHeader.getObjects();
664
		if(entities.size() == 0){
665
			logger.warn("El bloque "+blockHeader.getName()+" no tiene ninguna entidad");
666
		}
667
		Iterator blkEntIt = entities.iterator();
668
		while(blkEntIt.hasNext()){
669
			DwgObject obj = (DwgObject) blkEntIt.next();
670
			 manageBlockEntity(obj, bPoint,
671
			 		  insPoint, scale,
672
			 		  rot, dwgObjectsWithoutBlocks,
673
			 		  handleObjectsWithoutBlocks);
674
		}//while
675
	}
676

  
677

  
678
	public int getIndexOf(DwgObject dwgObject){
679
		return dwgObjects.indexOf(dwgObject);
680
	}
681

  
682

  
683

  
684
    /**
685
     * Changes the location of an object extracted from a block. This location will be
686
     * obtained through the insertion parameters from the block and the corresponding
687
     * insert.
688
     * @param entity, the entity extracted from the block.
689
     * @param bPoint, offset for the coordinates of the entity.
690
     * @param insPoint, coordinates of the insertion point for the entity.
691
     * @param scale, scale for the entity.
692
     * @param rot, rotation angle for the entity.
693
     * @param id, a count as a id.
694
     * @param dwgObjectsWithoutBlocks, a object list with the elements extracted from
695
     * the blocks.
696
     */
697
	private void manageBlockEntity(DwgObject entity,
698
									double[] bPoint,
699
									Point2D insPoint,
700
									double[] scale,
701
									double rot,
702
									List dwgObjectsWithoutBlocks,
703
									Map handleObjectsWithoutBlocks) {
704

  
705
		if(entity instanceof IDwgBlockMember){
706
			IDwgBlockMember blockMember = (IDwgBlockMember)entity;
707
			blockMember.transform2Block(bPoint, insPoint, scale, rot,
708
					dwgObjectsWithoutBlocks,
709
					handleObjectsWithoutBlocks,this);
710
		}
711

  
712
	}
713

  
714

  
715
	/**
716
	 * Add a DWG section offset to the dwgSectionOffsets vector
717
	 *
718
	 * @param key Define the DWG section
719
	 * @param seek Offset of the section
720
	 * @param size Size of the section
721
	 */
722
	public void addDwgSectionOffset(String key, int seek, int size) {
723
		DwgSectionOffset dso = new DwgSectionOffset(key, seek, size);
724
		dwgSectionOffsets.add(dso);
725
	}
726

  
727
	/**
728
     * Returns the offset of DWG section given by its key
729
	 *
730
     * @param key Define the DWG section
731
	 * @return int Offset of the section in the DWG file
732
	 */
733
	public int getDwgSectionOffset(String key) {
734
		int offset = 0;
735
		for (int i=0; i<dwgSectionOffsets.size(); i++) {
736
			DwgSectionOffset dso = (DwgSectionOffset)dwgSectionOffsets.get(i);
737
			String ikey = dso.getKey();
738
			if (key.equals(ikey)) {
739
				offset = dso.getSeek();
740
				break;
741
			}
742
		}
743
		return offset;
744
	}
745

  
746
	/**
747
	 * Add a DWG object offset to the dwgObjectOffsets vector
748
	 *
749
	 * @param handle Object handle
750
	 * @param offset Offset of the object data in the DWG file
751
	 */
752
	public void addDwgObjectOffset(int handle, int offset) {
753
		DwgObjectOffset doo = new DwgObjectOffset(handle, offset);
754
		dwgObjectOffsets.add(doo);
755
	}
756

  
757
	/**
758
	 *
759
	 * Add a DWG object to the dwgObject vector
760
	 *
761
	 * @param dwgObject DWG object
762
	 */
763
	public void addDwgObject(DwgObject dwgObject){
764
		//TODO Ver si puedo inicializar las listas especificas
765
		//(IDwgPolyline, etc) aqu?
766
		dwgObjects.add(dwgObject);
767
		/*
768
		 * TODO Quitar todos estos if-then y sustituirlos por un metodo callback
769
		 *
770
		 *
771
		 * (dwgObject.init(this), y que cada objeto haga lo que tenga que hacer
772
		 * */
773
		if(dwgObject instanceof DwgLayer){
774
			this.addDwgLayer((DwgLayer) dwgObject);
775
		}
776

  
777
		//Probamos a no aplicar las extrusiones
778

  
779
		if(dwgObject instanceof IDwgExtrusionable){
780
			((IDwgExtrusionable)dwgObject).applyExtrussion();
781

  
782
		}
783

  
784
		if(dwgObject instanceof IDwgPolyline){
785
			dwgPolylines.add(dwgObject);
786
		}
787
		if(dwgObject instanceof IDwg3DTestable){
788
			if(!isDwg3DFile()){//if its true, we dont check again
789
				setDwg3DFile(((IDwg3DTestable)dwgObject).has3DData());
790
			}
791
		}
792
		if(dwgObject instanceof DwgInsert){
793
			insertList.add(dwgObject);
794
		}
795

  
796
		if(dwgObject instanceof DwgBlockHeader){
797
			blockList.add(dwgObject);
798
		}
799
		handle_objects.put(new Integer(dwgObject.getHandle().getOffset()), dwgObject);
800

  
801

  
802
	}
803

  
804
	/**
805
	 * Returns dwgObjects from its insertion order (position
806
	 * in the dwg file)
807
	 *
808
	 * @param index order in the dwg file
809
	 * @return position
810
	 * */
811
	public DwgObject getDwgObject(int index){
812
		return (DwgObject) dwgObjects.get(index);
813
	}
814

  
815
	public DwgObject getDwgObjectFromHandle(int handle){
816
		return (DwgObject) handle_objects.get(new Integer(handle));
817
	}
818

  
819
	/**
820
	 * Add a DWG class to the dwgClasses vector
821
	 *
822
	 * @param dwgClass DWG class
823
	 */
824
	public void addDwgClass(DwgClass dwgClass){
825
		dwgClasses.add(dwgClass);
826
	}
827

  
828
	/**
829
	 * Add a DWG class to the dwgClasses vector
830
	 *
831
	 * @param dwgClass DWG class
832
	 */
833
	public void addDwgClass(DwgClass2004 dwgClass){
834
		dwgClasses.add(dwgClass);
835
	}
836

  
837

  
838
	public void printClasses(){
839
		logger.info("#### CLASSES ####");
840
		for(int i = 0; i < dwgClasses.size(); i++){
841
			DwgClass clazz = (DwgClass) dwgClasses.get(i);
842
			logger.info(clazz.toString());
843
		}
844
		logger.info("#############");
845
	}
846

  
847
	public List getDwgClasses(){
848
		return dwgClasses;
849
	}
850

  
851
    /**
852
     * @return Returns the dwgObjectOffsets.
853
     */
854
    public ArrayList getDwgObjectOffsets() {
855
        return dwgObjectOffsets;
856
    }
857
    /**
858
     * @return Returns the dwgObjects.
859
     */
860
    public List getDwgObjects() {
861
        return dwgObjects;
862
    }
863
    /**
864
     * @return Returns the fileName.
865
     */
866
    public String getFileName() {
867
        return fileName;
868
    }
869
    /**
870
     * @return Returns the dwg3DFile.
871
     */
872
    public boolean isDwg3DFile() {
873
        return dwg3DFile;
874
    }
875
    /**
876
     * @param dwg3DFile The dwg3DFile to set.
877
     */
878
    public void setDwg3DFile(boolean dwg3DFile) {
879
        this.dwg3DFile = dwg3DFile;
880
    }
881
}
tags/org.gvsig.dwg-2.0.248/org.gvsig.dwg.lib/src/main/java/org/gvsig/dwg/lib/ByteUtils.java
1
/* gvSIG. Sistema de Informaci�n Geogr�fica de la Generalitat Valenciana
2
 *
3
 * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
4
 *
5
 * This program is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU General Public License
7
 * as published by the Free Software Foundation; either version 2
8
 * of the License, or (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
18
 *
19
 * For more information, contact:
20
 *
21
 *  Generalitat Valenciana
22
 *   Conselleria d'Infraestructures i Transport
23
 *   Av. Blasco Ib��ez, 50
24
 *   46010 VALENCIA
25
 *   SPAIN
26
 *
27
 *      +34 963862235
28
 *   gvsig@gva.es
29
 *      www.gvsig.gva.es
30
 *
31
 *    or
32
 *
33
 *   IVER T.I. S.A
34
 *   Salamanca 50
35
 *   46005 Valencia
36
 *   Spain
37
 *
38
 *   +34 963163400
39
 *   dac@iver.es
40
 */
41
package org.gvsig.dwg.lib;
42
import java.math.BigInteger;
43

  
44

  
45
/**
46
 * Clase que engloba m�todos para trabajar con bytes. 
47
 *
48
 * @author Vicente Caballero Navarro
49
 */
50
public class ByteUtils {
51
	public static final int SIZE_BOOL = 1;
52
	public static final int SIZE_SHORT = 2;
53
	public static final int SIZE_INT = 4;
54
	public static final int SIZE_LONG = 8;
55
	public static final int SIZE_DOUBLE = 8;
56

  
57
	/** A nibble->char mapping for printing out bytes. */
58
	public static final char[] digits = {
59
			'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd',
60
			'e', 'f'
61
		};
62

  
63
	/**
64
	 * Return the <code>int</code> represented by the bytes in
65
	 * <code>data</code> staring at offset <code>offset[0]</code>.
66
	 *
67
	 * @param data the array from which to read
68
	 * @param offset A single element array whose first element is the index in
69
	 * 		  data from which to begin reading on function entry, and which on
70
	 * 		  function exit has been incremented by the number of bytes read.
71
	 *
72
	 * @return the value of the <code>int</code> decoded
73
	 */
74
	public static final int bytesToInt(byte[] data, int[] offset) {
75
		/**
76
		 * TODO: We use network-order within OceanStore, but temporarily
77
		 * supporting intel-order to work with some JNI code until JNI code is
78
		 * set to interoperate with network-order.
79
		 */
80
		int result = 0;
81

  
82
		for (int i = 0; i < SIZE_INT; ++i) {
83
			result <<= 8;
84
			result |= byteToUnsignedInt(data[offset[0]++]);
85
		}
86

  
87
		return result;
88
	}
89

  
90
	/**
91
	 * Write the bytes representing <code>i</code> into the byte array
92
	 * <code>data</code>, starting at index <code>offset [0]</code>, and
93
	 * increment <code>offset [0]</code> by the number of bytes written; if
94
	 * <code>data == null</code>, increment <code>offset [0]</code> by the
95
	 * number of bytes that would have been written otherwise.
96
	 *
97
	 * @param i the <code>int</code> to encode
98
	 * @param data The byte array to store into, or <code>null</code>.
99
	 * @param offset A single element array whose first element is the index in
100
	 * 		  data to begin writing at on function entry, and which on
101
	 * 		  function exit has been incremented by the number of bytes
102
	 * 		  written.
103
	 */
104
	public static final void intToBytes(int i, byte[] data, int[] offset) {
105
		/**
106
		 * TODO: We use network-order within OceanStore, but temporarily
107
		 * supporting intel-order to work with some JNI code until JNI code is
108
		 * set to interoperate with network-order.
109
		 */
110
		if (data != null) {
111
			for (int j = (offset[0] + SIZE_INT) - 1; j >= offset[0]; --j) {
112
				data[j] = (byte) i;
113
				i >>= 8;
114
			}
115
		}
116

  
117
		offset[0] += SIZE_INT;
118
	}
119

  
120
	/**
121
	 * Return the <code>short</code> represented by the bytes in
122
	 * <code>data</code> staring at offset <code>offset[0]</code>.
123
	 *
124
	 * @param data the array from which to read
125
	 * @param offset A single element array whose first element is the index in
126
	 * 		  data from which to begin reading on function entry, and which on
127
	 * 		  function exit has been incremented by the number of bytes read.
128
	 *
129
	 * @return the value of the <code>short</code> decoded
130
	 */
131
	public static final short bytesToShort(byte[] data, int[] offset) {
132
		/**
133
		 * TODO: We use network-order within OceanStore, but temporarily
134
		 * supporting intel-order to work with some JNI code until JNI code is
135
		 * set to interoperate with network-order.
136
		 */
137
		short result = 0;
138

  
139
		for (int i = 0; i < SIZE_SHORT; ++i) {
140
			result <<= 8;
141
			result |= (short) byteToUnsignedInt(data[offset[0]++]);
142
		}
143

  
144
		return result;
145
	}
146

  
147
	/**
148
	 * Write the bytes representing <code>s</code> into the byte array
149
	 * <code>data</code>, starting at index <code>offset [0]</code>, and
150
	 * increment <code>offset [0]</code> by the number of bytes written; if
151
	 * <code>data == null</code>, increment <code>offset [0]</code> by the
152
	 * number of bytes that would have been written otherwise.
153
	 *
154
	 * @param s the <code>short</code> to encode
155
	 * @param data The byte array to store into, or <code>null</code>.
156
	 * @param offset A single element array whose first element is the index in
157
	 * 		  data to begin writing at on function entry, and which on
158
	 * 		  function exit has been incremented by the number of bytes
159
	 * 		  written.
160
	 */
161
	public static final void shortToBytes(short s, byte[] data, int[] offset) {
162
		/**
163
		 * TODO: We use network-order within OceanStore, but temporarily
164
		 * supporting intel-order to work with some JNI code until JNI code is
165
		 * set to interoperate with network-order.
166
		 */
167
		if (data != null) {
168
			data[offset[0] + 1] = (byte) s;
169
			data[offset[0]] = (byte) (s >> 8);
170
		}
171

  
172
		offset[0] += SIZE_SHORT;
173
	}
174

  
175
	/**
176
	 * Return the <code>long</code> represented by the bytes in
177
	 * <code>data</code> staring at offset <code>offset[0]</code>.
178
	 *
179
	 * @param data the array from which to read
180
	 * @param offset A single element array whose first element is the index in
181
	 * 		  data from which to begin reading on  function entry, and which
182
	 * 		  on function exit has been incremented by the number of bytes
183
	 * 		  read.
184
	 *
185
	 * @return the value of the <code>long</code> decoded
186
	 */
187
	public static final long bytesToLong(byte[] data, int[] offset) {
188
		long result = 0;
189

  
190
		for (int i = 0; i < SIZE_LONG; ++i) {
191
			result <<= 8;
192

  
193
			int res = byteToUnsignedInt(data[offset[0]++]);
194
			result = result | res;
195
		}
196

  
197
		return result;
198
	}
199

  
200
	/**
201
	 * Write the bytes representing <code>l</code> into the byte array
202
	 * <code>data</code>, starting at index <code>offset [0]</code>, and
203
	 * increment <code>offset [0]</code> by the number of bytes written; if
204
	 * <code>data == null</code>, increment <code>offset [0]</code> by the
205
	 * number of bytes that would have been written otherwise.
206
	 *
207
	 * @param l the <code>long</code> to encode
208
	 * @param data The byte array to store into, or <code>null</code>.
209
	 * @param offset A single element array whose first element is the index in
210
	 * 		  data to begin writing at on function entry, and which on
211
	 * 		  function exit has been incremented by the number of bytes
212
	 * 		  written.
213
	 */
214
	public static final void longToBytes(long l, byte[] data, int[] offset) {
215
		/**
216
		 * TODO: We use network-order within OceanStore, but temporarily
217
		 * supporting intel-order to work with some JNI code until JNI code is
218
		 * set to interoperate with network-order.
219
		 */
220
		if (data != null) {
221
			for (int j = (offset[0] + SIZE_LONG) - 1; j >= offset[0]; --j) {
222
				data[j] = (byte) l;
223
				l >>= 8;
224
			}
225
		}
226

  
227
		offset[0] += SIZE_LONG;
228
	}
229

  
230
	/**
231
	 * Return the <code>double</code> represented by the bytes in
232
	 * <code>data</code> staring at offset <code>offset[0]</code>.
233
	 *
234
	 * @param data the array from which to read
235
	 * @param offset A single element array whose first element is the index in
236
	 * 		  data from which to begin reading on  function entry, and which
237
	 * 		  on function exit has been incremented by the number of bytes
238
	 * 		  read.
239
	 *
240
	 * @return the value of the <code>double</code> decoded
241
	 */
242
	public static final double bytesToDouble(byte[] data, int[] offset) {
243
		long bits = bytesToLong(data, offset);
244

  
245
		return Double.longBitsToDouble(bits);
246
	}
247

  
248
	/**
249
	 * Write the bytes representing <code>d</code> into the byte array
250
	 * <code>data</code>, starting at index <code>offset [0]</code>, and
251
	 * increment <code>offset [0]</code> by the number of bytes written; if
252
	 * <code>data == null</code>, increment <code>offset [0]</code> by the
253
	 * number of bytes that would have been written otherwise.
254
	 *
255
	 * @param d the <code>double</code> to encode
256
	 * @param data The byte array to store into, or <code>null</code>.
257
	 * @param offset A single element array whose first element is the index in
258
	 * 		  data to begin writing at on function entry, and which on
259
	 * 		  function exit has been incremented by the number of bytes
260
	 * 		  written.
261
	 */
262
	public static final void doubleToBytes(double d, byte[] data, int[] offset) {
263
		long bits = Double.doubleToLongBits(d);
264
		longToBytes(bits, data, offset);
265
	}
266

  
267
	/**
268
	 * Return the <code>String</code> represented by the bytes in
269
	 * <code>data</code> staring at offset <code>offset[0]</code>. This method
270
	 * relies on the user using the corresponding <code>stringToBytes</code>
271
	 * method to encode the <code>String</code>, so that it may properly
272
	 * retrieve the <code>String</code> length.
273
	 *
274
	 * @param data the array from which to read
275
	 * @param offset A single element array whose first element is the index in
276
	 * 		  data from which to begin reading on function entry, and which on
277
	 * 		  function exit has been incremented by the number of bytes read.
278
	 *
279
	 * @return the value of the <code>String</code> decoded
280
	 */
281
	public static final String bytesToString(byte[] data, int[] offset) {
282
		offset[0] = 0;
283

  
284
		int length = bytesToInt(data, offset);
285
		String st = null;
286

  
287
		if ((length < 0) || (length > data.length)) {
288
			st = new String(data);
289
		} else {
290
			st = new String(data, offset[0], length);
291
		}
292

  
293
		offset[0] += length;
294

  
295
		return st;
296
	}
297

  
298
	/**
299
	 * Write the bytes representing <code>s</code> into the byte array
300
	 * <code>data</code>, starting at index <code>offset [0]</code>, and
301
	 * increment <code>offset [0]</code> by the number of bytes written; if
302
	 * <code>data == null</code>, increment <code>offset [0]</code> by the
303
	 * number of bytes that would have been written otherwise.
304
	 *
305
	 * @param s the <code>String</code> to encode
306
	 * @param data The byte array to store into, or <code>null</code>.
307
	 * @param offset A single element array whose first element is the index in
308
	 * 		  data to begin writing at on function entry, and which on
309
	 * 		  function exit has been incremented by the number of bytes
310
	 * 		  written.
311
	 */
312
	public static final void stringToBytes(String s, byte[] data, int[] offset) {
313
		byte[] s_bytes = s.getBytes();
314

  
315
		if (data != null) {
316
			intToBytes(s_bytes.length, data, offset);
317
			memcpy(data, offset[0], s_bytes, 0, s_bytes.length);
318
		} else {
319
			offset[0] += SIZE_INT;
320
		}
321

  
322
		offset[0] += s_bytes.length;
323
	}
324

  
325
	/**
326
	 * Return the <code>boolean</code> represented by the bytes in
327
	 * <code>data</code> staring at offset <code>offset[0]</code>.
328
	 *
329
	 * @param data the array from which to read
330
	 * @param offset A single element array whose first element is the index in
331
	 * 		  data from which to begin reading on  function entry, and which
332
	 * 		  on function exit has been incremented by the number of bytes
333
	 * 		  read.
334
	 *
335
	 * @return the value of the <code>boolean</code> decoded
336
	 */
337
	public static final boolean bytesToBool(byte[] data, int[] offset) {
338
		boolean result = true;
339

  
340
		if (data[offset[0]] == 0) {
341
			result = false;
342
		}
343

  
344
		offset[0] += SIZE_BOOL;
345

  
346
		return result;
347
	}
348

  
349
	/**
350
	 * Write the bytes representing <code>b</code> into the byte array
351
	 * <code>data</code>, starting at index <code>offset [0]</code>, and
352
	 * increment <code>offset [0]</code> by the number of bytes written; if
353
	 * <code>data == null</code>, increment <code>offset [0]</code> by the
354
	 * number of bytes that would have been written otherwise.
355
	 *
356
	 * @param b the <code>boolean</code> to encode
357
	 * @param data The byte array to store into, or <code>null</code>.
358
	 * @param offset A single element array whose first element is the index in
359
	 * 		  data to begin writing at on function entry, and which on
360
	 * 		  function exit has been incremented by the number of bytes
361
	 * 		  written.
362
	 */
363
	public static final void boolToBytes(boolean b, byte[] data, int[] offset) {
364
		if (data != null) {
365
			data[offset[0]] = (byte) (b ? 1 : 0);
366
		}
367

  
368
		offset[0] += SIZE_BOOL;
369
	}
370

  
371
	/**
372
	 * Return the <code>BigInteger</code> represented by the bytes in
373
	 * <code>data</code> staring at offset <code>offset[0]</code>.
374
	 *
375
	 * @param data the array from which to read
376
	 * @param offset A single element array whose first element is the index in
377
	 * 		  data from which to begin reading on  function entry, and which
378
	 * 		  on function exit has been incremented by the number of bytes
379
	 * 		  read.
380
	 *
381
	 * @return the <code>BigInteger</code> decoded
382
	 */
383
	public static final BigInteger bytesToBigInteger(byte[] data, int[] offset) {
384
		int length = bytesToInt(data, offset);
385
		byte[] bytes = new byte[length];
386
		offset[0] += memcpy(bytes, 0, data, offset[0], length);
387

  
388
		return new BigInteger(bytes);
389
	}
390

  
391
	/**
392
	 * Write the bytes representing <code>n</code> into the byte array
393
	 * <code>data</code>, starting at index <code>offset [0]</code>, and
394
	 * increment <code>offset [0]</code> by the number of bytes written; if
395
	 * <code>data == null</code>, increment <code>offset [0]</code> by the
396
	 * number of bytes that would have been written otherwise.
397
	 *
398
	 * @param n the <code>BigInteger</code> to encode
399
	 * @param data The byte array to store into, or <code>null</code>.
400
	 * @param offset A single element array whose first element is the index in
401
	 * 		  data to begin writing at on function entry, and which on
402
	 * 		  function exit has been incremented by the number of bytes
403
	 * 		  written.
404
	 */
405
	public static final void bigIntegerToBytes(BigInteger n, byte[] data,
406
		int[] offset) {
407
		byte[] bytes = n.toByteArray();
408
		intToBytes(bytes.length, data, offset);
409
		offset[0] += memcpy(data, offset[0], bytes, 0, bytes.length);
410
	}
411

  
412
	/**
413
	 * Convert an array of <code>bytes</code>s into an array of
414
	 * <code>ints</code>.
415
	 *
416
	 * @param dst the array to write
417
	 * @param dst_offset the start offset in <code>dst</code>, times 4. This
418
	 * 		  measures the offset as if <code>dst</code> were an array of
419
	 * 		  <code>byte</code>s (rather than <code>int</code>s).
420
	 * @param src the array to read
421
	 * @param src_offset the start offset in <code>src</code>
422
	 * @param length the number of <code>byte</code>s to copy.
423
	 */
424
	public static final void bytesToInts(int[] dst, int dst_offset, byte[] src,
425
		int src_offset, int length) {
426
		if ((src == null) || (dst == null) ||
427
				((src_offset + length) > src.length) ||
428
				((dst_offset + length) > (dst.length * 4)) ||
429
				((dst_offset % 4) != 0) || ((length % 4) != 0)) {
430
			croak("bytesToInts parameters are invalid" + " src==" + src +
431
				" dst==" + dst +
432
				(((src == null) || (dst == null)) ? " "
433
												  : (" (src_offset+length)>src.length==" +
434
				(src_offset + length) + ">" + src.length +
435
				" (dst_offset+length)>(dst.length*4)==" +
436
				(dst_offset + length) + ">" + (dst.length * 4) +
437
				" (dst_offset%4)==" + (dst_offset % 4) + " (length%4)==" +
438
				(length % 4) + " dest.length==" + dst.length + " length==" +
439
				length)));
440
		}
441

  
442
		// Convert parameters to normal format
443
		int[] offset = new int[1];
444
		offset[0] = src_offset;
445

  
446
		int int_dst_offset = dst_offset / 4;
447

  
448
		for (int i = 0; i < (length / 4); ++i) {
449
			dst[int_dst_offset++] = bytesToInt(src, offset);
450
		}
451
	}
452

  
453
	/**
454
	 * Convert an array of <code>int</code>s into an array of
455
	 * <code>bytes</code>.
456
	 *
457
	 * @param dst the array to write
458
	 * @param dst_offset the start offset in <code>dst</code>
459
	 * @param src the array to read
460
	 * @param src_offset the start offset in <code>src</code>, times 4. This
461
	 * 		  measures the offset as if <code>src</code> were an array of
462
	 * 		  <code>byte</code>s (rather than <code>int</code>s).
463
	 * @param length the number of <code>byte</code>s to copy.
464
	 */
465
	public static final void intsToBytes(byte[] dst, int dst_offset, int[] src,
466
		int src_offset, int length) {
467
		if ((src == null) || (dst == null) ||
468
				((dst_offset + length) > dst.length) ||
469
				((src_offset + length) > (src.length * 4)) ||
470
				((src_offset % 4) != 0) || ((length % 4) != 0)) {
471
			croak("intsToBytes parameters are invalid:" + " src=" + src +
472
				" dst=" + dst + " (dst_offset=" + dst_offset + " + length=" +
473
				length + ")=" + (dst_offset + length) + " > dst.length=" +
474
				((dst == null) ? 0 : dst.length) + " (src_offset=" +
475
				src_offset + " + length=" + length + ")=" +
476
				(src_offset + length) + " > (src.length=" +
477
				((src == null) ? 0 : src.length) + "*4)=" +
478
				((src == null) ? 0 : (src.length * 4)) + " (src_offset=" +
479
				src_offset + " % 4)=" + (src_offset % 4) + " != 0" +
480
				" (length=" + length + " % 4)=" + (length % 4) + " != 0");
481
		}
482

  
483
		// Convert parameters to normal format
484
		int[] offset = new int[1];
485
		offset[0] = dst_offset;
486

  
487
		int int_src_offset = src_offset / 4;
488

  
489
		for (int i = 0; i < (length / 4); ++i) {
490
			intToBytes(src[int_src_offset++], dst, offset);
491
		}
492
	}
493

  
494
	/**
495
	 * Convert a <code>byte</code> into an unsigned integer.
496
	 *
497
	 * @param b the <code>byte</code> to cast
498
	 *
499
	 * @return a postiive <code>int</code> whose lowest byte contains the bits
500
	 * 		   of <code>b</code>.
501
	 */
502
	public static final int byteToUnsignedInt(byte b) {
503
		return ((int) b) & 0xff;
504
	}
505

  
506
	/**
507
	 * Copy contents of one array of <code>bytes</code> into another. If either
508
	 * array is <code>null</code>, simply return the <code>length</code>
509
	 * parameter directly.
510
	 *
511
	 * @param dst the array to write, or <code>null</code>
512
	 * @param dst_offset the start offset in <code>dst</code>
513
	 * @param src the array to read, or <code>null</code>
514
	 * @param src_offset the start offset in <code>src</code>
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff