1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 package org.apache.hc.core5.http.message;
29
30 import java.util.ArrayList;
31 import java.util.BitSet;
32 import java.util.List;
33
34 import org.apache.hc.core5.annotation.Contract;
35 import org.apache.hc.core5.annotation.ThreadingBehavior;
36 import org.apache.hc.core5.http.HeaderElement;
37 import org.apache.hc.core5.http.NameValuePair;
38 import org.apache.hc.core5.util.Args;
39 import org.apache.hc.core5.util.Tokenizer;
40
41
42
43
44
45
46 @Contract(threading = ThreadingBehavior.IMMUTABLE)
47 public class BasicHeaderValueParser implements HeaderValueParser {
48
49 public final static BasicHeaderValueParser INSTANCE = new BasicHeaderValueParser();
50
51 private final static char PARAM_DELIMITER = ';';
52 private final static char ELEM_DELIMITER = ',';
53
54
55
56 private static final BitSet TOKEN_DELIMITER = Tokenizer.INIT_BITSET('=', PARAM_DELIMITER, ELEM_DELIMITER);
57 private static final BitSet VALUE_DELIMITER = Tokenizer.INIT_BITSET(PARAM_DELIMITER, ELEM_DELIMITER);
58
59 private final Tokenizer tokenizer;
60
61 public BasicHeaderValueParser() {
62 this.tokenizer = Tokenizer.INSTANCE;
63 }
64
65
66
67
68 private static final HeaderElement[] EMPTY_HEADER_ELEMENT_ARRAY = {};
69
70
71
72
73 private static final NameValuePair[] EMPTY_NAME_VALUE_ARRAY = {};
74
75 @Override
76 public HeaderElement[] parseElements(final CharSequence buffer, final ParserCursor cursor) {
77 Args.notNull(buffer, "Char sequence");
78 Args.notNull(cursor, "Parser cursor");
79 final List<HeaderElement> elements = new ArrayList<>();
80 while (!cursor.atEnd()) {
81 final HeaderElement element = parseHeaderElement(buffer, cursor);
82 if (!(element.getName().isEmpty() && element.getValue() == null)) {
83 elements.add(element);
84 }
85 }
86 return elements.toArray(EMPTY_HEADER_ELEMENT_ARRAY);
87 }
88
89 @Override
90 public HeaderElement parseHeaderElement(final CharSequence buffer, final ParserCursor cursor) {
91 Args.notNull(buffer, "Char sequence");
92 Args.notNull(cursor, "Parser cursor");
93 final NameValuePair nvp = parseNameValuePair(buffer, cursor);
94 NameValuePair[] params = null;
95 if (!cursor.atEnd()) {
96 final char ch = buffer.charAt(cursor.getPos());
97 if (ch == PARAM_DELIMITER || ch == ELEM_DELIMITER) {
98 cursor.updatePos(cursor.getPos() + 1);
99 }
100 if (ch != ELEM_DELIMITER) {
101 params = parseParameters(buffer, cursor);
102 }
103 }
104 return new BasicHeaderElement(nvp.getName(), nvp.getValue(), params);
105 }
106
107 @Override
108 public NameValuePair[] parseParameters(final CharSequence buffer, final ParserCursor cursor) {
109 Args.notNull(buffer, "Char sequence");
110 Args.notNull(cursor, "Parser cursor");
111 tokenizer.skipWhiteSpace(buffer, cursor);
112 final List<NameValuePair> params = new ArrayList<>();
113 while (!cursor.atEnd()) {
114 final NameValuePair param = parseNameValuePair(buffer, cursor);
115 params.add(param);
116 if (!cursor.atEnd()) {
117 final char ch = buffer.charAt(cursor.getPos());
118 if (ch == PARAM_DELIMITER) {
119 cursor.updatePos(cursor.getPos() + 1);
120 }
121 if (ch == ELEM_DELIMITER) {
122 break;
123 }
124 }
125 }
126 return params.toArray(EMPTY_NAME_VALUE_ARRAY);
127 }
128
129 @Override
130 public NameValuePair parseNameValuePair(final CharSequence buffer, final ParserCursor cursor) {
131 Args.notNull(buffer, "Char sequence");
132 Args.notNull(cursor, "Parser cursor");
133
134 final String name = tokenizer.parseToken(buffer, cursor, TOKEN_DELIMITER);
135 if (cursor.atEnd()) {
136 return new BasicNameValuePair(name, null);
137 }
138 final char delim = buffer.charAt(cursor.getPos());
139 if (delim != '=') {
140 return new BasicNameValuePair(name, null);
141 }
142 cursor.updatePos(cursor.getPos() + 1);
143 final String value = tokenizer.parseValue(buffer, cursor, VALUE_DELIMITER);
144 return new BasicNameValuePair(name, value);
145 }
146
147 }
148