Changeset 33012 in osm for applications/editors/josm/plugins/o5m/src
- Timestamp:
- 2016-09-24T14:37:01+02:00 (8 years ago)
- Location:
- applications/editors/josm/plugins/o5m/src/org/openstreetmap/josm/plugins/o5m
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
applications/editors/josm/plugins/o5m/src/org/openstreetmap/josm/plugins/o5m/O5mConstants.java
r32833 r33012 1 // JOSM o5m plugin. 2 // Copyright (C) 2013 Gerd Petermann 3 // 4 // This program is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // This program is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with this program. If not, see <http://www.gnu.org/licenses/>. 1 // License: GPL. For details, see LICENSE file. 16 2 package org.openstreetmap.josm.plugins.o5m; 17 3 … … 30 16 * File extension. 31 17 */ 32 public static finalString EXTENSION = "o5m";18 String EXTENSION = "o5m"; 33 19 34 20 /** 35 21 * File filter used in import/export dialogs. 36 22 */ 37 public static final ExtensionFileFilter FILE_FILTER = new ExtensionFileFilter(EXTENSION, EXTENSION, tr("OSM Server Files o5m compressed") + " (*."+EXTENSION+")"); 23 ExtensionFileFilter FILE_FILTER = new ExtensionFileFilter(EXTENSION, EXTENSION, 24 tr("OSM Server Files o5m compressed") + " (*."+EXTENSION+")"); 38 25 } -
applications/editors/josm/plugins/o5m/src/org/openstreetmap/josm/plugins/o5m/O5mPlugin.java
r32833 r33012 1 // JOSM o5m plugin. 2 // Copyright (C) 2013 Gerd Petermann 3 // 4 // This program is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // This program is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with this program. If not, see <http://www.gnu.org/licenses/>. 1 // License: GPL. For details, see LICENSE file. 16 2 package org.openstreetmap.josm.plugins.o5m; 17 3 -
applications/editors/josm/plugins/o5m/src/org/openstreetmap/josm/plugins/o5m/io/O5mImporter.java
r32833 r33012 1 // JOSM o5m plugin. 2 // Copyright (C) 2013 Gerd Petermann 3 // 4 // This program is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // This program is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with this program. If not, see <http://www.gnu.org/licenses/>. 1 // License: GPL. For details, see LICENSE file. 16 2 package org.openstreetmap.josm.plugins.o5m.io; 17 3 … … 37 23 } 38 24 39 /* (non-Javadoc) 40 * @see org.openstreetmap.josm.io.OsmImporter#parseDataSet(java.io.InputStream, org.openstreetmap.josm.gui.progress.ProgressMonitor) 41 */ 42 @Override 43 protected DataSet parseDataSet(InputStream in, ProgressMonitor progressMonitor) throws IllegalDataException { 44 return O5mReader.parseDataSet(in, progressMonitor); 45 } 25 @Override 26 protected DataSet parseDataSet(InputStream in, ProgressMonitor progressMonitor) throws IllegalDataException { 27 return O5mReader.parseDataSet(in, progressMonitor); 28 } 46 29 47 48 try(CachedFile cf = new CachedFile(source)){49 50 51 30 protected DataSet parseDataSet(final String source) throws IOException, IllegalDataException { 31 try (CachedFile cf = new CachedFile(source)) { 32 return parseDataSet(cf.getInputStream(), NullProgressMonitor.INSTANCE); 33 } 34 } 52 35 } -
applications/editors/josm/plugins/o5m/src/org/openstreetmap/josm/plugins/o5m/io/O5mReader.java
r32857 r33012 1 // JOSM o5m plugin. 2 // Copyright (C) 2013 Gerd Petermann 3 // 4 // This program is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // This program is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with this program. If not, see <http://www.gnu.org/licenses/>. 1 // License: GPL. For details, see LICENSE file. 16 2 package org.openstreetmap.josm.plugins.o5m.io; 17 3 … … 52 38 */ 53 39 public class O5mReader extends AbstractReader { 54 55 56 40 public IllegalDataException exception = null; 41 private boolean discourageUpload; 42 57 43 private static void checkCoordinates(LatLon coor) throws IllegalDataException { 58 44 if (!coor.isValid()) { … … 73 59 } 74 60 75 // O5M data set constants 76 private static final int NODE_DATASET = 0x10; 77 private static final int WAY_DATASET = 0x11; 78 private static final int REL_DATASET = 0x12; 79 private static final int BBOX_DATASET = 0xdb; 80 private static final int TIMESTAMP_DATASET = 0xdc; 81 private static final int HEADER_DATASET = 0xe0; 82 private static final int EOD_FLAG = 0xfe; 83 private static final int RESET_FLAG = 0xff; 84 85 private static final int EOF_FLAG = -1; 86 87 // o5m constants 88 private static final int STRING_TABLE_SIZE = 15000; 89 private static final int MAX_STRING_PAIR_SIZE = 250 + 2; 90 private static final String[] REL_REF_TYPES = {"node", "way", "relation", "?"}; 91 private static final double FACTOR = 1d/1000000000; // used with 100*<Val>*FACTOR 92 93 private final BufferedInputStream fis; 94 private InputStream is; 95 private ByteArrayInputStream bis; 96 97 // buffer for byte -> String conversions 98 private byte[] cnvBuffer; 99 100 private byte[] ioBuf; 101 private int ioPos; 102 // the o5m string table 103 private String[][] stringTable; 104 private String[] stringPair; 105 private int currStringTablePos; 106 // a counter that must be maintained by all routines that read data from the stream 107 private int bytesToRead; 108 // total number of bytes read from stream 109 long countBytes; 110 111 // for delta calculations 112 private long lastNodeId; 113 private long lastWayId; 114 private long lastRelId; 115 private long lastRef[]; 116 private long lastTs; 117 private long lastChangeSet; 118 private int lastLon,lastLat; 119 private int version; 120 private User osmUser; 121 private String header; 122 /** 123 * A parser for the o5m format 124 * @param stream The InputStream that contains the OSM data in o5m format 125 */ 126 O5mReader(InputStream stream) { 127 this.fis = new BufferedInputStream(stream); 128 is = fis; 129 this.cnvBuffer = new byte[4000]; // OSM data should not contain string pairs with length > 512 130 this.ioBuf = new byte[8192]; 131 this.ioPos = 0; 132 this.stringPair = new String[2]; 133 this.lastRef = new long[3]; 134 reset(); 135 } 136 137 /** 138 * parse the input stream 139 */ 140 public void parse(){ 141 try { 142 int start = is.read(); 143 ++countBytes; 144 if (start != RESET_FLAG) 145 throw new IOException(tr("wrong header byte ") + Integer.toHexString(start)); 146 readFile(); 147 if (discourageUpload) 148 ds.setUploadDiscouraged(true); 149 } catch (IOException e) { 150 e.printStackTrace(); 151 } 152 } 153 154 private void readFile() throws IOException{ 155 boolean done = false; 156 while(!done){ 157 is = fis; 158 long size = 0; 159 int fileType = is.read(); 160 ++countBytes; 161 if (fileType >= 0 && fileType < 0xf0){ 162 bytesToRead = 0; 163 size = readUnsignedNum64FromStream(); 164 countBytes += size - bytesToRead; // bytesToRead is negative 165 bytesToRead = (int)size; 166 167 switch(fileType){ 168 case NODE_DATASET: 169 case WAY_DATASET: 170 case REL_DATASET: 171 case BBOX_DATASET: 172 case TIMESTAMP_DATASET: 173 case HEADER_DATASET: 174 if (bytesToRead > ioBuf.length){ 175 ioBuf = new byte[bytesToRead+100]; 176 } 177 int bytesRead = 0; 178 int neededBytes = bytesToRead; 179 while (neededBytes > 0){ 180 bytesRead += is.read(ioBuf, bytesRead, neededBytes); 181 neededBytes -= bytesRead; 182 } 183 ioPos = 0; 184 bis = new ByteArrayInputStream(ioBuf,0,bytesToRead); 185 is = bis; 186 break; 187 default: 188 } 189 } 190 if (fileType == EOF_FLAG) done = true; 191 else if (fileType == NODE_DATASET) readNode(); 192 else if (fileType == WAY_DATASET) readWay(); 193 else if (fileType == REL_DATASET) readRel(); 194 else if (fileType == BBOX_DATASET) readBBox(); 195 else if (fileType == TIMESTAMP_DATASET) readFileTimestamp(); 196 else if (fileType == HEADER_DATASET) readHeader(); 197 else if (fileType == EOD_FLAG) done = true; 198 else if (fileType == RESET_FLAG) reset(); 199 else { 200 if (fileType < 0xf0 )skip(size); // skip unknown data set 201 } 202 } 203 } 204 205 /** 206 * read (and ignore) the file timestamp data set 207 */ 208 private void readFileTimestamp(){ 209 /*long fileTimeStamp = */readSignedNum64(); 210 } 211 212 /** 213 * Skip the given number of bytes 214 * @param bytes 215 * @throws IOException 216 */ 217 private void skip(long bytes)throws IOException{ 218 long toSkip = bytes; 219 while (toSkip > 0) 220 toSkip -= is.skip(toSkip); 221 } 222 223 /** 224 * read the bounding box data set 225 * @throws IOException 226 */ 227 private void readBBox() { 228 double minlon = FACTOR * 100L * readSignedNum32(); 229 double minlat = FACTOR * 100L * readSignedNum32(); 230 double maxlon = FACTOR * 100L * readSignedNum32(); 231 double maxlat = FACTOR * 100L * readSignedNum32(); 61 // O5M data set constants 62 private static final int NODE_DATASET = 0x10; 63 private static final int WAY_DATASET = 0x11; 64 private static final int REL_DATASET = 0x12; 65 private static final int BBOX_DATASET = 0xdb; 66 private static final int TIMESTAMP_DATASET = 0xdc; 67 private static final int HEADER_DATASET = 0xe0; 68 private static final int EOD_FLAG = 0xfe; 69 private static final int RESET_FLAG = 0xff; 70 71 private static final int EOF_FLAG = -1; 72 73 // o5m constants 74 private static final int STRING_TABLE_SIZE = 15000; 75 private static final int MAX_STRING_PAIR_SIZE = 250 + 2; 76 private static final String[] REL_REF_TYPES = {"node", "way", "relation", "?"}; 77 private static final double FACTOR = 1d/1000000000; // used with 100*<Val>*FACTOR 78 79 private final BufferedInputStream fis; 80 private InputStream is; 81 private ByteArrayInputStream bis; 82 83 // buffer for byte -> String conversions 84 private byte[] cnvBuffer; 85 86 private byte[] ioBuf; 87 private int ioPos; 88 // the o5m string table 89 private String[][] stringTable; 90 private String[] stringPair; 91 private int currStringTablePos; 92 // a counter that must be maintained by all routines that read data from the stream 93 private int bytesToRead; 94 // total number of bytes read from stream 95 long countBytes; 96 97 // for delta calculations 98 private long lastNodeId; 99 private long lastWayId; 100 private long lastRelId; 101 private long[] lastRef; 102 private long lastTs; 103 private long lastChangeSet; 104 private int lastLon, lastLat; 105 private int version; 106 private User osmUser; 107 private String header; 108 /** 109 * A parser for the o5m format 110 * @param stream The InputStream that contains the OSM data in o5m format 111 */ 112 O5mReader(InputStream stream) { 113 this.fis = new BufferedInputStream(stream); 114 is = fis; 115 this.cnvBuffer = new byte[4000]; // OSM data should not contain string pairs with length > 512 116 this.ioBuf = new byte[8192]; 117 this.ioPos = 0; 118 this.stringPair = new String[2]; 119 this.lastRef = new long[3]; 120 reset(); 121 } 122 123 /** 124 * parse the input stream 125 */ 126 public void parse() { 127 try { 128 int start = is.read(); 129 ++countBytes; 130 if (start != RESET_FLAG) 131 throw new IOException(tr("wrong header byte ") + Integer.toHexString(start)); 132 readFile(); 133 if (discourageUpload) 134 ds.setUploadDiscouraged(true); 135 } catch (IOException e) { 136 e.printStackTrace(); 137 } 138 } 139 140 private void readFile() throws IOException { 141 boolean done = false; 142 while (!done) { 143 is = fis; 144 long size = 0; 145 int fileType = is.read(); 146 ++countBytes; 147 if (fileType >= 0 && fileType < 0xf0) { 148 bytesToRead = 0; 149 size = readUnsignedNum64FromStream(); 150 countBytes += size - bytesToRead; // bytesToRead is negative 151 bytesToRead = (int) size; 152 153 switch(fileType) { 154 case NODE_DATASET: 155 case WAY_DATASET: 156 case REL_DATASET: 157 case BBOX_DATASET: 158 case TIMESTAMP_DATASET: 159 case HEADER_DATASET: 160 if (bytesToRead > ioBuf.length) { 161 ioBuf = new byte[bytesToRead+100]; 162 } 163 int bytesRead = 0; 164 int neededBytes = bytesToRead; 165 while (neededBytes > 0) { 166 bytesRead += is.read(ioBuf, bytesRead, neededBytes); 167 neededBytes -= bytesRead; 168 } 169 ioPos = 0; 170 bis = new ByteArrayInputStream(ioBuf, 0, bytesToRead); 171 is = bis; 172 break; 173 default: 174 } 175 } 176 if (fileType == EOF_FLAG) done = true; 177 else if (fileType == NODE_DATASET) readNode(); 178 else if (fileType == WAY_DATASET) readWay(); 179 else if (fileType == REL_DATASET) readRel(); 180 else if (fileType == BBOX_DATASET) readBBox(); 181 else if (fileType == TIMESTAMP_DATASET) readFileTimestamp(); 182 else if (fileType == HEADER_DATASET) readHeader(); 183 else if (fileType == EOD_FLAG) done = true; 184 else if (fileType == RESET_FLAG) reset(); 185 else { 186 if (fileType < 0xf0) skip(size); // skip unknown data set 187 } 188 } 189 } 190 191 /** 192 * read (and ignore) the file timestamp data set 193 */ 194 private void readFileTimestamp() { 195 /*long fileTimeStamp = */readSignedNum64(); 196 } 197 198 /** 199 * Skip the given number of bytes 200 * @param bytes number of bytes to skip 201 * @throws IOException in case of I/O error 202 */ 203 private void skip(long bytes) throws IOException { 204 long toSkip = bytes; 205 while (toSkip > 0) { 206 toSkip -= is.skip(toSkip); 207 } 208 } 209 210 /** 211 * read the bounding box data set 212 * @throws IOException in case of I/O error 213 */ 214 private void readBBox() { 215 double minlon = FACTOR * 100L * readSignedNum32(); 216 double minlat = FACTOR * 100L * readSignedNum32(); 217 double maxlon = FACTOR * 100L * readSignedNum32(); 218 double maxlat = FACTOR * 100L * readSignedNum32(); 232 219 233 220 Bounds b = new Bounds(minlat, minlon, maxlat, maxlon); … … 238 225 Main.error("Invalid Bounds: "+b); 239 226 } 240 } 241 242 /** 243 * read a node data set 244 * @throws IOException 245 */ 246 private void readNode() throws IOException{ 247 if (exception != null) 248 return; 249 try{ 250 lastNodeId += readSignedNum64(); 251 if (bytesToRead == 0) 252 return; // only nodeId: this is a delete action, we ignore it 253 readVersionTsAuthor(); 254 255 if (bytesToRead == 0) 256 return; // only nodeId+version: this is a delete action, we ignore it 257 int lon = readSignedNum32() + lastLon; lastLon = lon; 258 int lat = readSignedNum32() + lastLat; lastLat = lat; 259 260 double flon = FACTOR * (100L*lon); 261 double flat = FACTOR * (100L*lat); 262 assert flat >= -90.0 && flat <= 90.0; 263 assert flon >= -180.0 && flon <= 180.0; 264 if (version == 0) 265 discourageUpload = true; 266 Node node = new Node(lastNodeId, version == 0 ? 1:version); 267 node.setCoor(new LatLon(flat, flon).getRoundedToOsmPrecision()); 268 269 270 checkCoordinates(node.getCoor()); 271 checkChangesetId(lastChangeSet); 272 node.setChangesetId((int) lastChangeSet); 273 // User id 274 if (lastTs != 0){ 275 checkTimestamp(lastTs); 276 node.setTimestamp(new Date(lastTs * 1000)); 277 if (osmUser != null) 278 node.setUser(osmUser); 279 } 280 if (bytesToRead > 0){ 281 Map<String, String> keys = readTags(); 282 node.setKeys(keys); 283 } 284 externalIdMap.put(node.getPrimitiveId(), node); 285 } catch (IllegalDataException e) { 286 exception = e; 287 } 288 289 } 290 291 /** 292 * read a way data set 293 * @throws IOException 294 */ 295 private void readWay() throws IOException{ 296 if (exception != null) 297 return; 298 try{ 299 lastWayId += readSignedNum64(); 300 if (bytesToRead == 0) 301 return; // only wayId: this is a delete action, we ignore it 302 303 readVersionTsAuthor(); 304 if (bytesToRead == 0) 305 return; // only wayId + version: this is a delete action, we ignore it 306 if (version == 0) 307 discourageUpload = true; 308 final Way way = new Way(lastWayId, version == 0 ? 1:version); 309 checkChangesetId(lastChangeSet); 310 way.setChangesetId((int) lastChangeSet); 311 // User id 312 if (lastTs != 0){ 313 checkTimestamp(lastTs); 314 way.setTimestamp(new Date(lastTs * 1000)); 315 if (osmUser != null) 316 way.setUser(osmUser); 317 } 318 319 long refSize = readUnsignedNum32(); 320 long stop = bytesToRead - refSize; 321 Collection<Long> nodeIds = new ArrayList<>(); 322 323 while(bytesToRead > stop){ 324 lastRef[0] += readSignedNum64(); 325 nodeIds.add(lastRef[0]); 326 } 327 328 Map<String, String> keys = readTags(); 329 way.setKeys(keys); 330 ways.put(way.getUniqueId(), nodeIds); 331 externalIdMap.put(way.getPrimitiveId(), way); 332 } catch (IllegalDataException e) { 333 exception = e; 334 } 335 336 } 337 338 /** 339 * read a relation data set 340 * @throws IOException 341 */ 342 private void readRel() throws IOException{ 343 if (exception != null) 344 return; 345 try{ 346 lastRelId += readSignedNum64(); 347 if (bytesToRead == 0) 348 return; // only relId: this is a delete action, we ignore it 349 readVersionTsAuthor(); 350 if (bytesToRead == 0) 351 return; // only relId + version: this is a delete action, we ignore it 352 if (version == 0) 353 discourageUpload = true; 354 final Relation rel = new Relation(lastRelId, version == 0 ? 1:version); 355 checkChangesetId(lastChangeSet); 356 rel.setChangesetId((int) lastChangeSet); 357 if (lastTs != 0){ 358 checkTimestamp(lastTs); 359 rel.setTimestamp(new Date(lastTs * 1000)); 360 if (osmUser != null) 361 rel.setUser(osmUser); 362 } 363 364 long refSize = readUnsignedNum32(); 365 long stop = bytesToRead - refSize; 366 Collection<RelationMemberData> members = new ArrayList<>(); 367 while(bytesToRead > stop){ 368 long deltaRef = readSignedNum64(); 369 int refType = readRelRef(); 370 String role = stringPair[1]; 371 lastRef[refType] += deltaRef; 372 long memId = lastRef[refType]; 373 OsmPrimitiveType type = null; 374 375 if (refType == 0){ 376 type = OsmPrimitiveType.NODE; 377 } 378 else if (refType == 1){ 379 type = OsmPrimitiveType.WAY; 380 } 381 else if (refType == 2){ 382 type = OsmPrimitiveType.RELATION; 383 } 384 members.add(new RelationMemberData(role, type, memId)); 385 } 386 Map<String, String> keys = readTags(); 387 rel.setKeys(keys); 388 relations.put(rel.getUniqueId(), members); 389 externalIdMap.put(rel.getPrimitiveId(), rel); 390 } catch (IllegalDataException e) { 391 exception = e; 392 } 393 } 394 395 private Map<String, String> readTags() throws IOException{ 396 Map<String, String> keys = new HashMap<>(); 397 while (bytesToRead > 0){ 398 readStringPair(); 399 keys.put(stringPair[0],stringPair[1]); 400 } 401 assert bytesToRead == 0; 402 return keys; 403 } 404 /** 405 * Store a new string pair (length check must be performed by caller) 406 */ 407 private void storeStringPair(){ 408 stringTable[0][currStringTablePos] = stringPair[0]; 409 stringTable[1][currStringTablePos] = stringPair[1]; 410 ++currStringTablePos; 411 if (currStringTablePos >= STRING_TABLE_SIZE) 412 currStringTablePos = 0; 413 } 414 415 /** 416 * set stringPair to the values referenced by given string reference 417 * No checking is performed. 418 * @param ref valid values are 1 .. STRING_TABLE_SIZE 419 */ 420 private void setStringRefPair(int ref){ 421 int pos = currStringTablePos - ref; 422 if (pos < 0) 423 pos += STRING_TABLE_SIZE; 424 stringPair[0] = stringTable[0][pos]; 425 stringPair[1] = stringTable[1][pos]; 426 } 427 428 /** 429 * Read version, time stamp and change set and author. 430 * We are not interested in the values, but we have to maintain the string table. 431 * @throws IOException 432 */ 433 434 private void readVersionTsAuthor() throws IOException { 435 stringPair[0] = null; 436 stringPair[1] = null; 437 version = readUnsignedNum32(); 438 if (version != 0){ 439 // version info 440 long ts = readSignedNum64() + lastTs; lastTs = ts; 441 if (ts != 0){ 442 long changeSet = readSignedNum32() + lastChangeSet; lastChangeSet = changeSet; 443 readAuthor(); 444 } 445 } 446 } 447 /** 448 * Read author . 449 * @throws IOException 450 */ 451 private void readAuthor() throws IOException{ 452 int stringRef = readUnsignedNum32(); 453 if (stringRef == 0){ 454 long toReadStart = bytesToRead; 455 long uidNum = readUnsignedNum64(); 456 if (uidNum == 0) 457 stringPair[0] = ""; 458 else{ 459 stringPair[0] = Long.toString(uidNum); 460 ioPos++; // skip terminating zero from uid 461 --bytesToRead; 462 } 463 int start = 0; 464 int buffPos = 0; 465 stringPair[1] = null; 466 while(stringPair[1] == null){ 467 final int b = ioBuf[ioPos++]; 468 --bytesToRead; 469 cnvBuffer[buffPos++] = (byte) b; 470 471 if (b == 0) 472 stringPair[1] = new String(cnvBuffer, start, buffPos-1, "UTF-8"); 473 } 474 long bytes = toReadStart - bytesToRead; 475 if (bytes <= MAX_STRING_PAIR_SIZE) 476 storeStringPair(); 477 } 478 else 479 setStringRefPair(stringRef); 480 if (stringPair[0] != null && stringPair[0].isEmpty() == false){ 481 long uid = Long.parseLong(stringPair[0]); 482 osmUser = User.createOsmUser(uid, stringPair[1]); 483 } 484 else 485 osmUser = null; 486 } 487 488 /** 489 * read object type ("0".."2") concatenated with role (single string) 490 * @return 0..3 for type (3 means unknown) 491 */ 492 private int readRelRef () throws IOException{ 493 int refType = -1; 494 long toReadStart = bytesToRead; 495 int stringRef = readUnsignedNum32(); 496 if (stringRef == 0){ 497 refType = ioBuf[ioPos++] - 0x30; 498 --bytesToRead; 499 500 if (refType < 0 || refType > 2) 501 refType = 3; 502 stringPair[0] = REL_REF_TYPES[refType]; 503 504 int start = 0; 505 int buffPos = 0; 506 stringPair[1] = null; 507 while(stringPair[1] == null){ 508 final int b = ioBuf[ioPos++]; 509 --bytesToRead; 510 cnvBuffer[buffPos++] = (byte)b; 511 512 if (b == 0) 513 stringPair[1] = new String(cnvBuffer, start, buffPos-1, "UTF-8"); 514 } 515 long bytes = toReadStart - bytesToRead; 516 if (bytes <= MAX_STRING_PAIR_SIZE) 517 storeStringPair(); 518 } 519 else { 520 setStringRefPair(stringRef); 521 char c = stringPair[0].charAt(0); 522 switch (c){ 523 case 'n': refType = 0; break; 524 case 'w': refType = 1; break; 525 case 'r': refType = 2; break; 526 default: refType = 3; 527 } 528 } 529 return refType; 530 } 531 532 /** 533 * read a string pair (see o5m definition) 534 * @throws IOException 535 */ 536 private void readStringPair() throws IOException{ 537 int stringRef = readUnsignedNum32(); 538 if (stringRef == 0){ 539 long toReadStart = bytesToRead; 540 int cnt = 0; 541 int buffPos = 0; 542 int start = 0; 543 while (cnt < 2){ 544 final int b = ioBuf[ioPos++]; 545 --bytesToRead; 546 cnvBuffer[buffPos++] = (byte)b; 547 548 if (b == 0){ 549 stringPair[cnt] = new String(cnvBuffer, start, buffPos-start-1, "UTF-8"); 550 ++cnt; 551 start = buffPos; 552 } 553 } 554 long bytes = toReadStart - bytesToRead; 555 if (bytes <= MAX_STRING_PAIR_SIZE) 556 storeStringPair(); 557 } 558 else 559 setStringRefPair(stringRef); 560 } 561 562 /** reset the delta values and string table */ 563 private void reset(){ 564 lastNodeId = 0; lastWayId = 0; lastRelId = 0; 565 lastRef[0] = 0; lastRef[1] = 0;lastRef[2] = 0; 566 lastTs = 0; lastChangeSet = 0; 567 lastLon = 0; lastLat = 0; 568 stringTable = new String[2][STRING_TABLE_SIZE]; 569 currStringTablePos = 0; 570 } 571 572 /** 573 * read and verify o5m header (known values are o5m2 and o5c2) 574 * @throws IOException 575 */ 576 private void readHeader() throws IOException { 577 if (ioBuf[0] != 'o' || ioBuf[1] != '5' || (ioBuf[2]!='c'&&ioBuf[2]!='m') ||ioBuf[3] != '2' ){ 578 throw new IOException(tr("unsupported header")); 579 } 580 header = new String(ioBuf, 0, 3, "UTF-8"); 581 } 582 583 /** 584 * read a varying length signed number (see o5m definition) 585 * @return the number 586 * @throws IOException 587 */ 588 private int readSignedNum32() { 589 int result; 590 int b = ioBuf[ioPos++]; 591 --bytesToRead; 592 result = b; 593 if ((b & 0x80) == 0){ // just one byte 594 if ((b & 0x01) == 1) 595 return -1-(result>>1); 596 return result>>1; 597 } 598 int sign = b & 0x01; 599 result = (result & 0x7e)>>1; 600 int fac = 0x40; 601 while (((b = ioBuf[ioPos++]) & 0x80) != 0){ // more bytes will follow 602 --bytesToRead; 603 result += fac * (b & 0x7f) ; 604 fac <<= 7; 605 } 606 --bytesToRead; 607 result += fac * b; 608 if (sign == 1) // negative 609 return -1-result; 610 return result; 611 612 } 613 614 /** 615 * read a varying length signed number (see o5m definition) 616 * @return the number 617 * @throws IOException 618 */ 619 private long readSignedNum64() { 620 long result; 621 int b = ioBuf[ioPos++]; 622 --bytesToRead; 623 result = b; 624 if ((b & 0x80) == 0){ // just one byte 625 if ((b & 0x01) == 1) 626 return -1-(result>>1); 627 return result>>1; 628 } 629 int sign = b & 0x01; 630 result = (result & 0x7e)>>1; 631 long fac = 0x40; 632 while (((b = ioBuf[ioPos++]) & 0x80) != 0){ // more bytes will follow 633 --bytesToRead; 634 result += fac * (b & 0x7f) ; 635 fac <<= 7; 636 } 637 --bytesToRead; 638 result += fac * b; 639 if (sign == 1) // negative 640 return -1-result; 641 return result; 642 643 } 644 645 /** 646 * read a varying length unsigned number (see o5m definition) 647 * @return a long 648 * @throws IOException 649 */ 650 private long readUnsignedNum64FromStream()throws IOException { 651 int b = is.read(); 652 --bytesToRead; 653 long result = b; 654 if ((b & 0x80) == 0){ // just one byte 655 return result; 656 } 657 result &= 0x7f; 658 long fac = 0x80; 659 while (((b = is.read()) & 0x80) != 0){ // more bytes will follow 660 --bytesToRead; 661 result += fac * (b & 0x7f) ; 662 fac <<= 7; 663 } 664 --bytesToRead; 665 result += fac * b; 666 return result; 667 } 668 669 670 /** 671 * read a varying length unsigned number (see o5m definition) 672 * @return a long 673 * @throws IOException 674 */ 675 private long readUnsignedNum64(){ 676 int b = ioBuf[ioPos++]; 677 --bytesToRead; 678 long result = b; 679 if ((b & 0x80) == 0){ // just one byte 680 return result; 681 } 682 result &= 0x7f; 683 long fac = 0x80; 684 while (((b = ioBuf[ioPos++]) & 0x80) != 0){ // more bytes will follow 685 --bytesToRead; 686 result += fac * (b & 0x7f) ; 687 fac <<= 7; 688 } 689 --bytesToRead; 690 result += fac * b; 691 return result; 692 } 693 694 /** 695 * read a varying length unsigned number (see o5m definition) 696 * is similar to the 64 bit version. 697 * @return an int 698 * @throws IOException 699 */ 700 private int readUnsignedNum32(){ 701 int b = ioBuf[ioPos++]; 702 --bytesToRead; 703 int result = b; 704 if ((b & 0x80) == 0){ // just one byte 705 return result; 706 } 707 result &= 0x7f; 708 long fac = 0x80; 709 while (((b = ioBuf[ioPos++]) & 0x80) != 0){ // more bytes will follow 710 --bytesToRead; 711 result += fac * (b & 0x7f) ; 712 fac <<= 7; 713 } 714 --bytesToRead; 715 result += fac * b; 716 return result; 717 } 718 719 227 } 228 229 /** 230 * read a node data set 231 * @throws IOException in case of I/O error 232 */ 233 private void readNode() throws IOException { 234 if (exception != null) 235 return; 236 try { 237 lastNodeId += readSignedNum64(); 238 if (bytesToRead == 0) 239 return; // only nodeId: this is a delete action, we ignore it 240 readVersionTsAuthor(); 241 242 if (bytesToRead == 0) 243 return; // only nodeId+version: this is a delete action, we ignore it 244 int lon = readSignedNum32() + lastLon; lastLon = lon; 245 int lat = readSignedNum32() + lastLat; lastLat = lat; 246 247 double flon = FACTOR * (100L*lon); 248 double flat = FACTOR * (100L*lat); 249 assert flat >= -90.0 && flat <= 90.0; 250 assert flon >= -180.0 && flon <= 180.0; 251 if (version == 0) 252 discourageUpload = true; 253 Node node = new Node(lastNodeId, version == 0 ? 1 : version); 254 node.setCoor(new LatLon(flat, flon).getRoundedToOsmPrecision()); 255 256 257 checkCoordinates(node.getCoor()); 258 checkChangesetId(lastChangeSet); 259 node.setChangesetId((int) lastChangeSet); 260 // User id 261 if (lastTs != 0) { 262 checkTimestamp(lastTs); 263 node.setTimestamp(new Date(lastTs * 1000)); 264 if (osmUser != null) 265 node.setUser(osmUser); 266 } 267 if (bytesToRead > 0) { 268 Map<String, String> keys = readTags(); 269 node.setKeys(keys); 270 } 271 externalIdMap.put(node.getPrimitiveId(), node); 272 } catch (IllegalDataException e) { 273 exception = e; 274 } 275 276 } 277 278 /** 279 * read a way data set 280 * @throws IOException in case of I/O error 281 */ 282 private void readWay() throws IOException { 283 if (exception != null) 284 return; 285 try { 286 lastWayId += readSignedNum64(); 287 if (bytesToRead == 0) 288 return; // only wayId: this is a delete action, we ignore it 289 290 readVersionTsAuthor(); 291 if (bytesToRead == 0) 292 return; // only wayId + version: this is a delete action, we ignore it 293 if (version == 0) 294 discourageUpload = true; 295 final Way way = new Way(lastWayId, version == 0 ? 1 : version); 296 checkChangesetId(lastChangeSet); 297 way.setChangesetId((int) lastChangeSet); 298 // User id 299 if (lastTs != 0) { 300 checkTimestamp(lastTs); 301 way.setTimestamp(new Date(lastTs * 1000)); 302 if (osmUser != null) 303 way.setUser(osmUser); 304 } 305 306 long refSize = readUnsignedNum32(); 307 long stop = bytesToRead - refSize; 308 Collection<Long> nodeIds = new ArrayList<>(); 309 310 while (bytesToRead > stop) { 311 lastRef[0] += readSignedNum64(); 312 nodeIds.add(lastRef[0]); 313 } 314 315 Map<String, String> keys = readTags(); 316 way.setKeys(keys); 317 ways.put(way.getUniqueId(), nodeIds); 318 externalIdMap.put(way.getPrimitiveId(), way); 319 } catch (IllegalDataException e) { 320 exception = e; 321 } 322 323 } 324 325 /** 326 * read a relation data set 327 * @throws IOException in case of I/O error 328 */ 329 private void readRel() throws IOException { 330 if (exception != null) 331 return; 332 try { 333 lastRelId += readSignedNum64(); 334 if (bytesToRead == 0) 335 return; // only relId: this is a delete action, we ignore it 336 readVersionTsAuthor(); 337 if (bytesToRead == 0) 338 return; // only relId + version: this is a delete action, we ignore it 339 if (version == 0) 340 discourageUpload = true; 341 final Relation rel = new Relation(lastRelId, version == 0 ? 1 : version); 342 checkChangesetId(lastChangeSet); 343 rel.setChangesetId((int) lastChangeSet); 344 if (lastTs != 0) { 345 checkTimestamp(lastTs); 346 rel.setTimestamp(new Date(lastTs * 1000)); 347 if (osmUser != null) 348 rel.setUser(osmUser); 349 } 350 351 long refSize = readUnsignedNum32(); 352 long stop = bytesToRead - refSize; 353 Collection<RelationMemberData> members = new ArrayList<>(); 354 while (bytesToRead > stop) { 355 long deltaRef = readSignedNum64(); 356 int refType = readRelRef(); 357 String role = stringPair[1]; 358 lastRef[refType] += deltaRef; 359 long memId = lastRef[refType]; 360 OsmPrimitiveType type = null; 361 362 if (refType == 0) { 363 type = OsmPrimitiveType.NODE; 364 } else if (refType == 1) { 365 type = OsmPrimitiveType.WAY; 366 } else if (refType == 2) { 367 type = OsmPrimitiveType.RELATION; 368 } 369 members.add(new RelationMemberData(role, type, memId)); 370 } 371 Map<String, String> keys = readTags(); 372 rel.setKeys(keys); 373 relations.put(rel.getUniqueId(), members); 374 externalIdMap.put(rel.getPrimitiveId(), rel); 375 } catch (IllegalDataException e) { 376 exception = e; 377 } 378 } 379 380 private Map<String, String> readTags() throws IOException { 381 Map<String, String> keys = new HashMap<>(); 382 while (bytesToRead > 0) { 383 readStringPair(); 384 keys.put(stringPair[0], stringPair[1]); 385 } 386 assert bytesToRead == 0; 387 return keys; 388 } 389 390 /** 391 * Store a new string pair (length check must be performed by caller) 392 */ 393 private void storeStringPair() { 394 stringTable[0][currStringTablePos] = stringPair[0]; 395 stringTable[1][currStringTablePos] = stringPair[1]; 396 ++currStringTablePos; 397 if (currStringTablePos >= STRING_TABLE_SIZE) 398 currStringTablePos = 0; 399 } 400 401 /** 402 * set stringPair to the values referenced by given string reference 403 * No checking is performed. 404 * @param ref valid values are 1 .. STRING_TABLE_SIZE 405 */ 406 private void setStringRefPair(int ref) { 407 int pos = currStringTablePos - ref; 408 if (pos < 0) 409 pos += STRING_TABLE_SIZE; 410 stringPair[0] = stringTable[0][pos]; 411 stringPair[1] = stringTable[1][pos]; 412 } 413 414 /** 415 * Read version, time stamp and change set and author. 416 * We are not interested in the values, but we have to maintain the string table. 417 * @throws IOException in case of I/O error 418 */ 419 private void readVersionTsAuthor() throws IOException { 420 stringPair[0] = null; 421 stringPair[1] = null; 422 version = readUnsignedNum32(); 423 if (version != 0) { 424 // version info 425 long ts = readSignedNum64() + lastTs; lastTs = ts; 426 if (ts != 0) { 427 long changeSet = readSignedNum32() + lastChangeSet; lastChangeSet = changeSet; 428 readAuthor(); 429 } 430 } 431 } 432 433 /** 434 * Read author . 435 * @throws IOException in case of I/O error 436 */ 437 private void readAuthor() throws IOException { 438 int stringRef = readUnsignedNum32(); 439 if (stringRef == 0) { 440 long toReadStart = bytesToRead; 441 long uidNum = readUnsignedNum64(); 442 if (uidNum == 0) 443 stringPair[0] = ""; 444 else { 445 stringPair[0] = Long.toString(uidNum); 446 ioPos++; // skip terminating zero from uid 447 --bytesToRead; 448 } 449 int start = 0; 450 int buffPos = 0; 451 stringPair[1] = null; 452 while (stringPair[1] == null) { 453 final int b = ioBuf[ioPos++]; 454 --bytesToRead; 455 cnvBuffer[buffPos++] = (byte) b; 456 457 if (b == 0) 458 stringPair[1] = new String(cnvBuffer, start, buffPos-1, "UTF-8"); 459 } 460 long bytes = toReadStart - bytesToRead; 461 if (bytes <= MAX_STRING_PAIR_SIZE) 462 storeStringPair(); 463 } else 464 setStringRefPair(stringRef); 465 if (stringPair[0] != null && stringPair[0].isEmpty() == false) { 466 long uid = Long.parseLong(stringPair[0]); 467 osmUser = User.createOsmUser(uid, stringPair[1]); 468 } else 469 osmUser = null; 470 } 471 472 /** 473 * read object type ("0".."2") concatenated with role (single string) 474 * @return 0..3 for type (3 means unknown) 475 */ 476 private int readRelRef() throws IOException { 477 int refType = -1; 478 long toReadStart = bytesToRead; 479 int stringRef = readUnsignedNum32(); 480 if (stringRef == 0) { 481 refType = ioBuf[ioPos++] - 0x30; 482 --bytesToRead; 483 484 if (refType < 0 || refType > 2) 485 refType = 3; 486 stringPair[0] = REL_REF_TYPES[refType]; 487 488 int start = 0; 489 int buffPos = 0; 490 stringPair[1] = null; 491 while (stringPair[1] == null) { 492 final int b = ioBuf[ioPos++]; 493 --bytesToRead; 494 cnvBuffer[buffPos++] = (byte) b; 495 496 if (b == 0) 497 stringPair[1] = new String(cnvBuffer, start, buffPos-1, "UTF-8"); 498 } 499 long bytes = toReadStart - bytesToRead; 500 if (bytes <= MAX_STRING_PAIR_SIZE) 501 storeStringPair(); 502 } else { 503 setStringRefPair(stringRef); 504 char c = stringPair[0].charAt(0); 505 switch (c) { 506 case 'n': refType = 0; break; 507 case 'w': refType = 1; break; 508 case 'r': refType = 2; break; 509 default: refType = 3; 510 } 511 } 512 return refType; 513 } 514 515 /** 516 * read a string pair (see o5m definition) 517 * @throws IOException in case of I/O error 518 */ 519 private void readStringPair() throws IOException { 520 int stringRef = readUnsignedNum32(); 521 if (stringRef == 0) { 522 long toReadStart = bytesToRead; 523 int cnt = 0; 524 int buffPos = 0; 525 int start = 0; 526 while (cnt < 2) { 527 final int b = ioBuf[ioPos++]; 528 --bytesToRead; 529 cnvBuffer[buffPos++] = (byte) b; 530 531 if (b == 0) { 532 stringPair[cnt] = new String(cnvBuffer, start, buffPos-start-1, "UTF-8"); 533 ++cnt; 534 start = buffPos; 535 } 536 } 537 long bytes = toReadStart - bytesToRead; 538 if (bytes <= MAX_STRING_PAIR_SIZE) 539 storeStringPair(); 540 } else 541 setStringRefPair(stringRef); 542 } 543 544 /** reset the delta values and string table */ 545 private void reset() { 546 lastNodeId = 0; lastWayId = 0; lastRelId = 0; 547 lastRef[0] = 0; lastRef[1] = 0; lastRef[2] = 0; 548 lastTs = 0; lastChangeSet = 0; 549 lastLon = 0; lastLat = 0; 550 stringTable = new String[2][STRING_TABLE_SIZE]; 551 currStringTablePos = 0; 552 } 553 554 /** 555 * read and verify o5m header (known values are o5m2 and o5c2) 556 * @throws IOException in case of I/O error 557 */ 558 private void readHeader() throws IOException { 559 if (ioBuf[0] != 'o' || ioBuf[1] != '5' || (ioBuf[2] != 'c' && ioBuf[2] != 'm') || ioBuf[3] != '2') { 560 throw new IOException(tr("unsupported header")); 561 } 562 header = new String(ioBuf, 0, 3, "UTF-8"); 563 } 564 565 /** 566 * read a varying length signed number (see o5m definition) 567 * @return the number 568 * @throws IOException in case of I/O error 569 */ 570 private int readSignedNum32() { 571 int result; 572 int b = ioBuf[ioPos++]; 573 --bytesToRead; 574 result = b; 575 if ((b & 0x80) == 0) { // just one byte 576 if ((b & 0x01) == 1) 577 return -1-(result >> 1); 578 return result >> 1; 579 } 580 int sign = b & 0x01; 581 result = (result & 0x7e) >> 1; 582 int fac = 0x40; 583 while (((b = ioBuf[ioPos++]) & 0x80) != 0) { // more bytes will follow 584 --bytesToRead; 585 result += fac * (b & 0x7f); 586 fac <<= 7; 587 } 588 --bytesToRead; 589 result += fac * b; 590 if (sign == 1) // negative 591 return -1-result; 592 return result; 593 594 } 595 596 /** 597 * read a varying length signed number (see o5m definition) 598 * @return the number 599 * @throws IOException in case of I/O error 600 */ 601 private long readSignedNum64() { 602 long result; 603 int b = ioBuf[ioPos++]; 604 --bytesToRead; 605 result = b; 606 if ((b & 0x80) == 0) { // just one byte 607 if ((b & 0x01) == 1) 608 return -1-(result >> 1); 609 return result >> 1; 610 } 611 int sign = b & 0x01; 612 result = (result & 0x7e) >> 1; 613 long fac = 0x40; 614 while (((b = ioBuf[ioPos++]) & 0x80) != 0) { // more bytes will follow 615 --bytesToRead; 616 result += fac * (b & 0x7f); 617 fac <<= 7; 618 } 619 --bytesToRead; 620 result += fac * b; 621 if (sign == 1) // negative 622 return -1-result; 623 return result; 624 625 } 626 627 /** 628 * read a varying length unsigned number (see o5m definition) 629 * @return a long 630 * @throws IOException in case of I/O error 631 */ 632 private long readUnsignedNum64FromStream()throws IOException { 633 int b = is.read(); 634 --bytesToRead; 635 long result = b; 636 if ((b & 0x80) == 0) { // just one byte 637 return result; 638 } 639 result &= 0x7f; 640 long fac = 0x80; 641 while (((b = is.read()) & 0x80) != 0) { // more bytes will follow 642 --bytesToRead; 643 result += fac * (b & 0x7f); 644 fac <<= 7; 645 } 646 --bytesToRead; 647 result += fac * b; 648 return result; 649 } 650 651 652 /** 653 * read a varying length unsigned number (see o5m definition) 654 * @return a long 655 * @throws IOException in case of I/O error 656 */ 657 private long readUnsignedNum64() { 658 int b = ioBuf[ioPos++]; 659 --bytesToRead; 660 long result = b; 661 if ((b & 0x80) == 0) { // just one byte 662 return result; 663 } 664 result &= 0x7f; 665 long fac = 0x80; 666 while (((b = ioBuf[ioPos++]) & 0x80) != 0) { // more bytes will follow 667 --bytesToRead; 668 result += fac * (b & 0x7f); 669 fac <<= 7; 670 } 671 --bytesToRead; 672 result += fac * b; 673 return result; 674 } 675 676 /** 677 * read a varying length unsigned number (see o5m definition) 678 * is similar to the 64 bit version. 679 * @return an int 680 * @throws IOException in case of I/O error 681 */ 682 private int readUnsignedNum32() { 683 int b = ioBuf[ioPos++]; 684 --bytesToRead; 685 int result = b; 686 if ((b & 0x80) == 0) { // just one byte 687 return result; 688 } 689 result &= 0x7f; 690 long fac = 0x80; 691 while (((b = ioBuf[ioPos++]) & 0x80) != 0) { // more bytes will follow 692 --bytesToRead; 693 result += fac * (b & 0x7f); 694 fac <<= 7; 695 } 696 --bytesToRead; 697 result += fac * b; 698 return result; 699 } 700 701 720 702 721 703 /**
Note:
See TracChangeset
for help on using the changeset viewer.