842 }
843 }
844 return newString(result, 0, resultOffset);
845 }
846
847 public static String trim(byte[] value) {
848 int length = value.length >> 1;
849 int len = length;
850 int st = 0;
851 while (st < len && getChar(value, st) <= ' ') {
852 st++;
853 }
854 while (st < len && getChar(value, len - 1) <= ' ') {
855 len--;
856 }
857 return ((st > 0) || (len < length )) ?
858 new String(Arrays.copyOfRange(value, st << 1, len << 1), UTF16) :
859 null;
860 }
861
862
863 public static int indexOfNonWhitespace(byte[] value) {
864 int length = value.length >> 1;
865 int left = 0;
866 while (left < length) {
867 int codepoint = codePointAt(value, left, length);
868 if (codepoint != ' ' && codepoint != '\t' && !Character.isWhitespace(codepoint)) {
869 break;
870 }
871 left += Character.charCount(codepoint);
872 }
873 return left;
874 }
875
876 public static int lastIndexOfNonWhitespace(byte[] value) {
877 int length = value.length >> 1;
878 int right = length;
879 while (0 < right) {
880 int codepoint = codePointBefore(value, right);
881 if (codepoint != ' ' && codepoint != '\t' && !Character.isWhitespace(codepoint)) {
882 break;
883 }
884 right -= Character.charCount(codepoint);
885 }
886 return right;
887 }
888
889 public static String strip(byte[] value) {
890 int length = value.length >> 1;
891 int left = indexOfNonWhitespace(value);
892 if (left == length) {
893 return "";
894 }
895 int right = lastIndexOfNonWhitespace(value);
896 return ((left > 0) || (right < length)) ? newString(value, left, right - left) : null;
897 }
898
899 public static String stripLeading(byte[] value) {
900 int length = value.length >> 1;
901 int left = indexOfNonWhitespace(value);
902 if (left == length) {
903 return "";
904 }
905 return (left != 0) ? newString(value, left, length - left) : null;
906 }
907
908 public static String stripTrailing(byte[] value) {
909 int length = value.length >> 1;
910 int right = lastIndexOfNonWhitespace(value);
911 if (right == 0) {
912 return "";
913 }
914 return (right != length) ? newString(value, 0, right) : null;
915 }
916
917 private final static class LinesSpliterator implements Spliterator<String> {
918 private byte[] value;
919 private int index; // current index, modified on advance/split
920 private final int fence; // one past last index
921
922 LinesSpliterator(byte[] value) {
923 this(value, 0, value.length >>> 1);
924 }
925
926 LinesSpliterator(byte[] value, int start, int length) {
927 this.value = value;
928 this.index = start;
929 this.fence = start + length;
930 }
931
932 private int indexOfLineSeparator(int start) {
933 for (int current = start; current < fence; current++) {
934 char ch = getChar(value, current);
935 if (ch == '\n' || ch == '\r') {
936 return current;
937 }
938 }
939 return fence;
940 }
941
942 private int skipLineSeparator(int start) {
943 if (start < fence) {
944 if (getChar(value, start) == '\r') {
945 int next = start + 1;
946 if (next < fence && getChar(value, next) == '\n') {
985 public Spliterator<String> trySplit() {
986 int half = (fence + index) >>> 1;
987 int mid = skipLineSeparator(indexOfLineSeparator(half));
988 if (mid < fence) {
989 int start = index;
990 index = mid;
991 return new LinesSpliterator(value, start, mid - start);
992 }
993 return null;
994 }
995
996 @Override
997 public long estimateSize() {
998 return fence - index + 1;
999 }
1000
1001 @Override
1002 public int characteristics() {
1003 return Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL;
1004 }
1005 }
1006
1007 static Stream<String> lines(byte[] value) {
1008 return StreamSupport.stream(new LinesSpliterator(value), false);
1009 }
1010
1011 private static void putChars(byte[] val, int index, char[] str, int off, int end) {
1012 while (off < end) {
1013 putChar(val, index++, str[off++]);
1014 }
1015 }
1016
1017 public static String newString(byte[] val, int index, int len) {
1018 if (String.COMPACT_STRINGS) {
1019 byte[] buf = compress(val, index, len);
1020 if (buf != null) {
1021 return new String(buf, LATIN1);
1022 }
1023 }
1024 int last = index + len;
1025 return new String(Arrays.copyOfRange(val, index << 1, last << 1), UTF16);
1026 }
1027
1028 public static void fillNull(byte[] val, int index, int end) {
|
842 }
843 }
844 return newString(result, 0, resultOffset);
845 }
846
847 public static String trim(byte[] value) {
848 int length = value.length >> 1;
849 int len = length;
850 int st = 0;
851 while (st < len && getChar(value, st) <= ' ') {
852 st++;
853 }
854 while (st < len && getChar(value, len - 1) <= ' ') {
855 len--;
856 }
857 return ((st > 0) || (len < length )) ?
858 new String(Arrays.copyOfRange(value, st << 1, len << 1), UTF16) :
859 null;
860 }
861
862 public static int indexOfNonWhitespace(byte[] value) {
863 int length = value.length >> 1;
864 int left = 0;
865 while (left < length) {
866 int codepoint = codePointAt(value, left, length);
867 if (codepoint != ' ' && codepoint != '\t' && !Character.isWhitespace(codepoint)) {
868 break;
869 }
870 left += Character.charCount(codepoint);
871 }
872 return left;
873 }
874
875 public static int lastIndexOfNonWhitespace(byte[] value) {
876 int length = value.length >>> 1;
877 int right = length;
878 while (0 < right) {
879 int codepoint = codePointBefore(value, right);
880 if (codepoint != ' ' && codepoint != '\t' && !Character.isWhitespace(codepoint)) {
881 break;
882 }
883 right -= Character.charCount(codepoint);
884 }
885 return right;
886 }
887
888 public static String strip(byte[] value) {
889 int length = value.length >>> 1;
890 int left = indexOfNonWhitespace(value);
891 if (left == length) {
892 return "";
893 }
894 int right = lastIndexOfNonWhitespace(value);
895 boolean ifChanged = (left > 0) || (right < length);
896 return ifChanged ? newString(value, left, right - left) : null;
897 }
898
899 public static String stripLeading(byte[] value) {
900 int length = value.length >>> 1;
901 int left = indexOfNonWhitespace(value);
902 if (left == length) {
903 return "";
904 }
905 return (left != 0) ? newString(value, left, length - left) : null;
906 }
907
908 public static String stripTrailing(byte[] value) {
909 int length = value.length >>> 1;
910 int right = lastIndexOfNonWhitespace(value);
911 if (right == 0) {
912 return "";
913 }
914 return (right != length) ? newString(value, 0, right) : null;
915 }
916
917 private final static class LinesSpliterator implements Spliterator<String> {
918 private byte[] value;
919 private int index; // current index, modified on advance/split
920 private final int fence; // one past last index
921
922 private LinesSpliterator(byte[] value, int start, int length) {
923 this.value = value;
924 this.index = start;
925 this.fence = start + length;
926 }
927
928 private int indexOfLineSeparator(int start) {
929 for (int current = start; current < fence; current++) {
930 char ch = getChar(value, current);
931 if (ch == '\n' || ch == '\r') {
932 return current;
933 }
934 }
935 return fence;
936 }
937
938 private int skipLineSeparator(int start) {
939 if (start < fence) {
940 if (getChar(value, start) == '\r') {
941 int next = start + 1;
942 if (next < fence && getChar(value, next) == '\n') {
981 public Spliterator<String> trySplit() {
982 int half = (fence + index) >>> 1;
983 int mid = skipLineSeparator(indexOfLineSeparator(half));
984 if (mid < fence) {
985 int start = index;
986 index = mid;
987 return new LinesSpliterator(value, start, mid - start);
988 }
989 return null;
990 }
991
992 @Override
993 public long estimateSize() {
994 return fence - index + 1;
995 }
996
997 @Override
998 public int characteristics() {
999 return Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL;
1000 }
1001
1002 static LinesSpliterator spliterator(byte[] value) {
1003 return new LinesSpliterator(value, 0, value.length >>> 1);
1004 }
1005
1006 static LinesSpliterator spliterator(byte[] value, int leading, int trailing) {
1007 int length = value.length >>> 1;
1008 int left = 0;
1009 int index;
1010 for (int l = 0; l < leading; l++) {
1011 index = skipBlankForward(value, left, length);
1012 if (index == left) {
1013 break;
1014 }
1015 left = index;
1016 }
1017 int right = length;
1018 for (int t = 0; t < trailing; t++) {
1019 index = skipBlankBackward(value, left, right);
1020 if (index == right) {
1021 break;
1022 }
1023 right = index;
1024 }
1025 return new LinesSpliterator(value, left, right - left);
1026 }
1027
1028 private static int skipBlankForward(byte[] value, int start, int length) {
1029 int index = start;
1030 while (index < length) {
1031 char ch = getChar(value, index++);
1032 if (ch == '\n') {
1033 return index;
1034 }
1035 if (ch == '\r') {
1036 if (index < length && getChar(value, index) == '\n') {
1037 return index + 1;
1038 }
1039 return index;
1040 }
1041 if (ch != ' ' && ch != '\t' && !Character.isWhitespace(ch)) {
1042 return start;
1043 }
1044 }
1045 return length;
1046 }
1047
1048 private static int skipBlankBackward(byte[] value, int start, int fence) {
1049 int index = fence;
1050 if (start < index && getChar(value, index - 1) == '\n') {
1051 index--;
1052 }
1053 if (start < index && getChar(value, index - 1) == '\r') {
1054 index--;
1055 }
1056 while (start < index) {
1057 char ch = getChar(value, --index);
1058 if (ch == '\r' || ch == '\n') {
1059 return index + 1;
1060 }
1061 if (ch != ' ' && ch != '\t' && !Character.isWhitespace(ch)) {
1062 return fence;
1063 }
1064 }
1065 return start;
1066 }
1067 }
1068
1069 static Stream<String> lines(byte[] value, int leading, int trailing) {
1070 if (leading == 0 && trailing == 0) {
1071 return StreamSupport.stream(LinesSpliterator.spliterator(value), false);
1072 } else {
1073 return StreamSupport.stream(LinesSpliterator.spliterator(value, leading, trailing), false);
1074 }
1075 }
1076
1077 private static void putChars(byte[] val, int index, char[] str, int off, int end) {
1078 while (off < end) {
1079 putChar(val, index++, str[off++]);
1080 }
1081 }
1082
1083 public static String newString(byte[] val, int index, int len) {
1084 if (String.COMPACT_STRINGS) {
1085 byte[] buf = compress(val, index, len);
1086 if (buf != null) {
1087 return new String(buf, LATIN1);
1088 }
1089 }
1090 int last = index + len;
1091 return new String(Arrays.copyOfRange(val, index << 1, last << 1), UTF16);
1092 }
1093
1094 public static void fillNull(byte[] val, int index, int end) {
|