- Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathencoding_prefs.c
More file actions
Latest commit
145 lines (126 loc) · 3.15 KB
/
Copy pathencoding_prefs.c
File metadata and controls
145 lines (126 loc) · 3.15 KB
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#include"encoding_prefs.h"
#include"util.h"
#include<assert.h>
#include<ctype.h>
#include<string.h>
voidinit_encoding_prefs(encoding_prefs_t*ep) {
assert(ep);
ep->gzip=-1;
ep->identity=-1;
ep->catch_all=-1;
}
//reads the decimal portion of a qvalue
//Decimal portion is optional.
//If present it has form '.' followed by 1-3 digits
//returns 1000*decimal value
staticintread_decimal_part(constchar*str) {
inti, decimal, digit_power;
//no decimal part => 0 for decimal value
if(str[0] =='\0') {
return0;
}
//no digit for decimal value => invalid
if(str[0] !='.') {
return-1;
}
decimal=0;
digit_power=1000;
str+=1;
//read up to 3 decimal digits
for(i=0; i<3; ++i) {
//end of digits
if(!str[i]) {
//check that there actually were digits after decimal
if(i==0) {
return-1;
}
returndecimal*digit_power;
}
//not actually a digit string
if(!isdigit(str[i])) {
return-1;
}
decimal=10*decimal+ (int)(str[i] -'0');
digit_power /= 10;
}
//no characters allowed after first 3 digits
if(str[i] !='\0') {
return-1;
}
returndecimal;
}
//qvalue = ( "0" [ "." *3DIGIT ] ) / ( "1" [ "." *3"0" ] )
//parses qvalue and returns 1000*qvalue (so value will be integer)
//returns -1 on invalid value
intparse_qvalue(constchar*qstr) {
assert(qstr);
switch(qstr[0]) {
case'1':
if(read_decimal_part(qstr+1) !=0) {
return-1;
} else {
return1000;
}
break;
case'0':
returnread_decimal_part(qstr+1);
break;
}
return-1;
}
//takes pointer to the ";" part of a weight string and returns
//1000*qvalue or -1 if string is invalid
intparse_weight(constchar*wstr) {
assert(wstr);
assert(wstr[0] ==';');
++wstr;
//skip leading whitespace
while(*wstr==' '||*wstr=='\t') ++wstr;
//check for "q="
if(wstr[0] !='q'||wstr[1] !='=') return-1;
//get qvalue
returnparse_qvalue(wstr+2);
}
staticinthandle_coding_entry(char*entry, void*arg) {
assert(entry);
assert(arg);
inti, weight;
encoding_prefs_t*prefs= (encoding_prefs_t*)arg;
//check for weight
i=find_first(entry, ';');
//determine encoding weigth
if(i!=-1) {
weight=parse_weight(entry+i);
//invalid weigth
if(weight<0) return-1;
//remove whitespace between coding and weight
entry[i] ='\0';
remove_trailing_whitespace(entry, (size_t)i);
} else {
//default is 1
weight=1000;
}
//check for known codings
if(!strcmp(entry, "gzip")) {
prefs->gzip=weight;
} elseif(!strcmp(entry, "identity")) {
prefs->identity=weight;
} elseif(!strcmp(entry, "*")) {
prefs->catch_all=weight;
}
return0;
}
//weight = OWS ";" OWS "q=" qvalue (default weigth is 1)
//Accept-Encoding = #( codings [ weight ] )
//Accept-Encoding = [ ( "," / ( codings [ weight ] ) ) *( OWS "," [ OWS
// ( codings [ weight ] ) ] ) ]
//codings = content-coding / "identity" / "*"
//content-coding = token
intparse_accepted_encodings(encoding_prefs_t*result, char*header_str) {
assert(result);
assert(header_str);
//initialize result
init_encoding_prefs(result);
//parse each entry in comman seperated list
returnparse_list(header_str, handle_coding_entry, (void*)result);
}