/*
* Copyright (C) 2011.
*
* 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.List;
import uk.me.parabola.imgfmt.app.ImgFileWriter;
import uk.me.parabola.imgfmt.app.srt.Sort;
import uk.me.parabola.imgfmt.app.srt.SortKey;
/**
* An index of countries sorted by name with pointers to the other country related sections.
* There is only one per name, not per name and map.
*
* @author Steve Ratcliffe
*/
public class Mdr29
extends MdrSection
implements HasHeaderFlags
{
private final List<Mdr29Record
> index =
new ArrayList<>();
private int max17
;
public Mdr29
(MdrConfig config
) {
setConfig
(config
);
}
public void buildFromCountries
(List<Mdr14Record
> countries
) {
Sort sort = getConfig
().
getSort();
List<SortKey<Mdr14Record
>> keys = MdrUtils.
sortList(sort, countries
);
// Sorted by name, for every new name we allocate a new 29 record and set the same one in every
// country with the same name.
String lastName =
null;
Mdr29Record mdr29 =
null;
for (SortKey<Mdr14Record
> key : keys
) {
Mdr14Record country = key.
getObject();
String name = country.
getName();
if (!name.
equals(lastName
)) {
mdr29 =
new Mdr29Record
();
mdr29.
setName(name
);
mdr29.
setStrOffset(country.
getStrOff());
index.
add(mdr29
);
lastName = name
;
}
assert mdr29
!=
null;
country.
setMdr29(mdr29
);
}
}
protected void preWriteImpl
() {
if (!index.
isEmpty()) {
Mdr29Record r = index.
get(index.
size() -
1);
this.
max17 = r.
getMdr17();
}
}
/**
* Write out the contents of this section.
*
* @param writer Where to write it.
*/
public void writeSectData
(ImgFileWriter writer
) {
int magic = getExtraValue
();
boolean hasString =
(magic
& 1) !=
0;
boolean has26 =
(magic
& 0x8
) !=
0;
boolean has17 =
(magic
& 0x30
) !=
0;
PointerSizes sizes = getSizes
();
int size24 = sizes.
getSize(24);
int size22 = sizes.
getSize(22);
int size25 = sizes.
getSize(5); // NB appears to be size of 5 (cities), not 25 (cities with country).
int size26 = has26
? sizes.
getSize(26):
0;
int size17 = numberToPointerSize
(max17
);
for (Mdr29Record record : index
) {
putN
(writer, size24, record.
getMdr24());
if (hasString
)
putStringOffset
(writer, record.
getStrOffset());
putN
(writer, size22, record.
getMdr22());
putN
(writer, size25, record.
getMdr25());
if (has26
)
putN
(writer, size26, record.
getMdr26());
if (has17
)
putN
(writer, size17, record.
getMdr17());
}
}
/**
* The size of a record in the section. This is not a constant and might vary
* on various factors, such as the file version, if we are preparing for a
* device, the number of maps etc.
*
* @return The size of a record in this section.
*/
public int getItemSize
() {
PointerSizes sizes = getSizes
();
int size = sizes.
getSize(24)
+ sizes.
getSize(22)
+ sizes.
getSize(5) // NB: not 25
;
if (isForDevice
()) {
size += numberToPointerSize
(max17
);
} else {
size += sizes.
getStrOffSize();
size += sizes.
getSize(26);
}
return size
;
}
/**
* The number of records in this section.
*
* @return The number of items in the section.
*/
protected int numberOfItems
() {
return index.
size();
}
/**
* Unknown flags.
*
* As there are 4 bits set and 4 extra fields, that might be it. Compare
* to mdr28 where there are 3 extra fields and 3 bits set. Just a guess...
*/
public int getExtraValue
() {
if (isForDevice
()) {
int magic = 0x6
; // 22 and 25
magic |= numberToPointerSize
(max17
) << 4;
return magic
; // +17, -26, -strings
}
else
return 0xf
; // strings, 22, 25 and 26
}
}