Mariusz Sieroń 6 лет назад
Родитель
Сommit
33b5d599d4

+ 1 - 1
assira/src/main/java/net/ranides/assira/collection/Grid.java

@@ -67,7 +67,7 @@ public class Grid<T> {
         return new Grid<>(head, data);
     }
 
-    public static Grid<Object> fromObjects(List<Object> rows) {
+    public static Grid<Object> fromObjects(List<? extends Object> rows) {
         return fromMap(rows.stream().map(v -> BeanModel.typefor(v).values(v)).collect(toList()));
     }
 

+ 17 - 0
assira/src/main/java/net/ranides/assira/collection/lists/FlatList.java

@@ -8,6 +8,7 @@ package net.ranides.assira.collection.lists;
 
 import java.io.Serializable;
 import java.util.*;
+import java.util.stream.Stream;
 
 /**
  * Klasa reprezentująca złączenie wielu list jako jedną kolekcję.
@@ -29,6 +30,11 @@ public class FlatList<T> extends AbstractSequentialList<T> implements Serializab
         this();
         joinAll(Arrays.asList(values));
     }
+
+    public FlatList(Stream<List<T>> values) {
+        this();
+        joinAll(values);
+    }
     
     public FlatList(List<List<T>> values) {
         this();
@@ -67,6 +73,17 @@ public class FlatList<T> extends AbstractSequentialList<T> implements Serializab
         content.addAll(list);
         return this;
     }
+
+    /***
+     * Inserts specified lists into view.
+     * Note: It stores containers, not actual elements from them.
+     * @param stream
+     * @return
+     */
+    public final FlatList<T> joinAll(Stream<List<T>> stream) {
+        stream.forEachOrdered(content::add);
+        return this;
+    }
     
     /**
      * Dodaje do kolekcji kolejne listy. Uwaga: dodawane są <b>listy</b>, a nie

+ 32 - 6
assira/src/main/java/net/ranides/assira/text/FormatHex.java

@@ -57,11 +57,11 @@ public final class FormatHex {
         try {
             int n= raw.length;
             if(n > 0) {
-                append(target, raw[0]);
+                appendByte(target, raw[0]);
             }
             for(int i=1; i<n; i++) {
                 target.append(' ');
-                append(target, raw[i]);
+                appendByte(target, raw[i]);
             }
             return target;
         } catch (IOException cause) {
@@ -69,10 +69,36 @@ public final class FormatHex {
         }
     }
 
-    private static void append(Appendable target, byte value) throws IOException {
-        int ivalue = value & 0xFF;
-        target.append(HC_TABLE[ivalue >>> 4]);
-        target.append(HC_TABLE[ivalue & 0xF]);
+    public static void appendByte(Appendable target, byte value) {
+        try {
+            int ivalue = value & 0xFF;
+            target.append(HC_TABLE[ivalue >>> 4]);
+            target.append(HC_TABLE[ivalue & 0xF]);
+        } catch (IOException cause) {
+            throw new UncheckedIOException(cause);
+        }
+    }
+
+    public static void appendChar(Appendable target, char value) {
+        try {
+            System.out.println(">>>>> " + (int)value);
+            int ivalue = value & 0xFFFF;
+            target.append(HC_TABLE[(ivalue >>> 12) & 0xF]);
+            target.append(HC_TABLE[(ivalue >>> 8) & 0xF]);
+            target.append(HC_TABLE[(ivalue >>> 4) & 0xF]);
+            target.append(HC_TABLE[(ivalue & 0xF)]);
+        } catch (IOException cause) {
+            throw new UncheckedIOException(cause);
+        }
+    }
+
+    public static char parseChar(CharSequence text, int index) {
+        byte a = CH_TABLE[text.charAt(index++)];
+        byte b = CH_TABLE[text.charAt(index++)];
+        byte c = CH_TABLE[text.charAt(index++)];
+        byte d = CH_TABLE[text.charAt(index++)];
+
+        return (char) ((a << 12) | (b << 8) | (c << 4) | (d));
     }
 
     public static byte[] parse(CharSequence text) {

+ 36 - 0
assira/src/main/java/net/ranides/assira/text/StringUtils.java

@@ -53,6 +53,42 @@ public final class StringUtils {
 	private StringUtils() {
 		/* utility class */
 	}
