Rev 3408 |
Blame |
Compare with Previous |
Last modification |
View Log
| RSS feed
/*
* Copyright (C) 2009.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 or
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*/
package uk.me.parabola.imgfmt.app.mdr;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import uk.me.parabola.imgfmt.app.ImgFileWriter;
/**
* The section MDR 1 contains a list of maps and for each map
* an offset to a reverse index for that map.
*
* The reverse index consists of a number of sections, that I call sub-sections
* here. The sub-sections are all lists of record numbers in other sections
* in the MDR that contain records belonging to more than one map.
*
* Using the index you could extract records that belong to an individual map
* from other MDR sections without having to go through them all and check
* which map they belong to.
*
* The subsections are as follows:
*
* sub1 points into MDR 11 (POIs)
* sub2 points into MDR 10 (POI types)
* sub3 points into MDR 7 (street names)
* sub4 points into MDR 5 (cities)
* sub5 points into MDR 6 (zips)
* sub6 points into MDR 20
* sub7 points into MDR 21
* sub8 points into MDR 22
*
* @author Steve Ratcliffe
*/
public class Mdr1
extends MdrSection
implements HasHeaderFlags
{
private final List<Mdr1Record
> maps =
new ArrayList<>();
private int[] mapping
;
public Mdr1
(MdrConfig config
) {
setConfig
(config
);
}
/**
* Add a map. Create an MDR1 record for it and also allocate its reverse
* index if this is not for a device.
* @param mapNumber The map index number.
* @param index The map index.
*/
public void addMap
(int mapNumber,
int index
) {
assert index
> 0;
Mdr1Record rec =
new Mdr1Record
(mapNumber, getConfig
());
rec.
setMapIndex(index
);
maps.
add(rec
);
if (!isForDevice
()) {
Mdr1MapIndex mapIndex =
new Mdr1MapIndex
();
rec.
setMdrMapIndex(mapIndex
);
}
}
/**
* The maps must be sorted in numerical order.
*/
public void finish
() {
Collections.
sort(maps,
new Comparator<Mdr1Record
>() {
public int compare
(Mdr1Record o1, Mdr1Record o2
) {
if (o1.
getMapNumber() == o2.
getMapNumber())
return 0;
else if (o1.
getMapNumber() < o2.
getMapNumber())
return -
1;
else
return 1;
}
});
// Used to renumber all the existing (pre-sorted) map index numbers.
mapping =
new int[maps.
size()];
int count =
1;
for (Mdr1Record r : maps
) {
mapping
[r.
getMapIndex()-
1] = count
;
count++
;
}
}
public void writeSubSections
(ImgFileWriter writer
) {
if (isForDevice
())
return;
for (Mdr1Record rec : maps
) {
rec.
setIndexOffset(writer.
position());
Mdr1MapIndex mapIndex = rec.
getMdrMapIndex();
mapIndex.
writeSubSection(writer
);
}
}
/**
* This is written right at the end after we know all the offsets in
* the MDR 1 record.
* @param writer The mdr 1 records are written out to this writer.
*/
public void writeSectData
(ImgFileWriter writer
) {
boolean revIndex =
(getExtraValue
() & 1) !=
0;
for (Mdr1Record rec : maps
) {
writer.
putInt(rec.
getMapNumber());
if (revIndex
)
writer.
putInt(rec.
getIndexOffset());
}
}
public int getItemSize
() {
return isForDevice
()? 4:
8;
}
public void setStartPosition
(int sectionNumber
) {
if (isForDevice
())
return;
for (Mdr1Record mi : maps
)
mi.
getMdrMapIndex().
startSection(sectionNumber
);
}
public void setEndPosition
(int sectionNumber
) {
if (isForDevice
())
return;
for (Mdr1Record mi : maps
) {
mi.
getMdrMapIndex().
endSection(sectionNumber
);
}
}
public void setPointerSize
(int sectionSize,
int recordSize
) {
for (Mdr1Record mi : maps
) {
Mdr1MapIndex mapIndex = mi.
getMdrMapIndex();
mapIndex.
setPointerSize(sectionSize, recordSize
);
}
}
public void addPointer
(int mapNumber,
int recordNumber
) {
Mdr1MapIndex mi = maps.
get(mapNumber -
1).
getMdrMapIndex();
mi.
addPointer(recordNumber
);
}
/**
* The number of records in this section.
*
* @return The number of items in the section.
*/
protected int numberOfItems
() {
return maps.
size();
}
public int getExtraValue
() {
int magic =
0;
if (!isForDevice
())
magic |=
1;
return magic
;
}
public int sortedMapIndex
(int n
) {
return mapping
[n-
1];
}
}