提交 e7e6a8a9 authored 作者: Evgenij Ryazanov's avatar Evgenij Ryazanov

Add DataUtils.getMapName() as faster alternative to parseMap().get("name")

上级 969f44a9
...@@ -613,6 +613,40 @@ public final class DataUtils { ...@@ -613,6 +613,40 @@ public final class DataUtils {
} }
} }
/**
* @param buff output buffer, should be empty
* @param s parsed string
* @param i offset to parse from
* @param size stop offset (exclusive)
* @return new offset
*/
private static int parseMapValue(StringBuilder buff, String s, int i, int size) {
while (i < size) {
char c = s.charAt(i++);
if (c == ',') {
break;
} else if (c == '\"') {
while (i < size) {
c = s.charAt(i++);
if (c == '\\') {
if (i == size) {
throw DataUtils.newIllegalStateException(
DataUtils.ERROR_FILE_CORRUPT,
"Not a map: {0}", s);
}
c = s.charAt(i++);
} else if (c == '\"') {
break;
}
buff.append(c);
}
} else {
buff.append(c);
}
}
return i;
}
/** /**
* Parse a key-value pair list. * Parse a key-value pair list.
* *
...@@ -622,6 +656,7 @@ public final class DataUtils { ...@@ -622,6 +656,7 @@ public final class DataUtils {
*/ */
public static HashMap<String, String> parseMap(String s) { public static HashMap<String, String> parseMap(String s) {
HashMap<String, String> map = New.hashMap(); HashMap<String, String> map = New.hashMap();
StringBuilder buff = new StringBuilder();
for (int i = 0, size = s.length(); i < size;) { for (int i = 0, size = s.length(); i < size;) {
int startKey = i; int startKey = i;
i = s.indexOf(':', i); i = s.indexOf(':', i);
...@@ -630,33 +665,56 @@ public final class DataUtils { ...@@ -630,33 +665,56 @@ public final class DataUtils {
DataUtils.ERROR_FILE_CORRUPT, "Not a map: {0}", s); DataUtils.ERROR_FILE_CORRUPT, "Not a map: {0}", s);
} }
String key = s.substring(startKey, i++); String key = s.substring(startKey, i++);
StringBuilder buff = new StringBuilder(); i = parseMapValue(buff, s, i, size);
while (i < size) { map.put(key, buff.toString());
char c = s.charAt(i++); buff.setLength(0);
if (c == ',') { }
break; return map;
} else if (c == '\"') { }
while (i < size) {
c = s.charAt(i++); /**
if (c == '\\') { * Parse a name from key-value pair list.
if (i == size) { *
throw DataUtils.newIllegalStateException( * @param s the list
DataUtils.ERROR_FILE_CORRUPT, * @return value of name item, or {@code null}
"Not a map: {0}", s); * @throws IllegalStateException if parsing failed
} */
public static String getMapName(String s) {
for (int i = 0, size = s.length(); i < size;) {
int startKey = i;
i = s.indexOf(':', i);
if (i < 0) {
throw DataUtils.newIllegalStateException(
DataUtils.ERROR_FILE_CORRUPT, "Not a map: {0}", s);
}
if (i++ - startKey == 4 && s.regionMatches(startKey, "name", 0, 4)) {
StringBuilder buff = new StringBuilder();
i = parseMapValue(buff, s, i, size);
return buff.toString();
} else {
while (i < size) {
char c = s.charAt(i++);
if (c == ',') {
break;
} else if (c == '\"') {
while (i < size) {
c = s.charAt(i++); c = s.charAt(i++);
} else if (c == '\"') { if (c == '\\') {
break; if (i == size) {
throw DataUtils.newIllegalStateException(
DataUtils.ERROR_FILE_CORRUPT,
"Not a map: {0}", s);
}
c = s.charAt(i++);
} else if (c == '\"') {
break;
}
} }
buff.append(c);
} }
} else {
buff.append(c);
} }
} }
map.put(key, buff.toString());
} }
return map; return null;
} }
/** /**
......
...@@ -2462,7 +2462,7 @@ public final class MVStore { ...@@ -2462,7 +2462,7 @@ public final class MVStore {
public synchronized String getMapName(int id) { public synchronized String getMapName(int id) {
checkOpen(); checkOpen();
String m = meta.get(MVMap.getMapKey(id)); String m = meta.get(MVMap.getMapKey(id));
return m == null ? null : DataUtils.parseMap(m).get("name"); return m == null ? null : DataUtils.getMapName(m);
} }
/** /**
......
...@@ -99,16 +99,34 @@ public class TestDataUtils extends TestBase { ...@@ -99,16 +99,34 @@ public class TestDataUtils extends TestBase {
DataUtils.appendMap(buff, "c", "1,2"); DataUtils.appendMap(buff, "c", "1,2");
DataUtils.appendMap(buff, "d", "\"test\""); DataUtils.appendMap(buff, "d", "\"test\"");
DataUtils.appendMap(buff, "e", "}"); DataUtils.appendMap(buff, "e", "}");
assertEquals(":,a:1,b:\",\",c:\"1,2\",d:\"\\\"test\\\"\",e:}", buff.toString()); DataUtils.appendMap(buff, "name", "1:1\",");
String encoded = buff.toString();
assertEquals(":,a:1,b:\",\",c:\"1,2\",d:\"\\\"test\\\"\",e:},name:\"1:1\\\",\"", encoded);
HashMap<String, String> m = DataUtils.parseMap(buff.toString()); HashMap<String, String> m = DataUtils.parseMap(encoded);
assertEquals(6, m.size()); assertEquals(7, m.size());
assertEquals("", m.get("")); assertEquals("", m.get(""));
assertEquals("1", m.get("a")); assertEquals("1", m.get("a"));
assertEquals(",", m.get("b")); assertEquals(",", m.get("b"));
assertEquals("1,2", m.get("c")); assertEquals("1,2", m.get("c"));
assertEquals("\"test\"", m.get("d")); assertEquals("\"test\"", m.get("d"));
assertEquals("}", m.get("e")); assertEquals("}", m.get("e"));
assertEquals("1:1\",", m.get("name"));
assertEquals("1:1\",", DataUtils.getMapName(encoded));
buff.setLength(0);
DataUtils.appendMap(buff, "1", "1");
DataUtils.appendMap(buff, "name", "2");
DataUtils.appendMap(buff, "3", "3");
encoded = buff.toString();
assertEquals("2", DataUtils.parseMap(encoded).get("name"));
assertEquals("2", DataUtils.getMapName(encoded));
buff.setLength(0);
DataUtils.appendMap(buff, "name", "xx");
encoded = buff.toString();
assertEquals("xx", DataUtils.parseMap(encoded).get("name"));
assertEquals("xx", DataUtils.getMapName(encoded));
} }
private void testMapRandomized() { private void testMapRandomized() {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论