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() - 1);
97 if (ch != ELEM_DELIMITER) {
98 params = parseParameters(buffer, cursor);
99 }
100 }
101 return new BasicHeaderElement(nvp.getName(), nvp.getValue(), params);
102 }
103
104 @Override
105 public NameValuePair[] parseParameters(final CharSequence buffer, final ParserCursor cursor) {
106 Args.notNull(buffer, "Char sequence");
107 Args.notNull(cursor, "Parser cursor");
108 tokenizer.skipWhiteSpace(buffer, cursor);
109 final List<NameValuePair> params = new ArrayList<>();
110 while (!cursor.atEnd()) {
111 final NameValuePair param = parseNameValuePair(buffer, cursor);
112 params.add(param);
113 final char ch = buffer.charAt(cursor.getPos() - 1);
114 if (ch == ELEM_DELIMITER) {
115 break;
116 }
117 }
118 return params.toArray(EMPTY_NAME_VALUE_ARRAY);
119 }
120
121 @Override
122 public NameValuePair parseNameValuePair(final CharSequence buffer, final ParserCursor cursor) {
123 Args.notNull(buffer, "Char sequence");
124 Args.notNull(cursor, "Parser cursor");
125
126 final String name = tokenizer.parseToken(buffer, cursor, TOKEN_DELIMITER);
127 if (cursor.atEnd()) {
128 return new BasicNameValuePair(name, null);
129 }
130 final int delim = buffer.charAt(cursor.getPos());
131 cursor.updatePos(cursor.getPos() + 1);
132 if (delim != '=') {
133 return new BasicNameValuePair(name, null);
134 }
135 final String value = tokenizer.parseValue(buffer, cursor, VALUE_DELIMITER);
136 if (!cursor.atEnd()) {
137 cursor.updatePos(cursor.getPos() + 1);
138 }
139 return new BasicNameValuePair(name, value);
140 }
141
142 }
143