+
+    public static String escape(String value, char quote, String chars) {
+	    return escape(value, quote, CharPredicate.of(chars));
+    }
+
+    public static String escape(String value, char quote, Pattern chars) {
+        return escape(value, quote, CharPredicate.of(chars));
+    }
+
+    public static String escape(String value, char quote, CharPredicate chars) {
+        StrBuilder sb = new StrBuilder(value.length());
+        for(int i=0, n=value.length(); i<n; i++) {
+            char c = value.charAt(i);
+            if(chars.test(c) || c==quote) {
+                sb.append(quote);
+                FormatHex.appendChar(sb, c);
+            } else {
+                sb.append(c);
+            }
+        }
+        return sb.toString();
+    }
+
+    public static String unescape(String value, char quote) {
+        StrBuilder sb = new StrBuilder(value.length());
+        for(int i=0, n=value.length(); i<n; i++) {
+            char c = value.charAt(i);
+            if(c==quote) {
+                sb.append( FormatHex.parseChar(value, i+1) );
+                i+=4;
+            } else {
+                sb.append(c);
+            }
+        }
+        return sb.toString();
+    }
 	
 	public static String quote(String value) {
         if (null == value || value.isEmpty()) {

+ 26 - 0
assira/src/test/java/net/ranides/assira/text/FormatHexTest.java

@@ -18,6 +18,32 @@ import static org.junit.Assert.*;
  */
 public class FormatHexTest {
 
+    @Test
+    public void appendChar() {
+        StringBuilder target = new StringBuilder();
+
+        target.append("x");
+        FormatHex.appendChar(target, (char)0x32A7);
+        target.append(" x");
+        FormatHex.appendChar(target, (char)0x93ce);
+        target.append(" x");
+        FormatHex.appendChar(target, (char)0xaaa);
+        target.append(" x");
+        FormatHex.appendChar(target, (char)0x7e);
+
+        assertEquals("x32A7 x93CE x0AAA x007E", target.toString());
+    }
+
+    @Test
+    public void parseChar() {
+        String input = "x32A7 x93CE x0AAA x007E";
+
+        assertEquals((char)0x32A7, FormatHex.parseChar(input, 1) );
+        assertEquals((char)0x93CE, FormatHex.parseChar(input, 7) );
+        assertEquals((char)0x0AAA, FormatHex.parseChar(input, 13) );
+        assertEquals((char)0x007E, FormatHex.parseChar(input, 19) );
+    }
+
     @Test
     public void testFormatBuilder() {
         assertEquals("H:34 97 32 71", FormatHex.format(new StringBuilder("H:"), new byte[]{(byte)0x34, (byte)0x97, (byte)0x32, (byte)0x71}).toString());

+ 23 - 1
assira/src/test/java/net/ranides/assira/text/StringUtilsTest.java

@@ -9,6 +9,8 @@ package net.ranides.assira.text;
 import java.util.Arrays;
 import java.util.regex.Pattern;
 import static net.ranides.assira.junit.NewAssert.*;
+
+import net.ranides.assira.functional.CharPredicate;
 import org.junit.Test;
 
 /**
@@ -25,7 +27,27 @@ public class StringUtilsTest {
 	public StringUtilsTest() {
 	}
 
-	@Test
+    @Test
+    public void testEscape() {
+        String input = "Hello-%world! Here is some value. ↔ Źrebię na łące patrzy na słońce.";
+        String expect = "Hello%002D%0025world%0021 Here is some value. %2194 Źrebię na łące patrzy na sło%0144ce.";
+        String output = StringUtils.escape(input, '%', "!-?ń↔");
+        assertEquals(expect, output);
+        assertEquals(input, StringUtils.unescape(output, '%'));
+    }
+
+    @Test
+    public void testEscapeRe() {
+        String input = "Hello-%world! Here is some value. ↔ Źrebię na łące patrzy na słońce.";
+        String expect = "Hello%002D%0025world%0021 Here is some value. %2194 %0179rebi%0119 na %0142%0105ce patrzy na s%0142o%0144ce.";
+
+        String output = StringUtils.escape(input, '%', Pattern.compile("[^a-zA-Z .]"));
+        assertEquals(expect, output);
+        assertEquals(input, StringUtils.unescape(output, '%'));
+    }
+
+
+    @Test
 	public void testQuote() {
 		assertEquals("\"\"", StringUtils.quote(""));
 		assertEquals("\"abc\"", StringUtils.quote("abc"));