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
146
147
|
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef NET_SPDY_SPDY_HEADER_BLOCK_H_
#define NET_SPDY_SPDY_HEADER_BLOCK_H_
#include <stddef.h>
#include <map>
#include <memory>
#include <string>
#include "base/memory/scoped_ptr.h"
#include "base/strings/string_piece.h"
#include "net/base/linked_hash_map.h"
#include "net/base/net_export.h"
#include "net/log/net_log.h"
namespace net {
// Allows arg-dependent lookup to work for logging's operator<<.
using ::operator<<;
// This class provides a key-value map that can be used to store SPDY header
// names and values. This data structure preserves insertion order.
//
// Under the hood, this data structure uses large, contiguous blocks of memory
// to store names and values. Lookups may be performed with StringPiece keys,
// and values are returned as StringPieces (via StringPieceProxy, below).
// Value StringPieces are valid as long as the SpdyHeaderBlock exists; allocated
// memory is never freed until SpdyHeaderBlock's destruction.
//
// This implementation does not make much of an effort to minimize wasted space.
// It's expected that keys are rarely deleted from a SpdyHeaderBlock.
class NET_EXPORT SpdyHeaderBlock {
private:
using MapType = linked_hash_map<base::StringPiece,
base::StringPiece,
base::StringPieceHash>;
class Storage;
public:
using iterator = MapType::iterator;
using const_iterator = MapType::const_iterator;
using value_type = MapType::value_type;
using reverse_iterator = MapType::reverse_iterator;
class StringPieceProxy;
SpdyHeaderBlock();
SpdyHeaderBlock(const SpdyHeaderBlock& other);
~SpdyHeaderBlock();
SpdyHeaderBlock& operator=(const SpdyHeaderBlock& other);
bool operator==(const SpdyHeaderBlock& other) const;
bool operator!=(const SpdyHeaderBlock& other) const;
// Provides a human readable multi-line representation of the stored header
// keys and values.
std::string DebugString() const;
// These methods delegate to our MapType member.
iterator begin() { return block_.begin(); }
iterator end() { return block_.end(); }
const_iterator begin() const { return block_.begin(); }
const_iterator end() const { return block_.end(); }
bool empty() const { return block_.empty(); }
size_t size() const { return block_.size(); }
iterator find(base::StringPiece key) { return block_.find(key); }
const_iterator find(base::StringPiece key) const { return block_.find(key); }
reverse_iterator rbegin() { return block_.rbegin(); }
void erase(base::StringPiece key) { block_.erase(key); }
// Clears both our MapType member and the memory used to hold headers.
void clear();
// These methods copy data into our backing storage.
void insert(const MapType::value_type& value);
void ReplaceOrAppendHeader(const base::StringPiece key,
const base::StringPiece value);
// Allows either lookup or mutation of the value associated with a key.
StringPieceProxy operator[](const base::StringPiece key);
// This object provides automatic conversions that allow SpdyHeaderBlock to be
// nearly a drop-in replacement for linked_hash_map<string, string>. It reads
// data from or writes data to a SpdyHeaderBlock::Storage.
class NET_EXPORT StringPieceProxy {
public:
~StringPieceProxy();
StringPieceProxy(const StringPieceProxy& other);
// Assignment modifies the underlying SpdyHeaderBlock.
StringPieceProxy& operator=(const base::StringPiece other);
// Allows a StringPieceProxy to be automatically converted to a StringPiece.
// This makes SpdyHeaderBlock::operator[] easy to use with StringPieces.
operator base::StringPiece() const;
// Reserves |size| bytes in the underlying storage.
void reserve(size_t size);
std::string as_string() const {
return static_cast<base::StringPiece>(*this).as_string();
}
private:
friend class SpdyHeaderBlock;
StringPieceProxy(SpdyHeaderBlock::MapType* block,
SpdyHeaderBlock::Storage* storage,
SpdyHeaderBlock::MapType::iterator lookup_result,
const base::StringPiece key);
SpdyHeaderBlock::MapType* block_;
SpdyHeaderBlock::Storage* storage_;
SpdyHeaderBlock::MapType::iterator lookup_result_;
const base::StringPiece key_;
// Contains only POD members; explicitly copyable.
};
private:
void Write(const base::StringPiece s);
void AppendHeader(const base::StringPiece key, const base::StringPiece value);
MapType block_;
scoped_ptr<Storage> storage_;
};
// Converts a SpdyHeaderBlock into NetLog event parameters.
NET_EXPORT scoped_ptr<base::Value> SpdyHeaderBlockNetLogCallback(
const SpdyHeaderBlock* headers,
NetLogCaptureMode capture_mode);
// Converts NetLog event parameters into a SPDY header block and writes them
// to |headers|. |event_param| must have been created by
// SpdyHeaderBlockNetLogCallback. On failure, returns false and clears
// |headers|.
NET_EXPORT bool SpdyHeaderBlockFromNetLogParam(
const base::Value* event_param,
SpdyHeaderBlock* headers);
} // namespace net
#endif // NET_SPDY_SPDY_HEADER_BLOCK_H_
|