From c838db467ffb910f29827beadefdc3271a3223f5 Mon Sep 17 00:00:00 2001 From: Valentyn Kolesnikov Date: Wed, 11 Dec 2024 08:13:06 +0200 Subject: [PATCH] Sync with underscore-java --- src/main/java/com/github/underscore/Xml.java | 36 +++++----- .../com/github/underscore/FunctionsTest.java | 2 +- .../com/github/underscore/LodashTest.java | 13 ++++ .../com/github/underscore/StringTest.java | 66 ++++++++++++++++++- 4 files changed, 94 insertions(+), 23 deletions(-) diff --git a/src/main/java/com/github/underscore/Xml.java b/src/main/java/com/github/underscore/Xml.java index 122f5d4..3ed2173 100644 --- a/src/main/java/com/github/underscore/Xml.java +++ b/src/main/java/com/github/underscore/Xml.java @@ -1521,30 +1521,26 @@ private static Object addElement( } static Map parseAttributes(final String source) { - final Map result = new LinkedHashMap<>(); - final StringBuilder key = new StringBuilder(); - final StringBuilder value = new StringBuilder(); - boolean quoteFound = false; - boolean equalFound = false; - for (int index = 0; index < source.length(); index += 1) { - if (source.charAt(index) == '=') { - equalFound = !equalFound; - continue; - } - if (source.charAt(index) == '"') { - if (quoteFound && equalFound) { + Map result = new LinkedHashMap<>(); + StringBuilder key = new StringBuilder(); + StringBuilder value = new StringBuilder(); + boolean inQuotes = false; + boolean expectingValue = false; + for (char c : source.toCharArray()) { + if (c == '"') { + inQuotes = !inQuotes; + if (!inQuotes && expectingValue) { result.put(key.toString(), value.toString()); key.setLength(0); value.setLength(0); - equalFound = false; - } - quoteFound = !quoteFound; - } else if (quoteFound || SKIPPED_CHARS.contains(source.charAt(index))) { - if (quoteFound) { - value.append(source.charAt(index)); + expectingValue = false; } - } else { - key.append(source.charAt(index)); + } else if (c == '=' && !inQuotes) { + expectingValue = true; + } else if (inQuotes) { + value.append(c); + } else if (!SKIPPED_CHARS.contains(c)) { + key.append(c); } } return result; diff --git a/src/test/java/com/github/underscore/FunctionsTest.java b/src/test/java/com/github/underscore/FunctionsTest.java index 60206d5..4eb7b64 100644 --- a/src/test/java/com/github/underscore/FunctionsTest.java +++ b/src/test/java/com/github/underscore/FunctionsTest.java @@ -199,7 +199,7 @@ void defer() { return null; }); assertEquals(0, counter[0].intValue(), "incr was debounced"); - await().atMost(120, TimeUnit.MILLISECONDS) + await().atLeast(90, TimeUnit.MILLISECONDS) .until( () -> { assertEquals(1, counter[0].intValue(), "incr was debounced"); diff --git a/src/test/java/com/github/underscore/LodashTest.java b/src/test/java/com/github/underscore/LodashTest.java index 21085f4..837f037 100644 --- a/src/test/java/com/github/underscore/LodashTest.java +++ b/src/test/java/com/github/underscore/LodashTest.java @@ -1028,6 +1028,19 @@ void xmpToJson4() { + "")); } + @Test + void xmpToJson5() { + assertEquals("{\n" + + " \"Comment\": {\n" + + " \"-stringValue\": \"============================\",\n" + + " \"-self-closing\": \"true\"\n" + + " },\n" + + " \"#omit-xml-declaration\": \"yes\"\n" + + "}", + U.xmlToJson( + "")); + } + @Test void xmlToJsonMinimum() { assertEquals( diff --git a/src/test/java/com/github/underscore/StringTest.java b/src/test/java/com/github/underscore/StringTest.java index 8b083b7..692f389 100644 --- a/src/test/java/com/github/underscore/StringTest.java +++ b/src/test/java/com/github/underscore/StringTest.java @@ -2358,9 +2358,71 @@ void parseAttributes() { "{version=1.0}", Xml.parseAttributes(" version = \"1.0\" encoding= \"UTF-8 ").toString()); assertEquals( - "{}", Xml.parseAttributes(" version = \"1.0 encoding= \"UTF-8\" ").toString()); + "{version=1.0 encoding= }", + Xml.parseAttributes(" version = \"1.0 encoding= \"UTF-8\" ").toString()); assertEquals( - "{}", Xml.parseAttributes(" version = 1.0\" encoding= \"UTF-8\" ").toString()); + "{version1.0= encoding= }", + Xml.parseAttributes(" version = 1.0\" encoding= \"UTF-8\" ").toString()); + } + + @Test + void testSingleAttribute() { + Map result = Xml.parseAttributes("key1=\"value1\""); + assertEquals(Map.of("key1", "value1"), result); + } + + @Test + void testMultipleAttributes() { + Map result = Xml.parseAttributes("key1=\"value1\" key2=\"value2\""); + assertEquals(Map.of("key1", "value1", "key2", "value2"), result); + } + + @Test + void testAttributeWithSpaces() { + Map result = Xml.parseAttributes("key1=\"value with spaces\" key2=\"another value\""); + assertEquals(Map.of("key1", "value with spaces", "key2", "another value"), result); + } + + @Test + void testEmptyValue() { + Map result = Xml.parseAttributes("key1=\"value1\" key2=\"\""); + assertEquals(Map.of("key1", "value1", "key2", ""), result); + } + + @Test + void testAttributesWithoutSpaceSeparation() { + Map result = Xml.parseAttributes("key1=\"value1\"key2=\"value2\""); + assertEquals(Map.of("key1", "value1", "key2", "value2"), result); + } + + @Test + void testUnclosedQuotes() { + Map result = Xml.parseAttributes("key1=\"value1 key2=\"value2\""); + assertEquals(Map.of("key1", "value1 key2="), result); + } + + @Test + void testEqualsSignInValue() { + Map result = Xml.parseAttributes("key1=\"value=1\" key2=\"value=2\""); + assertEquals(Map.of("key1", "value=1", "key2", "value=2"), result); + } + + @Test + void testTrailingWhitespace() { + Map result = Xml.parseAttributes("key1=\"value1\" key2=\"value2\" "); + assertEquals(Map.of("key1", "value1", "key2", "value2"), result); + } + + @Test + void testLeadingWhitespace() { + Map result = Xml.parseAttributes(" key1=\"value1\" key2=\"value2\""); + assertEquals(Map.of("key1", "value1", "key2", "value2"), result); + } + + @Test + void testNoEqualsSign() { + Map result = Xml.parseAttributes("key1\"value1\" key2=\"value2\""); + assertEquals(Map.of("key1key2", "value1value2"), result); } @SuppressWarnings("unchecked")