Roll ICU to r205936
[chromium-blink-merge.git] / net / base / gzip_header.cc
blob81cb1d8efd32bef6add0e2f531c2c1f5206373e7
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/base/gzip_header.h"
7 #include "base/logging.h"
8 #include "third_party/zlib/zlib.h"
10 namespace net {
12 const uint8 GZipHeader::magic[] = { 0x1f, 0x8b };
14 GZipHeader::GZipHeader() {
15 Reset();
18 GZipHeader::~GZipHeader() {
21 void GZipHeader::Reset() {
22 state_ = IN_HEADER_ID1;
23 flags_ = 0;
24 extra_length_ = 0;
27 GZipHeader::Status GZipHeader::ReadMore(const char* inbuf, int inbuf_len,
28 const char** header_end) {
29 DCHECK_GE(inbuf_len, 0);
30 const uint8* pos = reinterpret_cast<const uint8*>(inbuf);
31 const uint8* const end = pos + inbuf_len;
33 while ( pos < end ) {
34 switch ( state_ ) {
35 case IN_HEADER_ID1:
36 if ( *pos != magic[0] ) return INVALID_HEADER;
37 pos++;
38 state_++;
39 break;
40 case IN_HEADER_ID2:
41 if ( *pos != magic[1] ) return INVALID_HEADER;
42 pos++;
43 state_++;
44 break;
45 case IN_HEADER_CM:
46 if ( *pos != Z_DEFLATED ) return INVALID_HEADER;
47 pos++;
48 state_++;
49 break;
50 case IN_HEADER_FLG:
51 flags_ = (*pos) & (FLAG_FHCRC | FLAG_FEXTRA |
52 FLAG_FNAME | FLAG_FCOMMENT);
53 pos++;
54 state_++;
55 break;
57 case IN_HEADER_MTIME_BYTE_0:
58 pos++;
59 state_++;
60 break;
61 case IN_HEADER_MTIME_BYTE_1:
62 pos++;
63 state_++;
64 break;
65 case IN_HEADER_MTIME_BYTE_2:
66 pos++;
67 state_++;
68 break;
69 case IN_HEADER_MTIME_BYTE_3:
70 pos++;
71 state_++;
72 break;
74 case IN_HEADER_XFL:
75 pos++;
76 state_++;
77 break;
79 case IN_HEADER_OS:
80 pos++;
81 state_++;
82 break;
84 case IN_XLEN_BYTE_0:
85 if ( !(flags_ & FLAG_FEXTRA) ) {
86 state_ = IN_FNAME;
87 break;
89 // We have a two-byte little-endian length, followed by a
90 // field of that length.
91 extra_length_ = *pos;
92 pos++;
93 state_++;
94 break;
95 case IN_XLEN_BYTE_1:
96 extra_length_ += *pos << 8;
97 pos++;
98 state_++;
99 // We intentionally fall through, because if we have a
100 // zero-length FEXTRA, we want to check to notice that we're
101 // done reading the FEXTRA before we exit this loop...
103 case IN_FEXTRA: {
104 // Grab the rest of the bytes in the extra field, or as many
105 // of them as are actually present so far.
106 const int num_extra_bytes = static_cast<const int>(std::min(
107 static_cast<ptrdiff_t>(extra_length_),
108 (end - pos)));
109 pos += num_extra_bytes;
110 extra_length_ -= num_extra_bytes;
111 if ( extra_length_ == 0 ) {
112 state_ = IN_FNAME; // advance when we've seen extra_length_ bytes
113 flags_ &= ~FLAG_FEXTRA; // we're done with the FEXTRA stuff
115 break;
118 case IN_FNAME:
119 if ( !(flags_ & FLAG_FNAME) ) {
120 state_ = IN_FCOMMENT;
121 break;
123 // See if we can find the end of the \0-terminated FNAME field.
124 pos = reinterpret_cast<const uint8*>(memchr(pos, '\0', (end - pos)));
125 if ( pos != NULL ) {
126 pos++; // advance past the '\0'
127 flags_ &= ~FLAG_FNAME; // we're done with the FNAME stuff
128 state_ = IN_FCOMMENT;
129 } else {
130 pos = end; // everything we have so far is part of the FNAME
132 break;
134 case IN_FCOMMENT:
135 if ( !(flags_ & FLAG_FCOMMENT) ) {
136 state_ = IN_FHCRC_BYTE_0;
137 break;
139 // See if we can find the end of the \0-terminated FCOMMENT field.
140 pos = reinterpret_cast<const uint8*>(memchr(pos, '\0', (end - pos)));
141 if ( pos != NULL ) {
142 pos++; // advance past the '\0'
143 flags_ &= ~FLAG_FCOMMENT; // we're done with the FCOMMENT stuff
144 state_ = IN_FHCRC_BYTE_0;
145 } else {
146 pos = end; // everything we have so far is part of the FNAME
148 break;
150 case IN_FHCRC_BYTE_0:
151 if ( !(flags_ & FLAG_FHCRC) ) {
152 state_ = IN_DONE;
153 break;
155 pos++;
156 state_++;
157 break;
159 case IN_FHCRC_BYTE_1:
160 pos++;
161 flags_ &= ~FLAG_FHCRC; // we're done with the FHCRC stuff
162 state_++;
163 break;
165 case IN_DONE:
166 *header_end = reinterpret_cast<const char*>(pos);
167 return COMPLETE_HEADER;
171 if ( (state_ > IN_HEADER_OS) && (flags_ == 0) ) {
172 *header_end = reinterpret_cast<const char*>(pos);
173 return COMPLETE_HEADER;
174 } else {
175 return INCOMPLETE_HEADER;
179 } // namespace net