Skip to content

Commit 8b4a11c

Browse files
committed
Add support for escape sequences in marker paths.
1 parent 2601fe9 commit 8b4a11c

File tree

4 files changed

+109
-27
lines changed

4 files changed

+109
-27
lines changed

httprpc-client/src/main/java/org/httprpc/io/JSONDecoder.java

Lines changed: 52 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -184,34 +184,65 @@ private String readString(Reader reader) throws IOException {
184184
if (c == '\\') {
185185
c = reader.read();
186186

187-
if (c == 'b') {
188-
c = '\b';
189-
} else if (c == 'f') {
190-
c = '\f';
191-
} else if (c == 'r') {
192-
c = '\r';
193-
} else if (c == 'n') {
194-
c = '\n';
195-
} else if (c == 't') {
196-
c = '\t';
197-
} else if (c == 'u') {
198-
StringBuilder characterBuilder = new StringBuilder();
187+
switch (c) {
188+
case 'b': {
189+
c = '\b';
190+
break;
191+
}
192+
193+
case 'f': {
194+
c = '\f';
195+
break;
196+
}
199197

200-
while (c != EOF && characterBuilder.length() < 4) {
201-
c = reader.read();
198+
case 'r': {
199+
c = '\r';
200+
break;
201+
}
202202

203-
characterBuilder.append((char)c);
203+
case 'n': {
204+
c = '\n';
205+
break;
204206
}
205207

206-
if (c == EOF) {
207-
throw new IOException("Invalid Unicode escape sequence.");
208+
case 't': {
209+
c = '\t';
210+
break;
208211
}
209212

210-
String unicodeValue = characterBuilder.toString();
213+
case 'u': {
214+
StringBuilder characterBuilder = new StringBuilder();
215+
216+
while (c != EOF && characterBuilder.length() < 4) {
217+
c = reader.read();
218+
219+
characterBuilder.append((char)c);
220+
}
221+
222+
if (c == EOF) {
223+
throw new IOException("Incomplete Unicode escape sequence.");
224+
}
211225

212-
c = (char)Integer.parseInt(unicodeValue, 16);
213-
} else if (c != '"' && c != '\\' && c != '/') {
214-
throw new IOException("Unsupported escape sequence.");
226+
String unicodeValue = characterBuilder.toString();
227+
228+
c = (char)Integer.parseInt(unicodeValue, 16);
229+
230+
break;
231+
}
232+
233+
case '"':
234+
case '\\':
235+
case '/': {
236+
break;
237+
}
238+
239+
case EOF: {
240+
throw new IOException("Unterminated escape sequence.");
241+
}
242+
243+
default: {
244+
throw new IOException("Invalid escape sequence.");
245+
}
215246
}
216247
}
217248

httprpc-client/src/main/java/org/httprpc/io/TemplateEncoder.java

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -815,14 +815,45 @@ private static Object getMarkerValue(Map<String, ?> dictionary, String name) {
815815
} else {
816816
Object value = dictionary;
817817

818-
String[] components = name.split("/");
818+
StringBuilder keyBuilder = new StringBuilder();
819819

820-
for (int i = 0; i < components.length; i++) {
821-
if (!(value instanceof Map<?, ?>)) {
822-
return null;
820+
int i = 0;
821+
int n = name.length();
822+
823+
while (i <= n) {
824+
char c = (i < n) ? name.charAt(i) : 0;
825+
826+
if (c == 0 || c == '/') {
827+
if (!(value instanceof Map<?, ?>)) {
828+
return null;
829+
}
830+
831+
String key = keyBuilder.toString();
832+
833+
if (key.length() > 0) {
834+
value = ((Map<?, ?>)value).get(key);
835+
}
836+
837+
keyBuilder.setLength(0);
838+
} else {
839+
if (c == '\\') {
840+
i++;
841+
842+
if (i == n) {
843+
throw new IllegalArgumentException("Unterminated escape sequence.");
844+
}
845+
846+
c = name.charAt(i);
847+
848+
if (c != '/') {
849+
throw new IllegalArgumentException("Invalid escape sequence.");
850+
}
851+
}
852+
853+
keyBuilder.append(c);
823854
}
824855

825-
value = ((Map<?, ?>)value).get(components[i]);
856+
i++;
826857
}
827858

828859
return value;

httprpc-client/src/test/java/org/httprpc/io/TemplateEncoderTest.java

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ public void testMap() throws IOException {
7575
}
7676

7777
@Test
78-
public void testConditionalSection() throws IOException {
78+
public void testConditionalSection1() throws IOException {
7979
TemplateEncoder encoder = new TemplateEncoder(getClass().getResource("conditional.txt"));
8080

8181
Map<String, ?> value = mapOf(
@@ -553,4 +553,23 @@ public void testUppercaseModifier() throws IOException {
553553

554554
assertEquals("ABCDEFG", result);
555555
}
556+
557+
@Test
558+
public void testEscape() throws IOException {
559+
TemplateEncoder encoder = new TemplateEncoder(getClass().getResource("escape.txt"));
560+
561+
Map<String, ?> value = mapOf(
562+
entry("a", mapOf(
563+
entry("b/c", "A")
564+
))
565+
);
566+
567+
String result;
568+
try (StringWriter writer = new StringWriter()) {
569+
encoder.write(value, writer);
570+
result = writer.toString();
571+
}
572+
573+
assertEquals("A", result);
574+
}
556575
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{{a/b\/c}}

0 commit comments

Comments
 (0)