src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java
changeset 49944 4690a2871b44
parent 49765 ee6f7a61f3a5
child 50681 4254bed3c09d
child 56507 2294c51eae30
equal deleted inserted replaced
49943:8e1ed2a15845 49944:4690a2871b44
    42 import java.net.InetSocketAddress;
    42 import java.net.InetSocketAddress;
    43 import java.net.URI;
    43 import java.net.URI;
    44 import java.net.URLPermission;
    44 import java.net.URLPermission;
    45 import java.net.http.HttpHeaders;
    45 import java.net.http.HttpHeaders;
    46 import java.nio.ByteBuffer;
    46 import java.nio.ByteBuffer;
       
    47 import java.nio.CharBuffer;
       
    48 import java.nio.charset.CharacterCodingException;
    47 import java.nio.charset.Charset;
    49 import java.nio.charset.Charset;
       
    50 import java.nio.charset.CodingErrorAction;
    48 import java.nio.charset.StandardCharsets;
    51 import java.nio.charset.StandardCharsets;
    49 import java.security.AccessController;
    52 import java.security.AccessController;
    50 import java.security.PrivilegedAction;
    53 import java.security.PrivilegedAction;
       
    54 import java.text.Normalizer;
    51 import java.util.Arrays;
    55 import java.util.Arrays;
    52 import java.util.Collection;
    56 import java.util.Collection;
    53 import java.util.Collections;
    57 import java.util.Collections;
    54 import java.util.List;
    58 import java.util.List;
    55 import java.util.Set;
    59 import java.util.Set;
   579             }
   583             }
   580         }
   584         }
   581         return (int) remain;
   585         return (int) remain;
   582     }
   586     }
   583 
   587 
   584     public static long remaining(ByteBufferReference[] refs) {
       
   585         long remain = 0;
       
   586         for (ByteBufferReference ref : refs) {
       
   587             remain += ref.get().remaining();
       
   588         }
       
   589         return remain;
       
   590     }
       
   591 
       
   592     public static int remaining(ByteBufferReference[] refs, int max) {
       
   593         long remain = 0;
       
   594         for (ByteBufferReference ref : refs) {
       
   595             remain += ref.get().remaining();
       
   596             if (remain > max) {
       
   597                 throw new IllegalArgumentException("too many bytes");
       
   598             }
       
   599         }
       
   600         return (int) remain;
       
   601     }
       
   602 
       
   603     public static int remaining(ByteBuffer[] refs, int max) {
   588     public static int remaining(ByteBuffer[] refs, int max) {
   604         long remain = 0;
   589         long remain = 0;
   605         for (ByteBuffer b : refs) {
   590         for (ByteBuffer b : refs) {
   606             remain += b.remaining();
   591             remain += b.remaining();
   607             if (remain > max) {
   592             if (remain > max) {
   621 
   606 
   622     // Put all these static 'empty' singletons here
   607     // Put all these static 'empty' singletons here
   623     public static final ByteBuffer EMPTY_BYTEBUFFER = ByteBuffer.allocate(0);
   608     public static final ByteBuffer EMPTY_BYTEBUFFER = ByteBuffer.allocate(0);
   624     public static final ByteBuffer[] EMPTY_BB_ARRAY = new ByteBuffer[0];
   609     public static final ByteBuffer[] EMPTY_BB_ARRAY = new ByteBuffer[0];
   625     public static final List<ByteBuffer> EMPTY_BB_LIST = List.of();
   610     public static final List<ByteBuffer> EMPTY_BB_LIST = List.of();
   626     public static final ByteBufferReference[] EMPTY_BBR_ARRAY = new ByteBufferReference[0];
       
   627 
   611 
   628     /**
   612     /**
   629      * Returns a slice of size {@code amount} from the given buffer. If the
   613      * Returns a slice of size {@code amount} from the given buffer. If the
   630      * buffer contains more data than {@code amount}, then the slice's capacity
   614      * buffer contains more data than {@code amount}, then the slice's capacity
   631      * ( and, but not just, its limit ) is set to {@code amount}. If the buffer
   615      * ( and, but not just, its limit ) is set to {@code amount}. If the buffer
   957             return 1 << 30;
   941             return 1 << 30;
   958         } else {
   942         } else {
   959             return 1 << (32 - Integer.numberOfLeadingZeros(n - 1));
   943             return 1 << (32 - Integer.numberOfLeadingZeros(n - 1));
   960         }
   944         }
   961     }
   945     }
       
   946 
       
   947     // -- toAsciiString-like support to encode path and query URI segments
       
   948 
       
   949     private static final char[] hexDigits = {
       
   950             '0', '1', '2', '3', '4', '5', '6', '7',
       
   951             '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
       
   952     };
       
   953 
       
   954     private static void appendEscape(StringBuilder sb, byte b) {
       
   955         sb.append('%');
       
   956         sb.append(hexDigits[(b >> 4) & 0x0f]);
       
   957         sb.append(hexDigits[(b >> 0) & 0x0f]);
       
   958     }
       
   959 
       
   960     // Encodes all characters >= \u0080 into escaped, normalized UTF-8 octets,
       
   961     // assuming that s is otherwise legal
       
   962     //
       
   963     public static String encode(String s) {
       
   964         int n = s.length();
       
   965         if (n == 0)
       
   966             return s;
       
   967 
       
   968         // First check whether we actually need to encode
       
   969         for (int i = 0;;) {
       
   970             if (s.charAt(i) >= '\u0080')
       
   971                 break;
       
   972             if (++i >= n)
       
   973                 return s;
       
   974         }
       
   975 
       
   976         String ns = Normalizer.normalize(s, Normalizer.Form.NFC);
       
   977         ByteBuffer bb = null;
       
   978         try {
       
   979             bb = StandardCharsets.UTF_8.newEncoder()
       
   980                     .onMalformedInput(CodingErrorAction.REPORT)
       
   981                     .onUnmappableCharacter(CodingErrorAction.REPORT)
       
   982                     .encode(CharBuffer.wrap(ns));
       
   983         } catch (CharacterCodingException x) {
       
   984             assert false : x;
       
   985         }
       
   986 
       
   987         StringBuilder sb = new StringBuilder();
       
   988         while (bb.hasRemaining()) {
       
   989             int b = bb.get() & 0xff;
       
   990             if (b >= 0x80)
       
   991                 appendEscape(sb, (byte)b);
       
   992             else
       
   993                 sb.append((char)b);
       
   994         }
       
   995         return sb.toString();
       
   996     }
   962 }
   997 }