]> git.saurik.com Git - apple/security.git/blob - cdsa/cdsa_utilities/headermap.cpp
Security-54.1.tar.gz
[apple/security.git] / cdsa / cdsa_utilities / headermap.cpp
1 /*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
8 * using this file.
9 *
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
16 */
17
18
19 //
20 // headermap - represent Internet-standard headers
21 //
22 #include "headermap.h"
23 #include <ctype.h>
24
25 using namespace std;
26
27 namespace Security {
28
29
30 //
31 // Given a constant text string, extract the leading substring up to 'end' (or \0),
32 // canonicalize its case, and store the result for use.
33 //
34 HeaderMap::CanonicalKey::CanonicalKey(const char *key, char end)
35 {
36 assert(key && key[0]); // non-empty
37 mValue[0] = toupper(key[0]);
38 for (unsigned int n = 1; n < sizeof(mValue) - 1; n++) {
39 if (key[n] == end) {
40 mValue[n] = '\0';
41 return;
42 }
43 mValue[n] = tolower(key[n]);
44 }
45 // overflow -- truncate? throw? dynamic allocation? seppuko? :-)
46 assert(false);
47 }
48
49
50 //
51 // Add an entry
52 //
53 void HeaderMap::add(const char *key, const char *value)
54 {
55 add(CanonicalKey(key), value);
56 }
57
58
59 //
60 // Given a standard form (Key: value), add its value to the headermap
61 //
62 void HeaderMap::add(const char *form)
63 {
64 while (*form && isspace(*form))
65 form++;
66 if (const char *colon = strchr(form, ':')) {
67 CanonicalKey key(form, ':');
68 const char *value = colon + 1;
69 while (*value && isspace(*value))
70 value++;
71 add(key, value);
72 } else {
73 // ignore this
74 //@@@ signal an error? how? how bad?
75 }
76 }
77
78
79 //
80 // Internal add method, given a canonicalized key
81 //
82 void HeaderMap::add(const CanonicalKey &key, const char *value)
83 {
84 Map::iterator it = mMap.find(key);
85 if (it == mMap.end())
86 mMap[key] = value;
87 else
88 merge(key, mMap[key], value);
89 }
90
91
92 //
93 // Locate an entry in a headermap.
94 // Find returns NULL if not found; [] creates a new entry if needed and returns
95 // a reference to the value, in good STL tradition.
96 //
97 const char *HeaderMap::find(const char *key, const char *defaultValue) const
98 {
99 Map::const_iterator it = mMap.find(CanonicalKey(key));
100 return (it == mMap.end()) ? defaultValue : it->second.c_str();
101 }
102
103 string &HeaderMap::operator[] (const char *key)
104 {
105 return mMap[CanonicalKey(key)];
106 }
107
108
109 //
110 // The default implementation of merge throws out the old contents and replaces
111 // them with the new.
112 //
113 void HeaderMap::merge(string key, string &old, string newValue)
114 {
115 old = newValue;
116 }
117
118
119 //
120 // Collect the entire contents into a single string
121 // Note that this is NOT exactly what was passed in; certain canonicalizations have
122 // been done; fields are reordered; and duplicate-header fields have been coalesced.
123 //@@@ size could be pre-calculated (running counter).
124 //
125 string HeaderMap::collect(const char *lineEnding) const
126 {
127 string value;
128 for (Map::const_iterator it = mMap.begin(); it != mMap.end(); it++)
129 value += it->first + ": " + it->second + lineEnding;
130 return value;
131 }
132
133 size_t HeaderMap::collectLength(const char *lineEnding) const
134 {
135 size_t size = 0;
136 size_t sepLength = strlen(lineEnding);
137 for (Map::const_iterator it = mMap.begin(); it != mMap.end(); it++)
138 size += it->first.length() + 2 + it->second.length() + sepLength;
139 return size;
140 }
141
142
143 } // end namespace Security