1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.squareup.okhttp.internal.http; 18 19 final class HeaderParser { 20 21 public interface CacheControlHandler { 22 void handle(String directive, String parameter); 23 } 24 25 /** Parse a comma-separated list of cache control header values. */ 26 public static void parseCacheControl(String value, CacheControlHandler handler) { 27 int pos = 0; 28 while (pos < value.length()) { 29 int tokenStart = pos; 30 pos = skipUntil(value, pos, "=,"); 31 String directive = value.substring(tokenStart, pos).trim(); 32 33 if (pos == value.length() || value.charAt(pos) == ',') { 34 pos++; // consume ',' (if necessary) 35 handler.handle(directive, null); 36 continue; 37 } 38 39 pos++; // consume '=' 40 pos = skipWhitespace(value, pos); 41 42 String parameter; 43 44 // quoted string 45 if (pos < value.length() && value.charAt(pos) == '\"') { 46 pos++; // consume '"' open quote 47 int parameterStart = pos; 48 pos = skipUntil(value, pos, "\""); 49 parameter = value.substring(parameterStart, pos); 50 pos++; // consume '"' close quote (if necessary) 51 52 // unquoted string 53 } else { 54 int parameterStart = pos; 55 pos = skipUntil(value, pos, ","); 56 parameter = value.substring(parameterStart, pos).trim(); 57 } 58 59 handler.handle(directive, parameter); 60 } 61 } 62 63 /** 64 * Returns the next index in {@code input} at or after {@code pos} that 65 * contains a character from {@code characters}. Returns the input length if 66 * none of the requested characters can be found. 67 */ 68 public static int skipUntil(String input, int pos, String characters) { 69 for (; pos < input.length(); pos++) { 70 if (characters.indexOf(input.charAt(pos)) != -1) { 71 break; 72 } 73 } 74 return pos; 75 } 76 77 /** 78 * Returns the next non-whitespace character in {@code input} that is white 79 * space. Result is undefined if input contains newline characters. 80 */ 81 public static int skipWhitespace(String input, int pos) { 82 for (; pos < input.length(); pos++) { 83 char c = input.charAt(pos); 84 if (c != ' ' && c != '\t') { 85 break; 86 } 87 } 88 return pos; 89 } 90 91 /** 92 * Returns {@code value} as a positive integer, or 0 if it is negative, or 93 * -1 if it cannot be parsed. 94 */ 95 public static int parseSeconds(String value) { 96 try { 97 long seconds = Long.parseLong(value); 98 if (seconds > Integer.MAX_VALUE) { 99 return Integer.MAX_VALUE; 100 } else if (seconds < 0) { 101 return 0; 102 } else { 103 return (int) seconds; 104 } 105 } catch (NumberFormatException e) { 106 return -1; 107 } 108 } 109 110 private HeaderParser() { 111 } 112 } 113