001package squidpony; 002 003import squidpony.squidmath.*; 004 005import java.util.*; 006 007/** 008 * Ways to produce concrete implementations of StringConvert for various data structures. 009 * Keeping the StringConvert producers separate from the data structures allows us to convert 010 * JDK types as well as to keep the parts that need ObText, and thus RegExodus, separate from 011 * the more general-use data structures. 012 * Created by Tommy Ettinger on 3/9/2017. 013 */ 014@SuppressWarnings("unchecked") 015public class Converters { 016 017 public static void appendQuoted(StringBuilder sb, String text) 018 { 019 ObText.appendQuoted(sb, text); 020 } 021 022 public static ObText.ContentMatcher makeMatcher(CharSequence text) 023 { 024 return ObText.makeMatcherNoComments(text); 025 } 026 027 public static <K> StringConvert<OrderedSet<K>> convertOrderedSet(final StringConvert<K> convert) { 028 CharSequence[] types = StringConvert.asArray("OrderedSet", convert.name); 029 StringConvert found = StringConvert.lookup(types); 030 if (found != null) 031 return found; // in this case we've already created a StringConvert for this type combination 032 033 return new StringConvert<OrderedSet<K>>(types) { 034 @Override 035 public String stringify(OrderedSet<K> item) { 036 StringBuilder sb = new StringBuilder(100); 037 K k; 038 for (int i = 0; i < item.size(); ) { 039 k = item.getAt(i); 040 if (item == k) 041 return ""; 042 ObText.appendQuoted(sb, convert.stringify(k)); 043 if (++i < item.size()) 044 sb.append(' '); 045 } 046 return sb.toString(); 047 } 048 049 @Override 050 public OrderedSet<K> restore(String text) { 051 ObText.ContentMatcher m = makeMatcher(text); 052 OrderedSet<K> d; 053 if(convert.isArray) 054 d = new OrderedSet<>(CrossHash.generalHasher); 055 else 056 d = new OrderedSet<>(); 057 while (m.find()) { 058 if (m.hasMatch()) { 059 d.add(convert.restore(m.getMatch())); 060 } 061 } 062 return d; 063 } 064 }; 065 } 066 067 public static <K> StringConvert<OrderedSet<K>> convertOrderedSet(final CharSequence type) { 068 return convertOrderedSet((StringConvert<K>) StringConvert.get(type)); 069 } 070 071 public static <K> StringConvert<OrderedSet<K>> convertOrderedSet(final Class<K> type) { 072 return convertOrderedSet((StringConvert<K>) StringConvert.get(type.getSimpleName())); 073 } 074 public static <K> StringConvert<UnorderedSet<K>> convertUnorderedSet(final StringConvert<K> convert) { 075 CharSequence[] types = StringConvert.asArray("UnorderedSet", convert.name); 076 StringConvert found = StringConvert.lookup(types); 077 if (found != null) 078 return found; // in this case we've already created a StringConvert for this type combination 079 080 return new StringConvert<UnorderedSet<K>>(types) { 081 @Override 082 public String stringify(UnorderedSet<K> item) { 083 StringBuilder sb = new StringBuilder(100); 084 int i = 0; 085 for (K k : item) { 086 if (item == k) 087 return ""; 088 ObText.appendQuoted(sb, convert.stringify(k)); 089 if (++i < item.size()) 090 sb.append(' '); 091 } 092 return sb.toString(); 093 } 094 095 @Override 096 public UnorderedSet<K> restore(String text) { 097 ObText.ContentMatcher m = makeMatcher(text); 098 UnorderedSet<K> d; 099 if(convert.isArray) 100 d = new UnorderedSet<>(CrossHash.generalHasher); 101 else 102 d = new UnorderedSet<>(); 103 while (m.find()) { 104 if (m.hasMatch()) { 105 d.add(convert.restore(m.getMatch())); 106 } 107 } 108 return d; 109 } 110 }; 111 } 112 113 public static <K> StringConvert<UnorderedSet<K>> convertUnorderedSet(final CharSequence type) { 114 return convertUnorderedSet((StringConvert<K>) StringConvert.get(type)); 115 } 116 117 public static <K> StringConvert<UnorderedSet<K>> convertUnorderedSet(final Class<K> type) { 118 return convertUnorderedSet((StringConvert<K>) StringConvert.get(type.getSimpleName())); 119 } 120 121 public static <K, V> StringConvert<OrderedMap<K, V>> convertOrderedMap(final StringConvert<K> convertK, final StringConvert<V> convertV) { 122 CharSequence[] types = StringConvert.asArray("OrderedMap", convertK.name, convertV.name); 123 StringConvert found = StringConvert.lookup(types); 124 if (found != null) 125 return found; // in this case we've already created a StringConvert for this type combination 126 127 return new StringConvert<OrderedMap<K, V>>(types) { 128 @Override 129 public String stringify(OrderedMap<K, V> item) { 130 StringBuilder sb = new StringBuilder(100); 131 K k; 132 V v; 133 for (int i = 0; i < item.size(); ) { 134 k = item.keyAt(i); 135 if (k == item) 136 return ""; 137 appendQuoted(sb, convertK.stringify(k)); 138 sb.append(' '); 139 v = item.getAt(i); 140 if (v == item) 141 return ""; 142 appendQuoted(sb, convertV.stringify(v)); 143 if (++i < item.size()) 144 sb.append(' '); 145 } 146 return sb.toString(); 147 } 148 149 @Override 150 public OrderedMap<K, V> restore(String text) { 151 ObText.ContentMatcher m = makeMatcher(text); 152 OrderedMap<K, V> d; 153 if(convertK.isArray) 154 d = new OrderedMap<>(CrossHash.generalHasher); 155 else 156 d = new OrderedMap<>(); 157 String t; 158 while (m.find()) { 159 if (m.hasMatch()) { 160 t = m.getMatch(); 161 if (m.find() && m.hasMatch()) { 162 d.put(convertK.restore(t), convertV.restore(m.getMatch())); 163 } 164 } 165 } 166 return d; 167 } 168 }; 169 } 170 171 public static <K, V> StringConvert<OrderedMap<K, V>> convertOrderedMap(final CharSequence typeK, final CharSequence typeV) { 172 return convertOrderedMap((StringConvert<K>) StringConvert.get(typeK), (StringConvert<V>) StringConvert.get(typeV)); 173 } 174 175 public static <K, V> StringConvert<OrderedMap<K, V>> convertOrderedMap(final Class<K> typeK, final Class<V> typeV) { 176 return convertOrderedMap((StringConvert<K>) StringConvert.get(typeK.getSimpleName()), 177 (StringConvert<V>) StringConvert.get(typeV.getSimpleName())); 178 } 179 180 public static <K, V> StringConvert<UnorderedMap<K, V>> convertUnorderedMap(final StringConvert<K> convertK, final StringConvert<V> convertV) { 181 CharSequence[] types = StringConvert.asArray("UnorderedMap", convertK.name, convertV.name); 182 StringConvert found = StringConvert.lookup(types); 183 if (found != null) 184 return found; // in this case we've already created a StringConvert for this type combination 185 186 return new StringConvert<UnorderedMap<K, V>>(types) { 187 @Override 188 public String stringify(UnorderedMap<K, V> item) { 189 StringBuilder sb = new StringBuilder(100); 190 K k; 191 V v; 192 Iterator<Map.Entry<K, V>> it = item.entrySet().iterator(); 193 Map.Entry<K, V> ent; 194 while (it.hasNext()) 195 { 196 ent = it.next(); 197 k = ent.getKey(); 198 if (k == item) 199 return ""; 200 appendQuoted(sb, convertK.stringify(k)); 201 sb.append(' '); 202 v = ent.getValue(); 203 if (v == item) 204 return ""; 205 appendQuoted(sb, convertV.stringify(v)); 206 if (it.hasNext()) 207 sb.append(' '); 208 } 209 return sb.toString(); 210 } 211 212 @Override 213 public UnorderedMap<K, V> restore(String text) { 214 ObText.ContentMatcher m = makeMatcher(text); 215 UnorderedMap<K, V> d; 216 if(convertK.isArray) 217 d = new UnorderedMap<>(CrossHash.generalHasher); 218 else 219 d = new UnorderedMap<>(); 220 String t; 221 while (m.find()) { 222 if (m.hasMatch()) { 223 t = m.getMatch(); 224 if (m.find() && m.hasMatch()) { 225 d.put(convertK.restore(t), convertV.restore(m.getMatch())); 226 } 227 } 228 } 229 return d; 230 } 231 }; 232 } 233 234 public static <K, V> StringConvert<UnorderedMap<K, V>> convertUnorderedMap(final CharSequence typeK, final CharSequence typeV) { 235 return convertUnorderedMap((StringConvert<K>) StringConvert.get(typeK), (StringConvert<V>) StringConvert.get(typeV)); 236 } 237 238 public static <K, V> StringConvert<UnorderedMap<K, V>> convertUnorderedMap(final Class<K> typeK, final Class<V> typeV) { 239 return convertUnorderedMap((StringConvert<K>) StringConvert.get(typeK.getSimpleName()), 240 (StringConvert<V>) StringConvert.get(typeV.getSimpleName())); 241 } 242 243 public static <K> StringConvert<HashSet<K>> convertHashSet(final StringConvert<K> convert) { 244 CharSequence[] types = StringConvert.asArray("HashSet", convert.name); 245 StringConvert found = StringConvert.lookup(types); 246 if (found != null) 247 return found; // in this case we've already created a StringConvert for this type combination 248 249 return new StringConvert<HashSet<K>>(types) { 250 @Override 251 public String stringify(HashSet<K> item) { 252 StringBuilder sb = new StringBuilder(100); 253 Iterator<K> it = item.iterator(); 254 K k; 255 while (it.hasNext()){ 256 k = it.next(); 257 if (item == k) 258 return ""; 259 ObText.appendQuoted(sb, convert.stringify(k)); 260 if (it.hasNext()) 261 sb.append(' '); 262 } 263 return sb.toString(); 264 } 265 266 @Override 267 public HashSet<K> restore(String text) { 268 ObText.ContentMatcher m = makeMatcher(text); 269 HashSet<K> d = new HashSet<>(); 270 while (m.find()) { 271 if (m.hasMatch()) { 272 d.add(convert.restore(m.getMatch())); 273 } 274 } 275 return d; 276 } 277 }; 278 } 279 280 public static <K> StringConvert<HashSet<K>> convertHashSet(final CharSequence type) { 281 return convertHashSet((StringConvert<K>) StringConvert.get(type)); 282 } 283 284 public static <K> StringConvert<HashSet<K>> convertHashSet(final Class<K> type) { 285 return convertHashSet((StringConvert<K>) StringConvert.get(type.getSimpleName())); 286 } 287 288 public static <K, V> StringConvert<HashMap<K, V>> convertHashMap(final StringConvert<K> convertK, final StringConvert<V> convertV) { 289 CharSequence[] types = StringConvert.asArray("HashMap", convertK.name, convertV.name); 290 StringConvert found = StringConvert.lookup(types); 291 if (found != null) 292 return found; // in this case we've already created a StringConvert for this type combination 293 294 return new StringConvert<HashMap<K, V>>(types) { 295 @Override 296 public String stringify(HashMap<K, V> item) { 297 StringBuilder sb = new StringBuilder(100); 298 K k; 299 V v; 300 Iterator<K> kit = item.keySet().iterator(); 301 Iterator<V> vit = item.values().iterator(); 302 while (kit.hasNext()) { 303 k = kit.next(); 304 if (k == item) 305 return ""; 306 appendQuoted(sb, convertK.stringify(k)); 307 sb.append(' '); 308 v = vit.next(); 309 if (v == item) 310 return ""; 311 appendQuoted(sb, convertV.stringify(v)); 312 if (kit.hasNext()) 313 sb.append(' '); 314 } 315 return sb.toString(); 316 } 317 318 @Override 319 public HashMap<K, V> restore(String text) { 320 ObText.ContentMatcher m = makeMatcher(text); 321 HashMap<K, V> d = new HashMap<>(); 322 String t; 323 while (m.find()) { 324 if (m.hasMatch()) { 325 t = m.getMatch(); 326 if (m.find() && m.hasMatch()) { 327 d.put(convertK.restore(t), convertV.restore(m.getMatch())); 328 } 329 } 330 } 331 return d; 332 } 333 }; 334 } 335 336 public static <K, V> StringConvert<HashMap<K, V>> convertHashMap(final CharSequence typeK, final CharSequence typeV) { 337 return convertHashMap((StringConvert<K>) StringConvert.get(typeK), (StringConvert<V>) StringConvert.get(typeV)); 338 } 339 340 public static <K, V> StringConvert<HashMap<K, V>> convertHashMap(final Class<K> typeK, final Class<V> typeV) { 341 return convertHashMap((StringConvert<K>) StringConvert.get(typeK.getSimpleName()), 342 (StringConvert<V>) StringConvert.get(typeV.getSimpleName())); 343 } 344 345 public static <K> StringConvert<Arrangement<K>> convertArrangement(final StringConvert<K> convert) { 346 CharSequence[] types = StringConvert.asArray("Arrangement", convert.name); 347 StringConvert found = StringConvert.lookup(types); 348 if (found != null) 349 return found; // in this case we've already created a StringConvert for this type combination 350 351 return new StringConvert<Arrangement<K>>(types) { 352 @Override 353 public String stringify(Arrangement<K> item) { 354 StringBuilder sb = new StringBuilder(100); 355 K k; 356 for (int i = 0; i < item.size(); ) { 357 k = item.keyAt(i); 358 if (item == k) 359 return ""; 360 ObText.appendQuoted(sb, convert.stringify(k)); 361 if (++i < item.size()) 362 sb.append(' '); 363 } 364 return sb.toString(); 365 } 366 367 @Override 368 public Arrangement<K> restore(String text) { 369 ObText.ContentMatcher m = makeMatcher(text); 370 Arrangement<K> d; 371 if(convert.isArray) 372 d = new Arrangement<>(CrossHash.generalHasher); 373 else 374 d = new Arrangement<>(); 375 while (m.find()) { 376 if (m.hasMatch()) { 377 d.add(convert.restore(m.getMatch())); 378 } 379 } 380 return d; 381 } 382 }; 383 } 384 385 public static <K> StringConvert<Arrangement<K>> convertArrangement(final CharSequence type) { 386 return convertArrangement((StringConvert<K>) StringConvert.get(type)); 387 } 388 389 public static <K> StringConvert<Arrangement<K>> convertArrangement(final Class<K> type) { 390 return convertArrangement((StringConvert<K>) StringConvert.get(type.getSimpleName())); 391 } 392 393 394 public static <K> StringConvert<ArrayList<K>> convertArrayList(final StringConvert<K> convert) { 395 CharSequence[] types = StringConvert.asArray("ArrayList", convert.name); 396 StringConvert found = StringConvert.lookup(types); 397 if (found != null) 398 return found; // in this case we've already created a StringConvert for this type combination 399 return new StringConvert<ArrayList<K>>(types) { 400 @Override 401 public String stringify(ArrayList<K> item) { 402 StringBuilder sb = new StringBuilder(100); 403 K k; 404 for (int i = 0; i < item.size(); ) { 405 k = item.get(i); 406 if (item == k) 407 return ""; 408 appendQuoted(sb, convert.stringify(k)); 409 if (++i < item.size()) 410 sb.append(' '); 411 } 412 return sb.toString(); 413 } 414 415 @Override 416 public ArrayList<K> restore(String text) { 417 ObText.ContentMatcher m = makeMatcher(text); 418 ArrayList<K> d = new ArrayList<>(); 419 while (m.find()) { 420 if (m.hasMatch()) { 421 d.add(convert.restore(m.getMatch())); 422 } 423 } 424 return d; 425 } 426 }; 427 } 428 429 public static <K> StringConvert<ArrayList<K>> convertArrayList(final CharSequence type) { 430 return convertArrayList((StringConvert<K>) StringConvert.get(type)); 431 } 432 433 public static <K> StringConvert<ArrayList<K>> convertArrayList(final Class<K> type) { 434 return convertArrayList((StringConvert<K>) StringConvert.get(type.getSimpleName())); 435 } 436 public static <K> StringConvert<List<K>> convertList(final StringConvert<K> convert) { 437 CharSequence[] types = StringConvert.asArray("List", convert.name); 438 StringConvert found = StringConvert.lookup(types); 439 if (found != null) 440 return found; // in this case we've already created a StringConvert for this type combination 441 return new StringConvert<List<K>>(types) { 442 @Override 443 public String stringify(List<K> item) { 444 StringBuilder sb = new StringBuilder(100); 445 K k; 446 for (int i = 0; i < item.size(); ) { 447 k = item.get(i); 448 if (item == k) 449 return ""; 450 appendQuoted(sb, convert.stringify(k)); 451 if (++i < item.size()) 452 sb.append(' '); 453 } 454 return sb.toString(); 455 } 456 457 @Override 458 public ArrayList<K> restore(String text) { 459 ObText.ContentMatcher m = makeMatcher(text); 460 ArrayList<K> d = new ArrayList<>(); 461 while (m.find()) { 462 if (m.hasMatch()) { 463 d.add(convert.restore(m.getMatch())); 464 } 465 } 466 return d; 467 } 468 }; 469 } 470 471 public static <K> StringConvert<List<K>> convertList(final CharSequence type) { 472 return convertList((StringConvert<K>) StringConvert.get(type)); 473 } 474 475 public static <K> StringConvert<List<K>> convertList(final Class<K> type) { 476 return convertList((StringConvert<K>) StringConvert.get(type.getSimpleName())); 477 } 478 479 public static final StringConvert<Coord> convertCoord = new StringConvert<Coord>("Coord") { 480 @Override 481 public String stringify(Coord item) { 482 if(item == null) return "n"; 483 return item.x + "," + item.y; 484 } 485 486 @Override 487 public Coord restore(String text) { 488 if(text == null || text.equals("n")) return null; 489 return Coord.get(StringKit.intFromDec(text), StringKit.intFromDec(text, text.indexOf(',') + 1, text.length())); 490 } 491 }; 492 493 public static final StringConvert<Coord[]> convertArrayCoord = new StringConvert<Coord[]>(true,"Coord[]") { 494 @Override 495 public String stringify(Coord[] item) { 496 if(item == null) 497 return "N"; 498 int len = item.length; 499 StringBuilder sb = new StringBuilder(len * 5); 500 for (int i = 0; i < len; ) { 501 if(item[i] == null) 502 sb.append('n'); 503 else 504 sb.append(item[i].x).append(',').append(item[i].y); 505 if (++i < len) 506 sb.append(';'); 507 } 508 return sb.toString(); 509 } 510 511 @Override 512 public Coord[] restore(String text) { 513 if(text == null || text.equals("N")) 514 return null; 515 Coord[] coords = new Coord[StringKit.count(text, ';') + 1]; 516 int start = -1, end = text.indexOf(','); 517 for (int i = 0; i < coords.length; i++) { 518 if(text.charAt(start+1) == 'n') { 519 coords[i] = null; 520 start = text.indexOf(';', end + 1); 521 } 522 else 523 coords[i] = Coord.get(StringKit.intFromDec(text, start + 1, end), 524 StringKit.intFromDec(text, end + 1, (start = text.indexOf(';', end + 1)))); 525 end = text.indexOf(',', start + 1); 526 } 527 return coords; 528 } 529 }; 530 531 public static final StringConvert<GreasedRegion> convertGreasedRegion = new StringConvert<GreasedRegion>("GreasedRegion") { 532 @Override 533 public String stringify(GreasedRegion item) { 534 return item.serializeToString(); 535 } 536 537 @Override 538 public GreasedRegion restore(String text) { 539 return GreasedRegion.deserializeFromString(text); 540 } 541 }; 542 public static final StringConvert<IntVLA> convertIntVLA = new StringConvert<IntVLA>("IntVLA") { 543 @Override 544 public String stringify(IntVLA item) { 545 return item.toString(","); 546 } 547 548 @Override 549 public IntVLA restore(String text) { 550 return IntVLA.deserializeFromString(text); 551 } 552 }; 553 554 public static final StringConvert<FakeLanguageGen> convertFakeLanguageGen = new StringConvert<FakeLanguageGen>("FakeLanguageGen") 555 { 556 @Override 557 public String stringify(FakeLanguageGen item) { 558 return item.serializeToString(); 559 } 560 561 @Override 562 public FakeLanguageGen restore(String text) { 563 return FakeLanguageGen.deserializeFromString(text); 564 } 565 }; 566 567 public static final StringConvert<FakeLanguageGen.SentenceForm> convertSentenceForm = new StringConvert<FakeLanguageGen.SentenceForm>("FakeLanguageGen$SentenceForm") 568 { 569 @Override 570 public String stringify(FakeLanguageGen.SentenceForm item) { 571 return item.serializeToString(); 572 } 573 574 @Override 575 public FakeLanguageGen.SentenceForm restore(String text) { 576 return FakeLanguageGen.SentenceForm.deserializeFromString(text); 577 } 578 }; 579 580 public static final StringConvert<MarkovTextLimited> convertMarkovText = new StringConvert<MarkovTextLimited>("MarkovTextLimited") 581 { 582 @Override 583 public String stringify(MarkovTextLimited item) { 584 return item.serializeToString(); 585 } 586 587 @Override 588 public MarkovTextLimited restore(String text) { 589 return MarkovTextLimited.deserializeFromString(text); 590 } 591 }; 592 593 public static final StringConvert<ObText> convertObText = new StringConvert<ObText>("ObText") { 594 @Override 595 public String stringify(ObText item) { 596 return item.serializeToString(); 597 } 598 599 @Override 600 public ObText restore(String text) { 601 return ObText.deserializeFromString(text); 602 } 603 }; 604 605 public static final StringConvert<WeightedTable> convertWeightedTable = new StringConvert<WeightedTable>("WeightedTable") { 606 @Override 607 public String stringify(WeightedTable item) { 608 return item.serializeToString(); 609 } 610 611 @Override 612 public WeightedTable restore(String text) { 613 return WeightedTable.deserializeFromString(text); 614 } 615 }; 616 617 618 619 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 620 /////// CORE JDK TYPES, PRIMITIVES, AND PRIMITIVE ARRAYS ARE THE ONLY TYPES AFTER THIS POINT 621 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 622 623 624 /** 625 * Simple implementation to help when passing StringConverts around with data that is already a String. 626 */ 627 public static final StringConvert<String> convertString = new StringConvert<String>("String") { 628 @Override 629 public String stringify(String item) { 630 return item; 631 } 632 633 @Override 634 public String restore(String text) { 635 return text; 636 } 637 }; 638 639 public static final StringConvert<Boolean> convertBoolean = new StringConvert<Boolean>("Boolean") { 640 @Override 641 public String stringify(Boolean item) { 642 return item == null ? "n" : item ? "1" : "0"; 643 } 644 645 @Override 646 public Boolean restore(String text) { 647 char c; 648 return (text == null || text.isEmpty() || (c = text.charAt(0)) == 'n') ? null : c == '1'; 649 } 650 }; 651 652 public static final StringConvert<Byte> convertByte = new StringConvert<Byte>("Byte") { 653 @Override 654 public String stringify(Byte item) { 655 return item.toString(); 656 } 657 658 @Override 659 public Byte restore(String text) { 660 return Byte.decode(text); 661 } 662 }; 663 664 public static final StringConvert<Short> convertShort = new StringConvert<Short>("Short") { 665 @Override 666 public String stringify(Short item) { 667 return item.toString(); 668 } 669 670 @Override 671 public Short restore(String text) { 672 return Short.decode(text); 673 } 674 }; 675 676 public static final StringConvert<Integer> convertInt = new StringConvert<Integer>("Integer") { 677 @Override 678 public String stringify(Integer item) { 679 return item.toString(); 680 } 681 682 @Override 683 public Integer restore(String text) { 684 return Integer.decode(text); 685 } 686 }; 687 688 public static final StringConvert<Long> convertLong = new StringConvert<Long>("Long") { 689 @Override 690 public String stringify(Long item) { 691 return item.toString(); 692 } 693 694 @Override 695 public Long restore(String text) { 696 return Long.decode(text); 697 } 698 }; 699 700 public static final StringConvert<Float> convertFloat = new StringConvert<Float>("Float") { 701 @Override 702 public String stringify(Float item) { 703 return item.toString(); 704 } 705 706 @Override 707 public Float restore(String text) { 708 return Float.parseFloat(text); 709 } 710 }; 711 712 public static final StringConvert<Double> convertDouble = new StringConvert<Double>("Double") { 713 @Override 714 public String stringify(Double item) { 715 return item.toString(); 716 } 717 718 @Override 719 public Double restore(String text) { 720 return Double.parseDouble(text); 721 } 722 }; 723 724 public static final StringConvert<Character> convertChar = new StringConvert<Character>("Character") { 725 @Override 726 public String stringify(Character item) { 727 return item.toString(); 728 } 729 730 @Override 731 public Character restore(String text) { 732 return text.charAt(0); 733 } 734 }; 735 736 public static final StringConvert<boolean[]> convertArrayBoolean = new StringConvert<boolean[]>(true,"boolean[]") { 737 @Override 738 public String stringify(boolean[] item) { 739 return StringKit.joinAlt(item); 740 } 741 742 @Override 743 public boolean[] restore(String text) { 744 if(text == null || text.equals("N")) return null; 745 int amount = text.length(); 746 if (amount <= 0) return new boolean[0]; 747 boolean[] splat = new boolean[amount]; 748 for (int i = 0; i < amount; i++) { 749 splat[amount] = text.charAt(i) == '1'; 750 } 751 return splat; 752 } 753 }; 754 755 public static final StringConvert<byte[]> convertArrayByte = new StringConvert<byte[]>(true,"byte[]") { 756 @Override 757 public String stringify(byte[] item) { 758 if(item == null) return "N"; 759 return StringKit.join(",", item); 760 } 761 762 @Override 763 public byte[] restore(String text) { 764 if(text == null || text.equals("N")) return null; 765 int amount = StringKit.count(text, ","); 766 if (amount <= 0) return new byte[]{Byte.decode(text)}; 767 byte[] splat = new byte[amount + 1]; 768 int dl = 1, idx = -dl, idx2; 769 for (int i = 0; i < amount; i++) { 770 splat[i] = Byte.decode(StringKit.safeSubstring(text, idx + dl, idx = text.indexOf(',', idx + dl))); 771 } 772 if ((idx2 = text.indexOf(',', idx + dl)) < 0) { 773 splat[amount] = Byte.decode(StringKit.safeSubstring(text, idx + dl, text.length())); 774 } else { 775 splat[amount] = Byte.decode(StringKit.safeSubstring(text, idx + dl, idx2)); 776 } 777 return splat; 778 } 779 }; 780 781 782 public static final StringConvert<short[]> convertArrayShort = new StringConvert<short[]>(true,"short[]") { 783 @Override 784 public String stringify(short[] item) { 785 if(item == null) return "N"; 786 return StringKit.join(",", item); 787 } 788 789 @Override 790 public short[] restore(String text) { 791 if(text == null || text.equals("N")) return null; 792 int amount = StringKit.count(text, ","); 793 if (amount <= 0) return new short[]{Short.decode(text)}; 794 short[] splat = new short[amount + 1]; 795 int dl = 1, idx = -dl, idx2; 796 for (int i = 0; i < amount; i++) { 797 splat[i] = Short.decode(StringKit.safeSubstring(text, idx + dl, idx = text.indexOf(',', idx + dl))); 798 } 799 if ((idx2 = text.indexOf(',', idx + dl)) < 0) { 800 splat[amount] = Short.decode(StringKit.safeSubstring(text, idx + dl, text.length())); 801 } else { 802 splat[amount] = Short.decode(StringKit.safeSubstring(text, idx + dl, idx2)); 803 } 804 return splat; 805 } 806 }; 807 808 public static final StringConvert<int[]> convertArrayInt = new StringConvert<int[]>(true,"int[]") { 809 @Override 810 public String stringify(int[] item) { 811 if(item == null) return "N"; 812 return StringKit.join(",", item); 813 } 814 815 @Override 816 public int[] restore(String text) { 817 if(text == null || text.equals("N")) return null; 818 int amount = StringKit.count(text, ","); 819 if (amount <= 0) return new int[]{Integer.decode(text)}; 820 int[] splat = new int[amount + 1]; 821 int dl = 1, idx = -dl, idx2; 822 for (int i = 0; i < amount; i++) { 823 splat[i] = Integer.decode(StringKit.safeSubstring(text, idx + dl, idx = text.indexOf(',', idx + dl))); 824 } 825 if ((idx2 = text.indexOf(',', idx + dl)) < 0) { 826 splat[amount] = Integer.decode(StringKit.safeSubstring(text, idx + dl, text.length())); 827 } else { 828 splat[amount] = Integer.decode(StringKit.safeSubstring(text, idx + dl, idx2)); 829 } 830 return splat; 831 } 832 }; 833 834 835 public static final StringConvert<long[]> convertArrayLong = new StringConvert<long[]>(true,"long[]") { 836 @Override 837 public String stringify(long[] item) { 838 if(item == null) return "N"; 839 return StringKit.join(",", item); 840 } 841 842 @Override 843 public long[] restore(String text) { 844 if(text == null || text.equals("N")) return null; 845 int amount = StringKit.count(text, ","); 846 if (amount <= 0) return new long[]{Long.decode(text)}; 847 long[] splat = new long[amount + 1]; 848 int dl = 1, idx = -dl, idx2; 849 for (int i = 0; i < amount; i++) { 850 splat[i] = Long.decode(StringKit.safeSubstring(text, idx + dl, idx = text.indexOf(',', idx + dl))); 851 } 852 if ((idx2 = text.indexOf(',', idx + dl)) < 0) { 853 splat[amount] = Long.decode(StringKit.safeSubstring(text, idx + dl, text.length())); 854 } else { 855 splat[amount] = Long.decode(StringKit.safeSubstring(text, idx + dl, idx2)); 856 } 857 return splat; 858 } 859 }; 860 861 public static final StringConvert<float[]> convertArrayFloat = new StringConvert<float[]>(true,"float[]") { 862 @Override 863 public String stringify(float[] item) { 864 if(item == null) return "N"; 865 return StringKit.join(",", item); 866 } 867 868 @Override 869 public float[] restore(String text) { 870 if(text == null || text.equals("N")) return null; 871 int amount = StringKit.count(text, ","); 872 if (amount <= 0) return new float[]{Float.parseFloat(text)}; 873 float[] splat = new float[amount + 1]; 874 int dl = 1, idx = -dl, idx2; 875 for (int i = 0; i < amount; i++) { 876 splat[i] = Float.parseFloat(StringKit.safeSubstring(text, idx + dl, idx = text.indexOf(',', idx + dl))); 877 } 878 if ((idx2 = text.indexOf(',', idx + dl)) < 0) { 879 splat[amount] = Float.parseFloat(StringKit.safeSubstring(text, idx + dl, text.length())); 880 } else { 881 splat[amount] = Float.parseFloat(StringKit.safeSubstring(text, idx + dl, idx2)); 882 } 883 return splat; 884 } 885 }; 886 887 public static final StringConvert<double[]> convertArrayDouble = new StringConvert<double[]>(true,"double[]") { 888 @Override 889 public String stringify(double[] item) { 890 if(item == null) return "N"; 891 return StringKit.join(",", item); 892 } 893 894 @Override 895 public double[] restore(String text) { 896 if(text == null || text.equals("N")) return null; 897 int amount = StringKit.count(text, ","); 898 if (amount <= 0) return new double[]{Double.parseDouble(text)}; 899 double[] splat = new double[amount + 1]; 900 int dl = 1, idx = -dl, idx2; 901 for (int i = 0; i < amount; i++) { 902 splat[i] = Double.parseDouble(StringKit.safeSubstring(text, idx + dl, idx = text.indexOf(',', idx + dl))); 903 } 904 if ((idx2 = text.indexOf(',', idx + dl)) < 0) { 905 splat[amount] = Double.parseDouble(StringKit.safeSubstring(text, idx + dl, text.length())); 906 } else { 907 splat[amount] = Double.parseDouble(StringKit.safeSubstring(text, idx + dl, idx2)); 908 } 909 return splat; 910 } 911 }; 912 913 914 public static final StringConvert<char[]> convertArrayChar = new StringConvert<char[]>(true,"char[]") { 915 @Override 916 public String stringify(char[] item) { 917 if(item == null) return ""; 918 return String.valueOf(item); 919 } 920 921 @Override 922 public char[] restore(String text) { 923 return text.toCharArray(); 924 } 925 }; 926 927 public static final StringConvert<boolean[][]> convertArrayBoolean2D = new StringConvert<boolean[][]>(true, "boolean[][]") { 928 @Override 929 public String stringify(boolean[][] item) { 930 if(item == null) 931 return "N"; 932 int len; 933 if((len = item.length) <= 0) 934 return ""; 935 StringBuilder sb = new StringBuilder(len * 128); 936 if(item[0] == null) 937 sb.append('n'); 938 else 939 sb.append(StringKit.joinAlt(item[0])); 940 for (int i = 1; i < len; i++) { 941 if(item[i] == null) 942 sb.append(";n"); 943 else 944 sb.append(';').append(StringKit.joinAlt(item[i])); 945 } 946 return sb.toString(); 947 } 948 949 @Override 950 public boolean[][] restore(String text) { 951 if(text == null) return null; 952 int len; 953 if((len = text.length()) <= 0) return new boolean[0][0]; 954 if(text.charAt(0) == 'N') return null; 955 int width = StringKit.count(text, ';')+1; 956 boolean[][] val = new boolean[width][]; 957 int start = 0, end = text.indexOf(';'); 958 for (int i = 0; i < width; i++) { 959 if(start == end || start >= len) val[i] = new boolean[0]; 960 else if(text.charAt(start) == 'n') val[i] = null; 961 else { 962 int amount = end - start; 963 val[i] = new boolean[amount]; 964 for (int j = 0; j < amount; j++) { 965 val[i][j] = text.charAt(start + j) == '1'; 966 } 967 } 968 start = end+1; 969 end = text.indexOf(';', start); 970 } 971 return val; 972 } 973 }; 974 975 public static final StringConvert<byte[][]> convertArrayByte2D = new StringConvert<byte[][]>(true, "byte[][]") { 976 @Override 977 public String stringify(byte[][] item) { 978 if(item == null) 979 return "N"; 980 int len; 981 if((len = item.length) <= 0) 982 return ""; 983 StringBuilder sb = new StringBuilder(len * 128); 984 if(item[0] == null) 985 sb.append('n'); 986 else 987 sb.append(StringKit.join(",", item[0])); 988 for (int i = 1; i < len; i++) { 989 if(item[i] == null) 990 sb.append(";n"); 991 else 992 sb.append(';').append(StringKit.join(",", item[i])); 993 } 994 return sb.toString(); 995 } 996 997 @Override 998 public byte[][] restore(String text) { 999 if(text == null) return null; 1000 int len; 1001 if((len = text.length()) <= 0) return new byte[0][0]; 1002 if(text.charAt(0) == 'N') return null; 1003 int width = StringKit.count(text, ';')+1; 1004 byte[][] val = new byte[width][]; 1005 int start = 0, end = text.indexOf(';'); 1006 for (int i = 0; i < width; i++) { 1007 if(start == end || start >= len) val[i] = new byte[0]; 1008 else if(text.charAt(start) == 'n') val[i] = null; 1009 else { 1010 int amount = StringKit.count(text, ",", start, end); 1011 if (amount <= 0){ 1012 val[i] = new byte[]{Byte.decode(text)}; 1013 continue; 1014 } 1015 val[i] = new byte[amount + 1]; 1016 int dl = 1, idx = start - dl, idx2; 1017 for (int j = 0; j < amount; j++) { 1018 val[i][j] = Byte.decode(StringKit.safeSubstring(text, idx + dl, idx = text.indexOf(',', idx + dl))); 1019 } 1020 if ((idx2 = text.indexOf(',', idx + dl)) < 0) { 1021 val[i][amount] = Byte.decode(StringKit.safeSubstring(text, idx + dl, text.length())); 1022 } else if(idx2 < end){ 1023 val[i][amount] = Byte.decode(StringKit.safeSubstring(text, idx + dl, idx2)); 1024 } else { 1025 val[i][amount] = Byte.decode(StringKit.safeSubstring(text, idx + dl, end)); 1026 } 1027 } 1028 start = end+1; 1029 end = text.indexOf(';', start); 1030 } 1031 return val; 1032 } 1033 }; 1034 1035 1036 public static final StringConvert<short[][]> convertArrayShort2D = new StringConvert<short[][]>(true, "short[][]") { 1037 @Override 1038 public String stringify(short[][] item) { 1039 if(item == null) 1040 return "N"; 1041 int len; 1042 if((len = item.length) <= 0) 1043 return ""; 1044 StringBuilder sb = new StringBuilder(len * 128); 1045 if(item[0] == null) 1046 sb.append('n'); 1047 else 1048 sb.append(StringKit.join(",", item[0])); 1049 for (int i = 1; i < len; i++) { 1050 if(item[i] == null) 1051 sb.append(";n"); 1052 else 1053 sb.append(';').append(StringKit.join(",", item[i])); 1054 } 1055 return sb.toString(); 1056 } 1057 1058 @Override 1059 public short[][] restore(String text) { 1060 if(text == null) return null; 1061 int len; 1062 if((len = text.length()) <= 0) return new short[0][0]; 1063 if(text.charAt(0) == 'N') return null; 1064 int width = StringKit.count(text, ';')+1; 1065 short[][] val = new short[width][]; 1066 int start = 0, end = text.indexOf(';'); 1067 for (int i = 0; i < width; i++) { 1068 if(start == end || start >= len) val[i] = new short[0]; 1069 else if(text.charAt(start) == 'n') val[i] = null; 1070 else { 1071 int amount = StringKit.count(text, ",", start, end); 1072 if (amount <= 0){ 1073 val[i] = new short[]{Short.decode(text)}; 1074 continue; 1075 } 1076 val[i] = new short[amount + 1]; 1077 int dl = 1, idx = start - dl, idx2; 1078 for (int j = 0; j < amount; j++) { 1079 val[i][j] = Short.decode(StringKit.safeSubstring(text, idx + dl, idx = text.indexOf(',', idx + dl))); 1080 } 1081 if ((idx2 = text.indexOf(',', idx + dl)) < 0) { 1082 val[i][amount] = Short.decode(StringKit.safeSubstring(text, idx + dl, text.length())); 1083 } else if(idx2 < end){ 1084 val[i][amount] = Short.decode(StringKit.safeSubstring(text, idx + dl, idx2)); 1085 } else { 1086 val[i][amount] = Short.decode(StringKit.safeSubstring(text, idx + dl, end)); 1087 } 1088 } 1089 start = end+1; 1090 end = text.indexOf(';', start); 1091 } 1092 return val; 1093 } 1094 }; 1095 1096 public static final StringConvert<int[][]> convertArrayInt2D = new StringConvert<int[][]>(true, "int[][]") { 1097 @Override 1098 public String stringify(int[][] item) { 1099 if(item == null) 1100 return "N"; 1101 int len; 1102 if((len = item.length) <= 0) 1103 return ""; 1104 StringBuilder sb = new StringBuilder(len * 128); 1105 if(item[0] == null) 1106 sb.append('n'); 1107 else 1108 sb.append(StringKit.join(",", item[0])); 1109 for (int i = 1; i < len; i++) { 1110 if(item[i] == null) 1111 sb.append(";n"); 1112 else 1113 sb.append(';').append(StringKit.join(",", item[i])); 1114 } 1115 return sb.toString(); 1116 } 1117 1118 @Override 1119 public int[][] restore(String text) { 1120 if(text == null) return null; 1121 int len; 1122 if((len = text.length()) <= 0) return new int[0][0]; 1123 if(text.charAt(0) == 'N') return null; 1124 int width = StringKit.count(text, ';')+1; 1125 int[][] val = new int[width][]; 1126 int start = 0, end = text.indexOf(';'); 1127 for (int i = 0; i < width; i++) { 1128 if(start == end || start >= len) val[i] = new int[0]; 1129 else if(text.charAt(start) == 'n') val[i] = null; 1130 else { 1131 int amount = StringKit.count(text, ",", start, end); 1132 if (amount <= 0){ 1133 val[i] = new int[]{Integer.decode(text)}; 1134 continue; 1135 } 1136 val[i] = new int[amount + 1]; 1137 int dl = 1, idx = start - dl, idx2; 1138 for (int j = 0; j < amount; j++) { 1139 val[i][j] = Integer.decode(StringKit.safeSubstring(text, idx + dl, idx = text.indexOf(',', idx + dl))); 1140 } 1141 if ((idx2 = text.indexOf(',', idx + dl)) < 0) { 1142 val[i][amount] = Integer.decode(StringKit.safeSubstring(text, idx + dl, text.length())); 1143 } else if(idx2 < end){ 1144 val[i][amount] = Integer.decode(StringKit.safeSubstring(text, idx + dl, idx2)); 1145 } else { 1146 val[i][amount] = Integer.decode(StringKit.safeSubstring(text, idx + dl, end)); 1147 } 1148 } 1149 start = end+1; 1150 end = text.indexOf(';', start); 1151 } 1152 return val; 1153 } 1154 }; 1155 1156 public static final StringConvert<long[][]> convertArrayLong2D = new StringConvert<long[][]>(true, "long[][]") { 1157 @Override 1158 public String stringify(long[][] item) { 1159 if(item == null) 1160 return "N"; 1161 int len; 1162 if((len = item.length) <= 0) 1163 return ""; 1164 StringBuilder sb = new StringBuilder(len * 128); 1165 if(item[0] == null) 1166 sb.append('n'); 1167 else 1168 sb.append(StringKit.join(",", item[0])); 1169 for (int i = 1; i < len; i++) { 1170 if(item[i] == null) 1171 sb.append(";n"); 1172 else 1173 sb.append(';').append(StringKit.join(",", item[i])); 1174 } 1175 return sb.toString(); 1176 } 1177 1178 @Override 1179 public long[][] restore(String text) { 1180 if(text == null) return null; 1181 int len; 1182 if((len = text.length()) <= 0) return new long[0][0]; 1183 if(text.charAt(0) == 'N') return null; 1184 int width = StringKit.count(text, ';')+1; 1185 long[][] val = new long[width][]; 1186 int start = 0, end = text.indexOf(';'); 1187 for (int i = 0; i < width; i++) { 1188 if(start == end || start >= len) val[i] = new long[0]; 1189 else if(text.charAt(start) == 'n') val[i] = null; 1190 else { 1191 int amount = StringKit.count(text, ",", start, end); 1192 if (amount <= 0){ 1193 val[i] = new long[]{Long.decode(text)}; 1194 continue; 1195 } 1196 val[i] = new long[amount + 1]; 1197 int dl = 1, idx = start - dl, idx2; 1198 for (int j = 0; j < amount; j++) { 1199 val[i][j] = Long.decode(StringKit.safeSubstring(text, idx + dl, idx = text.indexOf(',', idx + dl))); 1200 } 1201 if ((idx2 = text.indexOf(',', idx + dl)) < 0) { 1202 val[i][amount] = Long.decode(StringKit.safeSubstring(text, idx + dl, text.length())); 1203 } else if(idx2 < end){ 1204 val[i][amount] = Long.decode(StringKit.safeSubstring(text, idx + dl, idx2)); 1205 } else { 1206 val[i][amount] = Long.decode(StringKit.safeSubstring(text, idx + dl, end)); 1207 } 1208 } 1209 start = end+1; 1210 end = text.indexOf(';', start); 1211 } 1212 return val; 1213 } 1214 }; 1215 1216 public static final StringConvert<float[][]> convertArrayFloat2D = new StringConvert<float[][]>(true, "float[][]") { 1217 @Override 1218 public String stringify(float[][] item) { 1219 if(item == null) 1220 return "N"; 1221 int len; 1222 if((len = item.length) <= 0) 1223 return ""; 1224 StringBuilder sb = new StringBuilder(len * 128); 1225 if(item[0] == null) 1226 sb.append('n'); 1227 else 1228 sb.append(StringKit.join(",", item[0])); 1229 for (int i = 1; i < len; i++) { 1230 if(item[i] == null) 1231 sb.append(";n"); 1232 else 1233 sb.append(';').append(StringKit.join(",", item[i])); 1234 } 1235 return sb.toString(); 1236 } 1237 1238 @Override 1239 public float[][] restore(String text) { 1240 if(text == null) return null; 1241 int len; 1242 if((len = text.length()) <= 0) return new float[0][0]; 1243 if(text.charAt(0) == 'N') return null; 1244 int width = StringKit.count(text, ';')+1; 1245 float[][] val = new float[width][]; 1246 int start = 0, end = text.indexOf(';'); 1247 for (int i = 0; i < width; i++) { 1248 if(start == end || start >= len) val[i] = new float[0]; 1249 else if(text.charAt(start) == 'n') val[i] = null; 1250 else { 1251 int amount = StringKit.count(text, ",", start, end); 1252 if (amount <= 0){ 1253 val[i] = new float[]{Float.parseFloat(text)}; 1254 continue; 1255 } 1256 val[i] = new float[amount + 1]; 1257 int dl = 1, idx = start - dl, idx2; 1258 for (int j = 0; j < amount; j++) { 1259 val[i][j] = Float.parseFloat(StringKit.safeSubstring(text, idx + dl, idx = text.indexOf(',', idx + dl))); 1260 } 1261 if ((idx2 = text.indexOf(',', idx + dl)) < 0) { 1262 val[i][amount] = Float.parseFloat(StringKit.safeSubstring(text, idx + dl, text.length())); 1263 } else if(idx2 < end){ 1264 val[i][amount] = Float.parseFloat(StringKit.safeSubstring(text, idx + dl, idx2)); 1265 } else { 1266 val[i][amount] = Float.parseFloat(StringKit.safeSubstring(text, idx + dl, end)); 1267 } 1268 } 1269 start = end+1; 1270 end = text.indexOf(';', start); 1271 } 1272 return val; 1273 } 1274 }; 1275 1276 public static final StringConvert<double[][]> convertArrayDouble2D = new StringConvert<double[][]>(true, "double[][]") { 1277 @Override 1278 public String stringify(double[][] item) { 1279 if(item == null) 1280 return "N"; 1281 int len; 1282 if((len = item.length) <= 0) 1283 return ""; 1284 StringBuilder sb = new StringBuilder(len * 128); 1285 if(item[0] == null) 1286 sb.append('n'); 1287 else 1288 sb.append(StringKit.join(",", item[0])); 1289 for (int i = 1; i < len; i++) { 1290 if(item[i] == null) 1291 sb.append(";n"); 1292 else 1293 sb.append(';').append(StringKit.join(",", item[i])); 1294 } 1295 return sb.toString(); 1296 } 1297 1298 @Override 1299 public double[][] restore(String text) { 1300 if(text == null) return null; 1301 int len; 1302 if((len = text.length()) <= 0) return new double[0][0]; 1303 if(text.charAt(0) == 'N') return null; 1304 int width = StringKit.count(text, ';')+1; 1305 double[][] val = new double[width][]; 1306 int start = 0, end = text.indexOf(';'); 1307 for (int i = 0; i < width; i++) { 1308 if(start == end || start >= len) val[i] = new double[0]; 1309 else if(text.charAt(start) == 'n') val[i] = null; 1310 else { 1311 int amount = StringKit.count(text, ",", start, end); 1312 if (amount <= 0){ 1313 val[i] = new double[]{Double.parseDouble(text)}; 1314 continue; 1315 } 1316 val[i] = new double[amount + 1]; 1317 int dl = 1, idx = start - dl, idx2; 1318 for (int j = 0; j < amount; j++) { 1319 val[i][j] = Double.parseDouble(StringKit.safeSubstring(text, idx + dl, idx = text.indexOf(',', idx + dl))); 1320 } 1321 if ((idx2 = text.indexOf(',', idx + dl)) < 0) { 1322 val[i][amount] = Double.parseDouble(StringKit.safeSubstring(text, idx + dl, text.length())); 1323 } else if(idx2 < end){ 1324 val[i][amount] = Double.parseDouble(StringKit.safeSubstring(text, idx + dl, idx2)); 1325 } else { 1326 val[i][amount] = Double.parseDouble(StringKit.safeSubstring(text, idx + dl, end)); 1327 } 1328 } 1329 start = end+1; 1330 end = text.indexOf(';', start); 1331 } 1332 return val; 1333 } 1334 }; 1335 1336 1337 public static final StringConvert<char[][]> convertArrayChar2D = new StringConvert<char[][]>(true, "char[][]") { 1338 @Override 1339 public String stringify(char[][] item) { 1340 int len, l2, sum; 1341 if (item == null) return "N"; // N for null 1342 if((len = item.length) <= 0) return "R0|0|"; 1343 sum = l2 = item[0].length; 1344 char regular = 'R'; // R for rectangular 1345 for (int i = 1; i < len; i++) { 1346 if(item[i] == null) 1347 { 1348 regular = 'J'; // J for jagged 1349 } 1350 else if(l2 != (l2 = item[i].length)) 1351 { 1352 regular = 'J'; // J for jagged 1353 sum += l2; 1354 } 1355 } 1356 StringBuilder sb; 1357 if(regular == 'R') 1358 { 1359 sb = new StringBuilder(len * l2 + 15); 1360 sb.append('R').append(len).append('|').append(l2).append('|'); 1361 for (int i = 0; i < len; i++) { 1362 sb.append(item[i]); 1363 } 1364 } 1365 else 1366 { 1367 sb = new StringBuilder(len * 7 + sum + 8); 1368 sb.append('J').append(len).append('|'); 1369 for (int i = 0; i < len; i++) { 1370 if(item[i] == null) 1371 sb.append("-|"); 1372 else 1373 sb.append(item[i].length).append('|').append(item[i]); 1374 } 1375 } 1376 return sb.toString(); 1377 } 1378 1379 @Override 1380 public char[][] restore(String text) { 1381 if(text == null || text.length() <= 1) return null; 1382 if(text.charAt(0) == 'R') 1383 { 1384 int width, height, start = 1, end = text.indexOf('|'); 1385 width = StringKit.intFromDec(text, start, end); 1386 start = end+1; 1387 end = text.indexOf('|', start); 1388 height = StringKit.intFromDec(text, start, end); 1389 start = end+1; 1390 char[][] val = new char[width][height]; 1391 for (int i = 0; i < width; i++) { 1392 text.getChars(start, start += height, val[i], 0); 1393 } 1394 return val; 1395 } 1396 else 1397 { 1398 int width, current, start = 1, end = text.indexOf('|'); 1399 width = StringKit.intFromDec(text, start, end); 1400 start = end + 1; 1401 char[][] val = new char[width][]; 1402 for (int i = 0; i < width; i++) { 1403 end = text.indexOf('|', start); 1404 if (text.charAt(start) == '-') { 1405 val[i] = null; 1406 start = end + 1; 1407 } else { 1408 current = StringKit.intFromDec(text, start, end); 1409 start = end + 1; 1410 val[i] = new char[current]; 1411 text.getChars(start, start += current, val[i], 0); 1412 } 1413 } 1414 return val; 1415 } 1416 } 1417 }; 1418 1419}