2013-04-18 23:35:02 +02:00
|
|
|
package net.osmand.util;
|
|
|
|
|
|
|
|
|
|
|
|
import java.io.Closeable;
|
|
|
|
import java.io.EOFException;
|
|
|
|
import java.io.File;
|
|
|
|
import java.io.FileInputStream;
|
|
|
|
import java.io.IOException;
|
|
|
|
import java.io.InputStream;
|
|
|
|
import java.io.OutputStream;
|
|
|
|
import java.text.DateFormat;
|
|
|
|
import java.util.Date;
|
|
|
|
import java.util.Locale;
|
|
|
|
|
|
|
|
import net.osmand.PlatformUtil;
|
|
|
|
|
|
|
|
import org.apache.commons.logging.Log;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Basic algorithms that are not in jdk
|
|
|
|
*/
|
|
|
|
public class Algorithms {
|
|
|
|
private static final int BUFFER_SIZE = 1024;
|
|
|
|
private static final Log log = PlatformUtil.getLog(Algorithms.class);
|
|
|
|
|
|
|
|
public static boolean isEmpty(String s){
|
|
|
|
return s == null || s.length() == 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Determine whether a file is a ZIP File.
|
|
|
|
*/
|
|
|
|
public static boolean isZipFile(File file) throws IOException {
|
|
|
|
if (file.isDirectory()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (!file.canRead()) {
|
|
|
|
throw new IOException("Cannot read file " + file.getAbsolutePath());
|
|
|
|
}
|
|
|
|
if (file.length() < 4) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
FileInputStream in = new FileInputStream(file);
|
|
|
|
int test = readInt(in);
|
|
|
|
in.close();
|
|
|
|
return test == 0x504b0304;
|
|
|
|
}
|
|
|
|
|
|
|
|
private static final int readInt(InputStream in) throws IOException {
|
|
|
|
int ch1 = in.read();
|
|
|
|
int ch2 = in.read();
|
|
|
|
int ch3 = in.read();
|
|
|
|
int ch4 = in.read();
|
|
|
|
if ((ch1 | ch2 | ch3 | ch4) < 0)
|
|
|
|
throw new EOFException();
|
|
|
|
return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
|
|
|
|
}
|
|
|
|
|
|
|
|
public static String capitalizeFirstLetterAndLowercase(String s) {
|
|
|
|
if (s != null && s.length() > 1) {
|
|
|
|
// not very efficient algorithm
|
|
|
|
return Character.toUpperCase(s.charAt(0)) + s.substring(1).toLowerCase();
|
|
|
|
} else {
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static boolean objectEquals(Object a, Object b){
|
|
|
|
if(a == null){
|
|
|
|
return b == null;
|
|
|
|
} else {
|
|
|
|
return a.equals(b);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public static int extractFirstIntegerNumber(String s) {
|
|
|
|
int i = 0;
|
|
|
|
for (int k = 0; k < s.length(); k++) {
|
|
|
|
if (Character.isDigit(s.charAt(k))) {
|
|
|
|
i = i * 10 + (s.charAt(k) - '0');
|
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static String extractIntegerSuffix(String s) {
|
|
|
|
int k = 0;
|
|
|
|
for (; k < s.length(); k++) {
|
|
|
|
if (!Character.isDigit(s.charAt(k))) {
|
|
|
|
return s.substring(k);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static void streamCopy(InputStream in, OutputStream out) throws IOException{
|
|
|
|
byte[] b = new byte[BUFFER_SIZE];
|
|
|
|
int read;
|
|
|
|
while ((read = in.read(b)) != -1) {
|
|
|
|
out.write(b, 0, read);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void oneByteStreamCopy(InputStream in, OutputStream out) throws IOException{
|
|
|
|
int read;
|
|
|
|
while ((read = in.read()) != -1) {
|
|
|
|
out.write(read);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void closeStream(Closeable stream){
|
|
|
|
try {
|
|
|
|
if(stream != null){
|
|
|
|
stream.close();
|
|
|
|
}
|
|
|
|
} catch(IOException e){
|
|
|
|
log.warn("Closing stream warn", e); //$NON-NLS-1$
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void updateAllExistingImgTilesToOsmandFormat(File f){
|
|
|
|
if(f.isDirectory()){
|
|
|
|
for(File c : f.listFiles()){
|
|
|
|
updateAllExistingImgTilesToOsmandFormat(c);
|
|
|
|
}
|
|
|
|
} else if(f.getName().endsWith(".png") || f.getName().endsWith(".jpg")){ //$NON-NLS-1$ //$NON-NLS-2$
|
|
|
|
f.renameTo(new File(f.getAbsolutePath() + ".tile")); //$NON-NLS-1$
|
|
|
|
} else if(f.getName().endsWith(".andnav2")) { //$NON-NLS-1$
|
|
|
|
f.renameTo(new File(f.getAbsolutePath().substring(0, f.getAbsolutePath().length() - ".andnav2".length()) + ".tile")); //$NON-NLS-1$ //$NON-NLS-2$
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
public static boolean removeAllFiles(File f) {
|
|
|
|
if (f == null) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (f.isDirectory()) {
|
|
|
|
File[] fs = f.listFiles();
|
|
|
|
if(fs != null) {
|
|
|
|
for (File c : fs) {
|
|
|
|
removeAllFiles(c);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return f.delete();
|
|
|
|
} else {
|
|
|
|
return f.delete();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static long parseLongFromBytes(byte[] bytes, int offset) {
|
|
|
|
long o= 0xff & bytes[offset + 7];
|
|
|
|
o = o << 8 | (0xff & bytes[offset + 6]);
|
|
|
|
o = o << 8 | (0xff & bytes[offset + 5]);
|
|
|
|
o = o << 8 | (0xff & bytes[offset + 4]);
|
|
|
|
o = o << 8 | (0xff & bytes[offset + 3]);
|
|
|
|
o = o << 8 | (0xff & bytes[offset + 2]);
|
|
|
|
o = o << 8 | (0xff & bytes[offset + 1]);
|
2013-07-31 20:14:11 +02:00
|
|
|
o = o << 8 | (0xff & bytes[offset]);
|
2013-04-18 23:35:02 +02:00
|
|
|
return o;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static void putLongToBytes(byte[] bytes, int offset, long l){
|
|
|
|
bytes[offset] = (byte) (l & 0xff);
|
|
|
|
l >>= 8;
|
|
|
|
bytes[offset + 1] = (byte) (l & 0xff);
|
|
|
|
l >>= 8;
|
|
|
|
bytes[offset + 2] = (byte) (l & 0xff);
|
|
|
|
l >>= 8;
|
|
|
|
bytes[offset + 3] = (byte) (l & 0xff);
|
|
|
|
l >>= 8;
|
|
|
|
bytes[offset + 4] = (byte) (l & 0xff);
|
|
|
|
l >>= 8;
|
|
|
|
bytes[offset + 5] = (byte) (l & 0xff);
|
|
|
|
l >>= 8;
|
|
|
|
bytes[offset + 6] = (byte) (l & 0xff);
|
|
|
|
l >>= 8;
|
|
|
|
bytes[offset + 7] = (byte) (l & 0xff);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static int parseIntFromBytes(byte[] bytes, int offset) {
|
|
|
|
int o = (0xff & bytes[offset + 3]) << 24;
|
|
|
|
o |= (0xff & bytes[offset + 2]) << 16;
|
|
|
|
o |= (0xff & bytes[offset + 1]) << 8;
|
2013-07-31 20:14:11 +02:00
|
|
|
o |= (0xff & bytes[offset]);
|
2013-04-18 23:35:02 +02:00
|
|
|
return o;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void putIntToBytes(byte[] bytes, int offset, int l){
|
|
|
|
bytes[offset] = (byte) (l & 0xff);
|
|
|
|
l >>= 8;
|
|
|
|
bytes[offset + 1] = (byte) (l & 0xff);
|
|
|
|
l >>= 8;
|
|
|
|
bytes[offset + 2] = (byte) (l & 0xff);
|
|
|
|
l >>= 8;
|
|
|
|
bytes[offset + 3] = (byte) (l & 0xff);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static void writeLongInt(OutputStream stream, long l) throws IOException {
|
|
|
|
stream.write((int) (l & 0xff));
|
|
|
|
l >>= 8;
|
|
|
|
stream.write((int) (l & 0xff));
|
|
|
|
l >>= 8;
|
|
|
|
stream.write((int) (l & 0xff));
|
|
|
|
l >>= 8;
|
|
|
|
stream.write((int) (l & 0xff));
|
|
|
|
l >>= 8;
|
|
|
|
stream.write((int) (l & 0xff));
|
|
|
|
l >>= 8;
|
|
|
|
stream.write((int) (l & 0xff));
|
|
|
|
l >>= 8;
|
|
|
|
stream.write((int) (l & 0xff));
|
|
|
|
l >>= 8;
|
|
|
|
stream.write((int) (l & 0xff));
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void writeInt(OutputStream stream, int l) throws IOException {
|
|
|
|
stream.write(l & 0xff);
|
|
|
|
l >>= 8;
|
|
|
|
stream.write(l & 0xff);
|
|
|
|
l >>= 8;
|
|
|
|
stream.write(l & 0xff);
|
|
|
|
l >>= 8;
|
|
|
|
stream.write(l & 0xff);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static void writeSmallInt(OutputStream stream, int l) throws IOException {
|
|
|
|
stream.write(l & 0xff);
|
|
|
|
l >>= 8;
|
|
|
|
stream.write(l & 0xff);
|
|
|
|
l >>= 8;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static int parseSmallIntFromBytes(byte[] bytes, int offset) {
|
|
|
|
int s = (0xff & bytes[offset + 1]) << 8;
|
2013-07-31 20:14:11 +02:00
|
|
|
s |= (0xff & bytes[offset]);
|
2013-04-18 23:35:02 +02:00
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void putSmallIntBytes(byte[] bytes, int offset, int s){
|
|
|
|
bytes[offset] = (byte) (s & 0xff);
|
|
|
|
s >>= 8;
|
|
|
|
bytes[offset + 1] = (byte) (s & 0xff);
|
|
|
|
s >>= 8;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static boolean containsDigit(String name) {
|
|
|
|
for (int i = 0; i < name.length(); i++) {
|
|
|
|
if (Character.isDigit(name.charAt(i))) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public static String formatDuration(int seconds) {
|
|
|
|
String sec;
|
|
|
|
if (seconds % 60 < 10) {
|
|
|
|
sec = "0" + (seconds % 60);
|
|
|
|
} else {
|
|
|
|
sec = (seconds % 60) + "";
|
|
|
|
}
|
|
|
|
int minutes = seconds / 60;
|
|
|
|
if (minutes < 60) {
|
|
|
|
return minutes + ":" + sec;
|
|
|
|
} else {
|
|
|
|
String min;
|
|
|
|
if (minutes % 60 < 10) {
|
|
|
|
min = "0" + (minutes % 60);
|
|
|
|
} else {
|
|
|
|
min = (minutes % 60) + "";
|
|
|
|
}
|
|
|
|
int hours = minutes / 60;
|
|
|
|
return hours + ":" + min + ":" + sec;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public static <T extends Enum<T> > T parseEnumValue(T[] cl, String val, T defaultValue){
|
|
|
|
for(int i = 0; i< cl.length; i++) {
|
|
|
|
if(cl[i].name().equalsIgnoreCase(val)) {
|
|
|
|
return cl[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return defaultValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
private static java.text.DateFormat dateFormat;
|
|
|
|
private static java.text.DateFormat dateTimeFormat;
|
|
|
|
public static String formatDate(long t) {
|
|
|
|
return getDateFormat().format(new Date(t));
|
|
|
|
}
|
|
|
|
|
|
|
|
public static DateFormat getDateFormat() {
|
|
|
|
if(dateFormat == null) {
|
|
|
|
dateFormat = DateFormat.getDateInstance(DateFormat.SHORT, Locale.getDefault());
|
|
|
|
}
|
|
|
|
return dateFormat;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static DateFormat getDateTimeFormat() {
|
|
|
|
if (dateTimeFormat == null) {
|
|
|
|
dateTimeFormat = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, Locale.getDefault());
|
|
|
|
}
|
|
|
|
return dateTimeFormat;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static String formatDateTime(long t) {
|
|
|
|
return getDateTimeFormat().format(new Date(t));
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|