528 return StringUTF16.newString(result, 0, resultOffset);
529 }
530
531 public static String trim(byte[] value) {
532 int len = value.length;
533 int st = 0;
534 while ((st < len) && ((value[st] & 0xff) <= ' ')) {
535 st++;
536 }
537 while ((st < len) && ((value[len - 1] & 0xff) <= ' ')) {
538 len--;
539 }
540 return ((st > 0) || (len < value.length)) ?
541 newString(value, st, len - st) : null;
542 }
543
544 public static int indexOfNonWhitespace(byte[] value) {
545 int length = value.length;
546 int left = 0;
547 while (left < length) {
548 char ch = (char)(value[left] & 0xff);
549 if (ch != ' ' && ch != '\t' && !Character.isWhitespace(ch)) {
550 break;
551 }
552 left++;
553 }
554 return left;
555 }
556
557 public static int lastIndexOfNonWhitespace(byte[] value) {
558 int length = value.length;
559 int right = length;
560 while (0 < right) {
561 char ch = (char)(value[right - 1] & 0xff);
562 if (ch != ' ' && ch != '\t' && !Character.isWhitespace(ch)) {
563 break;
564 }
565 right--;
566 }
567 return right;
568 }
569
570 public static String strip(byte[] value) {
571 int left = indexOfNonWhitespace(value);
572 if (left == value.length) {
573 return "";
574 }
575 int right = lastIndexOfNonWhitespace(value);
576 return ((left > 0) || (right < value.length)) ? newString(value, left, right - left) : null;
577 }
578
579 public static String stripLeading(byte[] value) {
580 int left = indexOfNonWhitespace(value);
581 if (left == value.length) {
582 return "";
583 }
584 return (left != 0) ? newString(value, left, value.length - left) : null;
585 }
586
587 public static String stripTrailing(byte[] value) {
588 int right = lastIndexOfNonWhitespace(value);
589 if (right == 0) {
590 return "";
591 }
592 return (right != value.length) ? newString(value, 0, right) : null;
593 }
594
595 private final static class LinesSpliterator implements Spliterator<String> {
596 private byte[] value;
597 private int index; // current index, modified on advance/split
598 private final int fence; // one past last index
599
600 LinesSpliterator(byte[] value) {
601 this(value, 0, value.length);
602 }
603
604 LinesSpliterator(byte[] value, int start, int length) {
605 this.value = value;
606 this.index = start;
607 this.fence = start + length;
608 }
609
610 private int indexOfLineSeparator(int start) {
611 for (int current = start; current < fence; current++) {
612 byte ch = value[current];
613 if (ch == '\n' || ch == '\r') {
614 return current;
615 }
616 }
617 return fence;
618 }
619
620 private int skipLineSeparator(int start) {
621 if (start < fence) {
622 if (value[start] == '\r') {
623 int next = start + 1;
624 if (next < fence && value[next] == '\n') {
625 return next + 1;
626 }
627 }
628 return start + 1;
629 }
630 return fence;
631 }
632
633 private String next() {
634 int start = index;
635 int end = indexOfLineSeparator(start);
636 index = skipLineSeparator(end);
637 return newString(value, start, end - start);
638 }
639
640 @Override
641 public boolean tryAdvance(Consumer<? super String> action) {
642 if (action == null) {
643 throw new NullPointerException("tryAdvance action missing");
644 }
663 public Spliterator<String> trySplit() {
664 int half = (fence + index) >>> 1;
665 int mid = skipLineSeparator(indexOfLineSeparator(half));
666 if (mid < fence) {
667 int start = index;
668 index = mid;
669 return new LinesSpliterator(value, start, mid - start);
670 }
671 return null;
672 }
673
674 @Override
675 public long estimateSize() {
676 return fence - index + 1;
677 }
678
679 @Override
680 public int characteristics() {
681 return Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL;
682 }
683 }
684
685 static Stream<String> lines(byte[] value) {
686 return StreamSupport.stream(new LinesSpliterator(value), false);
687 }
688
689 public static void putChar(byte[] val, int index, int c) {
690 //assert (canEncode(c));
691 val[index] = (byte)(c);
692 }
693
694 public static char getChar(byte[] val, int index) {
695 return (char)(val[index] & 0xff);
696 }
697
698 public static byte[] toBytes(int[] val, int off, int len) {
699 byte[] ret = new byte[len];
700 for (int i = 0; i < len; i++) {
701 int cp = val[off++];
702 if (!canEncode(cp)) {
703 return null;
704 }
705 ret[i] = (byte)cp;
706 }
|
528 return StringUTF16.newString(result, 0, resultOffset);
529 }
530
531 public static String trim(byte[] value) {
532 int len = value.length;
533 int st = 0;
534 while ((st < len) && ((value[st] & 0xff) <= ' ')) {
535 st++;
536 }
537 while ((st < len) && ((value[len - 1] & 0xff) <= ' ')) {
538 len--;
539 }
540 return ((st > 0) || (len < value.length)) ?
541 newString(value, st, len - st) : null;
542 }
543
544 public static int indexOfNonWhitespace(byte[] value) {
545 int length = value.length;
546 int left = 0;
547 while (left < length) {
548 char ch = getChar(value, left);
549 if (ch != ' ' && ch != '\t' && !Character.isWhitespace(ch)) {
550 break;
551 }
552 left++;
553 }
554 return left;
555 }
556
557 public static int lastIndexOfNonWhitespace(byte[] value) {
558 int length = value.length;
559 int right = length;
560 while (0 < right) {
561 char ch = getChar(value, right - 1);
562 if (ch != ' ' && ch != '\t' && !Character.isWhitespace(ch)) {
563 break;
564 }
565 right--;
566 }
567 return right;
568 }
569
570 public static String strip(byte[] value) {
571 int left = indexOfNonWhitespace(value);
572 if (left == value.length) {
573 return "";
574 }
575 int right = lastIndexOfNonWhitespace(value);
576 boolean ifChanged = (left > 0) || (right < value.length);
577 return ifChanged ? newString(value, left, right - left) : null;
578 }
579
580 public static String stripLeading(byte[] value) {
581 int left = indexOfNonWhitespace(value);
582 if (left == value.length) {
583 return "";
584 }
585 return (left != 0) ? newString(value, left, value.length - left) : null;
586 }
587
588 public static String stripTrailing(byte[] value) {
589 int right = lastIndexOfNonWhitespace(value);
590 if (right == 0) {
591 return "";
592 }
593 return (right != value.length) ? newString(value, 0, right) : null;
594 }
595
596 private final static class LinesSpliterator implements Spliterator<String> {
597 private byte[] value;
598 private int index; // current index, modified on advance/split
599 private final int fence; // one past last index
600
601 private LinesSpliterator(byte[] value, int start, int length) {
602 this.value = value;
603 this.index = start;
604 this.fence = start + length;
605 }
606
607 private int indexOfLineSeparator(int start) {
608 for (int current = start; current < fence; current++) {
609 char ch = getChar(value, current);
610 if (ch == '\n' || ch == '\r') {
611 return current;
612 }
613 }
614 return fence;
615 }
616
617 private int skipLineSeparator(int start) {
618 if (start < fence) {
619 if (getChar(value, start) == '\r') {
620 int next = start + 1;
621 if (next < fence && getChar(value, next) == '\n') {
622 return next + 1;
623 }
624 }
625 return start + 1;
626 }
627 return fence;
628 }
629
630 private String next() {
631 int start = index;
632 int end = indexOfLineSeparator(start);
633 index = skipLineSeparator(end);
634 return newString(value, start, end - start);
635 }
636
637 @Override
638 public boolean tryAdvance(Consumer<? super String> action) {
639 if (action == null) {
640 throw new NullPointerException("tryAdvance action missing");
641 }
660 public Spliterator<String> trySplit() {
661 int half = (fence + index) >>> 1;
662 int mid = skipLineSeparator(indexOfLineSeparator(half));
663 if (mid < fence) {
664 int start = index;
665 index = mid;
666 return new LinesSpliterator(value, start, mid - start);
667 }
668 return null;
669 }
670
671 @Override
672 public long estimateSize() {
673 return fence - index + 1;
674 }
675
676 @Override
677 public int characteristics() {
678 return Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL;
679 }
680
681 static LinesSpliterator spliterator(byte[] value) {
682 return new LinesSpliterator(value, 0, value.length);
683 }
684
685 static LinesSpliterator spliterator(byte[] value, int leading, int trailing) {
686 int length = value.length;
687 int left = 0;
688 int index;
689 for (int l = 0; l < leading; l++) {
690 index = skipBlankForward(value, left, length);
691 if (index == left) {
692 break;
693 }
694 left = index;
695 }
696 int right = length;
697 for (int t = 0; t < trailing; t++) {
698 index = skipBlankBackward(value, left, right);
699 if (index == right) {
700 break;
701 }
702 right = index;
703 }
704 return new LinesSpliterator(value, left, right - left);
705 }
706
707 private static int skipBlankForward(byte[] value, int start, int length) {
708 int index = start;
709 while (index < length) {
710 char ch = getChar(value, index++);
711 if (ch == '\n') {
712 return index;
713 }
714 if (ch == '\r') {
715 if (index < length && getChar(value, index) == '\n') {
716 return index + 1;
717 }
718 return index;
719 }
720 if (ch != ' ' && ch != '\t' && !Character.isWhitespace(ch)) {
721 return start;
722 }
723 }
724 return length;
725 }
726
727 private static int skipBlankBackward(byte[] value, int start, int fence) {
728 int index = fence;
729 if (start < index && getChar(value, index - 1) == '\n') {
730 index--;
731 }
732 if (start < index && getChar(value, index - 1) == '\r') {
733 index--;
734 }
735 while (start < index) {
736 char ch = getChar(value, --index);
737 if (ch == '\r' || ch == '\n') {
738 return index + 1;
739 }
740 if (ch != ' ' && ch != '\t' && !Character.isWhitespace(ch)) {
741 return fence;
742 }
743 }
744 return start;
745 }
746 }
747
748 static Stream<String> lines(byte[] value, int leading, int trailing) {
749 if (leading == 0 && trailing == 0) {
750 return StreamSupport.stream(LinesSpliterator.spliterator(value), false);
751 } else {
752 return StreamSupport.stream(LinesSpliterator.spliterator(value, leading, trailing), false);
753 }
754 }
755
756 public static void putChar(byte[] val, int index, int c) {
757 //assert (canEncode(c));
758 val[index] = (byte)(c);
759 }
760
761 public static char getChar(byte[] val, int index) {
762 return (char)(val[index] & 0xff);
763 }
764
765 public static byte[] toBytes(int[] val, int off, int len) {
766 byte[] ret = new byte[len];
767 for (int i = 0; i < len; i++) {
768 int cp = val[off++];
769 if (!canEncode(cp)) {
770 return null;
771 }
772 ret[i] = (byte)cp;
773 }
|