Hi,
  the hard part is IMO done, should be enough for a first round of review;
I've left the TODO list I discussed with Amos on IRC in to keep track of
what's been done. There are two things left that I can think of: getting
rid of the masks (ListHeadersMask etc) in favor of bools or bitfields in
the headersTable (I'd go for bools for speed, I believe we can afford to
waste 100-ish bytes per flag), and possibly switching some enums  to c++11
strongly-typed enums (enum class foo) in some places.

Code has been casually run-tested, seems to be OK.

On Thu, Jul 30, 2015 at 9:44 PM, Kinkie <gkin...@gmail.com> wrote:

>
>
> On Thu, Jul 30, 2015 at 6:42 PM, Alex Rousskov <
> rouss...@measurement-factory.com> wrote:
>
>> On 07/30/2015 01:44 AM, Kinkie wrote:
>>
>> > headerDescription: a std::vector keyed by header ID containing header
>> type
>>
>> HeaderDescriptions (plural) then.
>>
>
> Ok, will change.
>
>
>> > template <typename EnumType>
>> > typedef struct LookupTableRecord
>> > {
>> >    const char *name;
>> >    EnumType id;
>> > }
>>
>> Please avoid "struct" whenever possible. Typing "public:" once is better
>> that always remembering whether to search for and forward-declare a
>> "struct Foo" or a "class Foo".
>>
>
> Sure.
>
>
>> > template<typename Enumtype, typename RecordType =
>> > LookupTableRecord<EnumType> >
>> > class LookupTable
>> > {
>> >    //...
>> > }
>> >
>> > This would make it so that someone could define a custom Record type,
>> > and as long as that record type matches the signature of
>> > LookupTableRecord, LookupTable won't care.
>>
>> Do not add that template parameter until you actually need to customize
>> the record type. If you end up using this design, just typedef Record to
>> be LookupTableRecord.
>>
>
> Need is already present; it's done exactly as you say.
> Thanks!
>
> --
>     Francesco
>



-- 
    Francesco
# Bazaar merge directive format 2 (Bazaar 0.90)
# revision_id: kin...@squid-cache.org-20150731193737-firdyshwvzs546v7
# target_branch: ../trunk
# testament_sha1: 2d0c92ab3a9b65da79ba165993fa47a61b13a869
# timestamp: 2015-07-31 21:38:29 +0200
# base_revision_id: squ...@treenet.co.nz-20150731062638-\
#   7524t81yy3nyarog
# 
# Begin patch
=== modified file 'src/HttpHeader.cc'
--- src/HttpHeader.cc	2015-03-04 16:02:53 +0000
+++ src/HttpHeader.cc	2015-07-31 15:05:22 +0000
@@ -9,6 +9,7 @@
 /* DEBUG: section 55    HTTP Header */
 
 #include "squid.h"
+#include "base/LookupTable.h"
 #include "base64.h"
 #include "globals.h"
 #include "HttpHdrCc.h"
@@ -59,114 +60,20 @@
  * local constants and vars
  */
 
-/*
- * A table with major attributes for every known field.
- * We calculate name lengths and reorganize this array on start up.
- * After reorganization, field id can be used as an index to the table.
+/* TODO:
+ * DONE 1. shift HDR_BAD_HDR to end of enum
+ * DONE 2. shift headers data array to http/RegistredHeaders.cc
+ * DONE 3. creatign LookupTable object from teh enum and array
+ * (with HDR_BAD_HDR as invalid value)
+ * DONE 4. replacing httpHeaderIdByName() uses with the lookup table
+ * 5. merge HDR_BAD_HDR and HDR_ENUM_END into one thing
+ * DONE 6. replacing httpHeaderNameById with direct array lookups
+ * 7. being looking at the other arrays removal
  */
-static const HttpHeaderFieldAttrs HeadersAttrs[] = {
-    HttpHeaderFieldAttrs("Accept", HDR_ACCEPT, ftStr),
-
-    HttpHeaderFieldAttrs("Accept-Charset", HDR_ACCEPT_CHARSET, ftStr),
-    HttpHeaderFieldAttrs("Accept-Encoding", HDR_ACCEPT_ENCODING, ftStr),
-    HttpHeaderFieldAttrs("Accept-Language", HDR_ACCEPT_LANGUAGE, ftStr),
-    HttpHeaderFieldAttrs("Accept-Ranges", HDR_ACCEPT_RANGES, ftStr),
-    HttpHeaderFieldAttrs("Age", HDR_AGE, ftInt),
-    HttpHeaderFieldAttrs("Allow", HDR_ALLOW, ftStr),
-    HttpHeaderFieldAttrs("Alternate-Protocol", HDR_ALTERNATE_PROTOCOL, ftStr),
-    HttpHeaderFieldAttrs("Authorization", HDR_AUTHORIZATION, ftStr),    /* for now */
-    HttpHeaderFieldAttrs("Cache-Control", HDR_CACHE_CONTROL, ftPCc),
-    HttpHeaderFieldAttrs("Connection", HDR_CONNECTION, ftStr),
-    HttpHeaderFieldAttrs("Content-Base", HDR_CONTENT_BASE, ftStr),
-    HttpHeaderFieldAttrs("Content-Disposition", HDR_CONTENT_DISPOSITION, ftStr),  /* for now */
-    HttpHeaderFieldAttrs("Content-Encoding", HDR_CONTENT_ENCODING, ftStr),
-    HttpHeaderFieldAttrs("Content-Language", HDR_CONTENT_LANGUAGE, ftStr),
-    HttpHeaderFieldAttrs("Content-Length", HDR_CONTENT_LENGTH, ftInt64),
-    HttpHeaderFieldAttrs("Content-Location", HDR_CONTENT_LOCATION, ftStr),
-    HttpHeaderFieldAttrs("Content-MD5", HDR_CONTENT_MD5, ftStr),    /* for now */
-    HttpHeaderFieldAttrs("Content-Range", HDR_CONTENT_RANGE, ftPContRange),
-    HttpHeaderFieldAttrs("Content-Type", HDR_CONTENT_TYPE, ftStr),
-    HttpHeaderFieldAttrs("Cookie", HDR_COOKIE, ftStr),
-    HttpHeaderFieldAttrs("Cookie2", HDR_COOKIE2, ftStr),
-    HttpHeaderFieldAttrs("Date", HDR_DATE, ftDate_1123),
-    HttpHeaderFieldAttrs("ETag", HDR_ETAG, ftETag),
-    HttpHeaderFieldAttrs("Expect", HDR_EXPECT, ftStr),
-    HttpHeaderFieldAttrs("Expires", HDR_EXPIRES, ftDate_1123),
-    HttpHeaderFieldAttrs("Forwarded", HDR_FORWARDED, ftStr),
-    HttpHeaderFieldAttrs("From", HDR_FROM, ftStr),
-    HttpHeaderFieldAttrs("Host", HDR_HOST, ftStr),
-    HttpHeaderFieldAttrs("HTTP2-Settings", HDR_HTTP2_SETTINGS, ftStr), /* for now */
-    HttpHeaderFieldAttrs("If-Match", HDR_IF_MATCH, ftStr),  /* for now */
-    HttpHeaderFieldAttrs("If-Modified-Since", HDR_IF_MODIFIED_SINCE, ftDate_1123),
-    HttpHeaderFieldAttrs("If-None-Match", HDR_IF_NONE_MATCH, ftStr),    /* for now */
-    HttpHeaderFieldAttrs("If-Range", HDR_IF_RANGE, ftDate_1123_or_ETag),
-    HttpHeaderFieldAttrs("If-Unmodified-Since", HDR_IF_UNMODIFIED_SINCE, ftDate_1123),
-    HttpHeaderFieldAttrs("Keep-Alive", HDR_KEEP_ALIVE, ftStr),
-    HttpHeaderFieldAttrs("Key", HDR_KEY, ftStr),
-    HttpHeaderFieldAttrs("Last-Modified", HDR_LAST_MODIFIED, ftDate_1123),
-    HttpHeaderFieldAttrs("Link", HDR_LINK, ftStr),
-    HttpHeaderFieldAttrs("Location", HDR_LOCATION, ftStr),
-    HttpHeaderFieldAttrs("Max-Forwards", HDR_MAX_FORWARDS, ftInt64),
-    HttpHeaderFieldAttrs("Mime-Version", HDR_MIME_VERSION, ftStr),  /* for now */
-    HttpHeaderFieldAttrs("Negotiate", HDR_NEGOTIATE, ftStr),
-    HttpHeaderFieldAttrs("Origin", HDR_ORIGIN, ftStr),
-    HttpHeaderFieldAttrs("Pragma", HDR_PRAGMA, ftStr),
-    HttpHeaderFieldAttrs("Proxy-Authenticate", HDR_PROXY_AUTHENTICATE, ftStr),
-    HttpHeaderFieldAttrs("Proxy-Authentication-Info", HDR_PROXY_AUTHENTICATION_INFO, ftStr),
-    HttpHeaderFieldAttrs("Proxy-Authorization", HDR_PROXY_AUTHORIZATION, ftStr),
-    HttpHeaderFieldAttrs("Proxy-Connection", HDR_PROXY_CONNECTION, ftStr),
-    HttpHeaderFieldAttrs("Proxy-support", HDR_PROXY_SUPPORT, ftStr),
-    HttpHeaderFieldAttrs("Public", HDR_PUBLIC, ftStr),
-    HttpHeaderFieldAttrs("Range", HDR_RANGE, ftPRange),
-    HttpHeaderFieldAttrs("Referer", HDR_REFERER, ftStr),
-    HttpHeaderFieldAttrs("Request-Range", HDR_REQUEST_RANGE, ftPRange), /* usually matches HDR_RANGE */
-    HttpHeaderFieldAttrs("Retry-After", HDR_RETRY_AFTER, ftStr),    /* for now (ftDate_1123 or ftInt!) */
-    HttpHeaderFieldAttrs("Server", HDR_SERVER, ftStr),
-    HttpHeaderFieldAttrs("Set-Cookie", HDR_SET_COOKIE, ftStr),
-    HttpHeaderFieldAttrs("Set-Cookie2", HDR_SET_COOKIE2, ftStr),
-    HttpHeaderFieldAttrs("TE", HDR_TE, ftStr),
-    HttpHeaderFieldAttrs("Title", HDR_TITLE, ftStr),
-    HttpHeaderFieldAttrs("Trailer", HDR_TRAILER, ftStr),
-    HttpHeaderFieldAttrs("Transfer-Encoding", HDR_TRANSFER_ENCODING, ftStr),
-    HttpHeaderFieldAttrs("Translate", HDR_TRANSLATE, ftStr),    /* for now. may need to crop */
-    HttpHeaderFieldAttrs("Unless-Modified-Since", HDR_UNLESS_MODIFIED_SINCE, ftStr),  /* for now ignore. may need to crop */
-    HttpHeaderFieldAttrs("Upgrade", HDR_UPGRADE, ftStr),    /* for now */
-    HttpHeaderFieldAttrs("User-Agent", HDR_USER_AGENT, ftStr),
-    HttpHeaderFieldAttrs("Vary", HDR_VARY, ftStr),  /* for now */
-    HttpHeaderFieldAttrs("Via", HDR_VIA, ftStr),    /* for now */
-    HttpHeaderFieldAttrs("Warning", HDR_WARNING, ftStr),    /* for now */
-    HttpHeaderFieldAttrs("WWW-Authenticate", HDR_WWW_AUTHENTICATE, ftStr),
-    HttpHeaderFieldAttrs("Authentication-Info", HDR_AUTHENTICATION_INFO, ftStr),
-    HttpHeaderFieldAttrs("X-Cache", HDR_X_CACHE, ftStr),
-    HttpHeaderFieldAttrs("X-Cache-Lookup", HDR_X_CACHE_LOOKUP, ftStr),
-    HttpHeaderFieldAttrs("X-Forwarded-For", HDR_X_FORWARDED_FOR, ftStr),
-    HttpHeaderFieldAttrs("X-Request-URI", HDR_X_REQUEST_URI, ftStr),
-    HttpHeaderFieldAttrs("X-Squid-Error", HDR_X_SQUID_ERROR, ftStr),
-#if X_ACCELERATOR_VARY
-    HttpHeaderFieldAttrs("X-Accelerator-Vary", HDR_X_ACCELERATOR_VARY, ftStr),
-#endif
-#if USE_ADAPTATION
-    HttpHeaderFieldAttrs("X-Next-Services", HDR_X_NEXT_SERVICES, ftStr),
-#endif
-    HttpHeaderFieldAttrs("Surrogate-Capability", HDR_SURROGATE_CAPABILITY, ftStr),
-    HttpHeaderFieldAttrs("Surrogate-Control", HDR_SURROGATE_CONTROL, ftPSc),
-    HttpHeaderFieldAttrs("Front-End-Https", HDR_FRONT_END_HTTPS, ftStr),
-    HttpHeaderFieldAttrs("FTP-Command", HDR_FTP_COMMAND, ftStr),
-    HttpHeaderFieldAttrs("FTP-Arguments", HDR_FTP_ARGUMENTS, ftStr),
-    HttpHeaderFieldAttrs("FTP-Pre", HDR_FTP_PRE, ftStr),
-    HttpHeaderFieldAttrs("FTP-Status", HDR_FTP_STATUS, ftInt),
-    HttpHeaderFieldAttrs("FTP-Reason", HDR_FTP_REASON, ftStr),
-    HttpHeaderFieldAttrs("Other:", HDR_OTHER, ftStr)    /* ':' will not allow matches */
-};
-
-static HttpHeaderFieldInfo *Headers = NULL;
-
-http_hdr_type &operator++ (http_hdr_type &aHeader)
-{
-    int tmp = (int)aHeader;
-    aHeader = (http_hdr_type)(++tmp);
-    return aHeader;
-}
+
+
+LookupTable<http_hdr_type, HeaderTableRecord> headerLookupTable(HDR_BAD_HDR, headerTable);
+std::vector<HttpHeaderFieldStat> headerStatsTable(HDR_OTHER+1);
 
 /*
  * headers with field values defined as #(values) in HTTP/1.1
@@ -370,11 +277,12 @@
 {
     /* check that we have enough space for masks */
     assert(8 * sizeof(HttpHeaderMask) >= HDR_ENUM_END);
-    /* all headers must be described */
-    assert(countof(HeadersAttrs) == HDR_ENUM_END);
-
-    if (!Headers)
-        Headers = httpHeaderBuildFieldsInfo(HeadersAttrs, HDR_ENUM_END);
+
+    // check invariant: for each index in headerTable, (int)headerTable[index] = index
+    for (int i = 0; headerTable[i].name; ++i)
+        assert(headerTable[i].id == i);
+
+    // use headerLookupTable in place of Headers
 
     /* create masks */
     httpHeaderMaskInit(&ListHeadersMask, 0);
@@ -406,8 +314,6 @@
 void
 httpHeaderCleanModule(void)
 {
-    httpHeaderDestroyFieldsInfo(Headers, HDR_ENUM_END);
-    Headers = NULL;
     httpHdrCcCleanModule();
     httpHdrScCleanModule();
 }
@@ -549,7 +455,7 @@
         if (denied_mask && CBIT_TEST(*denied_mask, e->id))
             continue;
 
-        debugs(55, 7, "Updating header '" << HeadersAttrs[e->id].name << "' in cached entry");
+        debugs(55, 7, "Updating header '" << headerTable[e->id].name << "' in cached entry");
 
         addEntry(e->clone());
     }
@@ -953,10 +859,11 @@
 
     debugs(55, 7, this << " adding entry: " << e->id << " at " << entries.size());
 
-    if (CBIT_TEST(mask, e->id))
-        ++ Headers[e->id].stat.repCount;
-    else
+    if (CBIT_TEST(mask, e->id)) {
+        ++ headerStatsTable[e->id].repCount;
+    } else {
         CBIT_SET(mask, e->id);
+    }
 
     entries.push_back(e);
 
@@ -975,10 +882,11 @@
 
     debugs(55, 7, this << " adding entry: " << e->id << " at " << entries.size());
 
-    if (CBIT_TEST(mask, e->id))
-        ++ Headers[e->id].stat.repCount;
-    else
+    if (CBIT_TEST(mask, e->id)) {
+        ++ headerStatsTable[e->id].repCount; //TODO: use operator[] ?
+    } else {
         CBIT_SET(mask, e->id);
+    }
 
     entries.insert(entries.begin(),e);
 
@@ -1010,7 +918,7 @@
      */
     /* temporary warning: remove it? (Is it useful for diagnostics ?) */
     if (!s->size())
-        debugs(55, 3, "empty list header: " << Headers[id].name << "(" << id << ")");
+        debugs(55, 3, "empty list header: " << headerTable[id].name << "(" << id << ")");
     else
         debugs(55, 6, this << ": joined for id " << id << ": " << s);
 
@@ -1044,7 +952,7 @@
      */
     /* temporary warning: remove it? (Is it useful for diagnostics ?) */
     if (!s.size())
-        debugs(55, 3, "empty list header: " << Headers[id].name << "(" << id << ")");
+        debugs(55, 3, "empty list header: " << headerTable[id].name << "(" << id << ")");
     else
         debugs(55, 6, this << ": joined for id " << id << ": " << s);
 
@@ -1088,7 +996,7 @@
     assert(name);
 
     /* First try the quick path */
-    id = httpHeaderIdByNameDef(name, strlen(name));
+    id = httpHeaderIdByNameDef(SBuf(name));
 
     if (id != -1) {
         if (!has(id))
@@ -1179,7 +1087,7 @@
 HttpHeader::putInt(http_hdr_type id, int number)
 {
     assert_eid(id);
-    assert(Headers[id].type == ftInt);  /* must be of an appropriate type */
+    assert(headerTable[id].type == ftInt);  /* must be of an appropriate type */
     assert(number >= 0);
     addEntry(new HttpHeaderEntry(id, NULL, xitoa(number)));
 }
@@ -1188,7 +1096,7 @@
 HttpHeader::putInt64(http_hdr_type id, int64_t number)
 {
     assert_eid(id);
-    assert(Headers[id].type == ftInt64);    /* must be of an appropriate type */
+    assert(headerTable[id].type == ftInt64);    /* must be of an appropriate type */
     assert(number >= 0);
     addEntry(new HttpHeaderEntry(id, NULL, xint64toa(number)));
 }
@@ -1197,7 +1105,7 @@
 HttpHeader::putTime(http_hdr_type id, time_t htime)
 {
     assert_eid(id);
-    assert(Headers[id].type == ftDate_1123);    /* must be of an appropriate type */
+    assert(headerTable[id].type == ftDate_1123);    /* must be of an appropriate type */
     assert(htime >= 0);
     addEntry(new HttpHeaderEntry(id, NULL, mkrfc1123(htime)));
 }
@@ -1206,7 +1114,7 @@
 HttpHeader::insertTime(http_hdr_type id, time_t htime)
 {
     assert_eid(id);
-    assert(Headers[id].type == ftDate_1123);    /* must be of an appropriate type */
+    assert(headerTable[id].type == ftDate_1123);    /* must be of an appropriate type */
     assert(htime >= 0);
     insertEntry(new HttpHeaderEntry(id, NULL, mkrfc1123(htime)));
 }
@@ -1215,7 +1123,7 @@
 HttpHeader::putStr(http_hdr_type id, const char *str)
 {
     assert_eid(id);
-    assert(Headers[id].type == ftStr);  /* must be of an appropriate type */
+    assert(headerTable[id].type == ftStr);  /* must be of an appropriate type */
     assert(str);
     addEntry(new HttpHeaderEntry(id, NULL, str));
 }
@@ -1312,7 +1220,7 @@
 HttpHeader::getInt(http_hdr_type id) const
 {
     assert_eid(id);
-    assert(Headers[id].type == ftInt);  /* must be of an appropriate type */
+    assert(headerTable[id].type == ftInt);  /* must be of an appropriate type */
     HttpHeaderEntry *e;
 
     if ((e = findEntry(id)))
@@ -1325,7 +1233,7 @@
 HttpHeader::getInt64(http_hdr_type id) const
 {
     assert_eid(id);
-    assert(Headers[id].type == ftInt64);    /* must be of an appropriate type */
+    assert(headerTable[id].type == ftInt64);    /* must be of an appropriate type */
     HttpHeaderEntry *e;
 
     if ((e = findEntry(id)))
@@ -1340,7 +1248,7 @@
     HttpHeaderEntry *e;
     time_t value = -1;
     assert_eid(id);
-    assert(Headers[id].type == ftDate_1123);    /* must be of an appropriate type */
+    assert(headerTable[id].type == ftDate_1123);    /* must be of an appropriate type */
 
     if ((e = findEntry(id))) {
         value = parse_rfc1123(e->value.termedBuf());
@@ -1356,7 +1264,7 @@
 {
     HttpHeaderEntry *e;
     assert_eid(id);
-    assert(Headers[id].type == ftStr);  /* must be of an appropriate type */
+    assert(headerTable[id].type == ftStr);  /* must be of an appropriate type */
 
     if ((e = findEntry(id))) {
         httpHeaderNoteParsedEntry(e->id, e->value, 0);  /* no errors are possible */
@@ -1372,7 +1280,7 @@
 {
     HttpHeaderEntry *e;
     assert_eid(id);
-    assert(Headers[id].type == ftStr);  /* must be of an appropriate type */
+    assert(headerTable[id].type == ftStr);  /* must be of an appropriate type */
 
     if ((e = findLastEntry(id))) {
         httpHeaderNoteParsedEntry(e->id, e->value, 0);  /* no errors are possible */
@@ -1510,7 +1418,7 @@
 {
     ETag etag = {NULL, -1};
     HttpHeaderEntry *e;
-    assert(Headers[id].type == ftETag);     /* must be of an appropriate type */
+    assert(headerTable[id].type == ftETag);     /* must be of an appropriate type */
 
     if ((e = findEntry(id)))
         etagParseInit(&etag, e->value.termedBuf());
@@ -1523,7 +1431,7 @@
 {
     TimeOrTag tot;
     HttpHeaderEntry *e;
-    assert(Headers[id].type == ftDate_1123_or_ETag);    /* must be of an appropriate type */
+    assert(headerTable[id].type == ftDate_1123_or_ETag);    /* must be of an appropriate type */
     memset(&tot, 0, sizeof(tot));
 
     if ((e = findEntry(id))) {
@@ -1555,13 +1463,13 @@
     id = anId;
 
     if (id != HDR_OTHER)
-        name = Headers[id].name;
+        name = headerTable[id].name;
     else
         name = aName;
 
     value = aValue;
 
-    ++ Headers[id].stat.aliveCount;
+    ++ headerStatsTable[id].aliveCount;
 
     debugs(55, 9, "created HttpHeaderEntry " << this << ": '" << name << " : " << value );
 }
@@ -1570,16 +1478,10 @@
 {
     assert_eid(id);
     debugs(55, 9, "destroying entry " << this << ": '" << name << ": " << value << "'");
-    /* clean name if needed */
-
-    if (id == HDR_OTHER)
-        name.clean();
-
-    value.clean();
-
-    assert(Headers[id].stat.aliveCount);
-
-    -- Headers[id].stat.aliveCount;
+
+    assert(headerStatsTable[id].aliveCount); // is this really needed?
+
+    -- headerStatsTable[id].aliveCount;
 
     id = HDR_BAD_HDR;
 }
@@ -1623,7 +1525,8 @@
     debugs(55, 9, "parsing HttpHeaderEntry: near '" <<  getStringPrefix(field_start, field_end-field_start) << "'");
 
     /* is it a "known" field? */
-    http_hdr_type id = httpHeaderIdByName(field_start, name_len, Headers, HDR_ENUM_END);
+    http_hdr_type id = headerLookupTable.lookup(SBuf(field_start,name_len));
+    debugs(55, 9, "got hdr id hdr: " << id);
 
     String name;
 
@@ -1638,7 +1541,7 @@
     if (id == HDR_OTHER)
         name.limitInit(field_start, name_len);
     else
-        name = Headers[id].name;
+        name = headerTable[id].name;
 
     /* trim field value */
     while (value_start < field_end && xisspace(*value_start))
@@ -1660,7 +1563,7 @@
     /* set field value */
     value.limitInit(value_start, field_end - value_start);
 
-    ++ Headers[id].stat.seenCount;
+    ++ headerStatsTable[id].seenCount;
 
     debugs(55, 9, "parsed HttpHeaderEntry: '" << name << ": " << value << "'");
 
@@ -1687,7 +1590,6 @@
 HttpHeaderEntry::getInt() const
 {
     assert_eid (id);
-    assert (Headers[id].type == ftInt);
     int val = -1;
     int ok = httpHeaderParseInt(value.termedBuf(), &val);
     httpHeaderNoteParsedEntry(id, value, !ok);
@@ -1701,7 +1603,6 @@
 HttpHeaderEntry::getInt64() const
 {
     assert_eid (id);
-    assert (Headers[id].type == ftInt64);
     int64_t val = -1;
     int ok = httpHeaderParseOffset(value.termedBuf(), &val);
     httpHeaderNoteParsedEntry(id, value, !ok);
@@ -1714,11 +1615,11 @@
 static void
 httpHeaderNoteParsedEntry(http_hdr_type id, String const &context, int error)
 {
-    ++ Headers[id].stat.parsCount;
+    ++ headerStatsTable[id].parsCount;
 
     if (error) {
-        ++ Headers[id].stat.errCount;
-        debugs(55, 2, "cannot parse hdr field: '" << Headers[id].name << ": " << context << "'");
+        ++ headerStatsTable[id].errCount;
+        debugs(55, 2, "cannot parse hdr field: '" << headerTable[id].name << ": " << context << "'");
     }
 }
 
@@ -1735,7 +1636,7 @@
 {
     const int id = (int) val;
     const int valid_id = id >= 0 && id < HDR_ENUM_END;
-    const char *name = valid_id ? Headers[id].name.termedBuf() : "INVALID";
+    const char *name = valid_id ? headerTable[id].name : "INVALID";
     int visible = count > 0;
     /* for entries with zero count, list only those that belong to current type of message */
 
@@ -1787,7 +1688,7 @@
 httpHeaderStoreReport(StoreEntry * e)
 {
     int i;
-    http_hdr_type ht;
+//    http_hdr_type ht;
     assert(e);
 
     HttpHeaderStats[0].parsedCount =
@@ -1809,12 +1710,13 @@
     storeAppendPrintf(e, "%2s\t %-25s\t %5s\t %6s\t %6s\n",
                       "id", "name", "#alive", "%err", "%repeat");
 
-    for (ht = (http_hdr_type)0; ht < HDR_ENUM_END; ++ht) {
-        HttpHeaderFieldInfo *f = Headers + ht;
+    // scan heaaderTable and output
+    for (int j = 0; headerTable[j].name != nullptr; ++j) {
+        auto stats = headerStatsTable[j];
         storeAppendPrintf(e, "%2d\t %-25s\t %5d\t %6.3f\t %6.3f\n",
-                          f->id, f->name.termedBuf(), f->stat.aliveCount,
-                          xpercent(f->stat.errCount, f->stat.parsCount),
-                          xpercent(f->stat.repCount, f->stat.seenCount));
+            headerTable[j].id, headerTable[j].name, stats.aliveCount,
+            xpercent(stats.errCount, stats.parsCount),
+            xpercent(stats.repCount, stats.seenCount));
     }
 
     storeAppendPrintf(e, "Headers Parsed: %d + %d = %d\n",
@@ -1824,6 +1726,7 @@
     storeAppendPrintf(e, "Hdr Fields Parsed: %d\n", HeaderEntryParsedCount);
 }
 
+// (ab)used by other modules.
 http_hdr_type
 httpHeaderIdByName(const char *name, size_t name_len, const HttpHeaderFieldInfo * info, int end)
 {
@@ -1841,23 +1744,22 @@
 }
 
 http_hdr_type
+httpHeaderIdByNameDef(const SBuf &name)
+{
+    return headerLookupTable.lookup(name);
+}
+
+http_hdr_type
 httpHeaderIdByNameDef(const char *name, int name_len)
 {
-    if (!Headers)
-        Headers = httpHeaderBuildFieldsInfo(HeadersAttrs, HDR_ENUM_END);
-
-    return httpHeaderIdByName(name, name_len, Headers, HDR_ENUM_END);
+    return headerLookupTable.lookup(SBuf(name,name_len));
 }
 
 const char *
 httpHeaderNameById(int id)
 {
-    if (!Headers)
-        Headers = httpHeaderBuildFieldsInfo(HeadersAttrs, HDR_ENUM_END);
-
     assert(id >= 0 && id < HDR_ENUM_END);
-
-    return Headers[id].name.termedBuf();
+    return headerTable[id].name;
 }
 
 int

=== modified file 'src/HttpHeader.h'
--- src/HttpHeader.h	2015-03-03 11:43:26 +0000
+++ src/HttpHeader.h	2015-07-31 14:42:48 +0000
@@ -26,21 +26,6 @@
 class StoreEntry;
 class SBuf;
 
-/** possible types for http header fields */
-typedef enum {
-    ftInvalid = HDR_ENUM_END,   /**< to catch nasty errors with hdr_id<->fld_type clashes */
-    ftInt,
-    ftInt64,
-    ftStr,
-    ftDate_1123,
-    ftETag,
-    ftPCc,
-    ftPContRange,
-    ftPRange,
-    ftPSc,
-    ftDate_1123_or_ETag
-} field_type;
-
 /** Possible owners of http header */
 typedef enum {
     hoNone =0,

=== modified file 'src/HttpHeaderTools.cc'
--- src/HttpHeaderTools.cc	2015-03-03 16:51:03 +0000
+++ src/HttpHeaderTools.cc	2015-07-31 14:14:34 +0000
@@ -456,7 +456,7 @@
 headerMangler *
 HeaderManglers::track(const char *name)
 {
-    int id = httpHeaderIdByNameDef(name, strlen(name));
+    int id = httpHeaderIdByNameDef(SBuf(name));
 
     if (id == HDR_BAD_HDR) { // special keyword or a custom header
         if (strcmp(name, "All") == 0)

=== modified file 'src/HttpHeaderTools.h'
--- src/HttpHeaderTools.h	2015-01-13 07:25:36 +0000
+++ src/HttpHeaderTools.h	2015-07-31 10:28:59 +0000
@@ -118,6 +118,7 @@
 HttpHeaderFieldInfo *httpHeaderBuildFieldsInfo(const HttpHeaderFieldAttrs * attrs, int count);
 void httpHeaderDestroyFieldsInfo(HttpHeaderFieldInfo * info, int count);
 http_hdr_type httpHeaderIdByName(const char *name, size_t name_len, const HttpHeaderFieldInfo * attrs, int end);
+http_hdr_type httpHeaderIdByNameDef(const SBuf &name);
 http_hdr_type httpHeaderIdByNameDef(const char *name, int name_len);
 const char *httpHeaderNameById(int id);
 int httpHeaderHasConnDir(const HttpHeader * hdr, const char *directive);

=== modified file 'src/acl/HttpHeaderData.cc'
--- src/acl/HttpHeaderData.cc	2015-07-27 12:51:43 +0000
+++ src/acl/HttpHeaderData.cc	2015-07-31 10:28:59 +0000
@@ -76,7 +76,7 @@
     char* t = ConfigParser::strtokFile();
     assert (t != NULL);
     hdrName = t;
-    hdrId = httpHeaderIdByNameDef(hdrName.rawBuf(), hdrName.size());
+    hdrId = httpHeaderIdByNameDef(SBuf(hdrName));
     regex_rule->parse();
 }
 

=== modified file 'src/base/LookupTable.h'
--- src/base/LookupTable.h	2015-07-28 12:12:10 +0000
+++ src/base/LookupTable.h	2015-07-30 12:35:58 +0000
@@ -14,11 +14,27 @@
 #include <map>
 
 /**
- * SBuf -> enum lookup table
+ * a record in the initializer list for a LookupTable
+ *
+ * In case it is wished to extend the structure of a LookupTable's initializer
+ * list, it can be done by using a custom struct which must match
+ * LookupTableRecord's signature plus any extra custom fields the user may
+ * wish to add; the extended record type must then be passed as RecordType
+ * template parameter to LookupTable.
+ */
+template <typename EnumType>
+struct LookupTableRecord
+{
+    const char *name;
+    EnumType id;
+};
+
+/**
+ * SBuf -> case-insensitive enum lookup table
  *
  * How to use:
  * enum enum_type { ... };
- * static const LookupTable<enum_type>::Record initializerTable[] {
+ * static const LookupTable<enum_type>::Record initializerTable[] = {
  *   {"key1", ENUM_1}, {"key2", ENUM_2}, ... {nullptr, ENUM_INVALID_VALUE}
  * };
  * LookupTable<enum_type> lookupTableInstance(ENUM_INVALID_VALUE, initializerTable);
@@ -29,15 +45,18 @@
  * if (item != ENUM_INVALID_VALUE) { // do stuff }
  *
  */
-template<typename EnumType>
+
+struct SBufCaseInsensitiveLess : public std::binary_function<SBuf, SBuf, bool> {
+    bool operator() (const SBuf &x, const SBuf &y) const {
+        return x.caseCmp(y) < 0;
+    }
+};
+template<typename EnumType, typename RecordType = LookupTableRecord<EnumType> >
 class LookupTable
 {
 public:
     /// element of the lookup table initialization list
-    typedef struct {
-        const char *name;
-        EnumType id;
-    } Record;
+    typedef RecordType Record;
 
     LookupTable(const EnumType theInvalid, const Record data[]) :
         invalidValue(theInvalid)
@@ -46,6 +65,7 @@
             lookupTable[SBuf(data[i].name)] = data[i].id;
         }
     }
+
     EnumType lookup(const SBuf &key) const {
         auto r = lookupTable.find(key);
         if (r == lookupTable.end())
@@ -54,7 +74,7 @@
     }
 
 private:
-    typedef std::map<const SBuf, EnumType> lookupTable_t;
+    typedef std::map<const SBuf, EnumType, SBufCaseInsensitiveLess> lookupTable_t;
     lookupTable_t lookupTable;
     EnumType invalidValue;
 };

=== modified file 'src/cache_cf.cc'
--- src/cache_cf.cc	2015-07-29 07:11:17 +0000
+++ src/cache_cf.cc	2015-07-31 14:14:34 +0000
@@ -4608,7 +4608,7 @@
     }
     HeaderWithAcl hwa;
     hwa.fieldName = fn;
-    hwa.fieldId = httpHeaderIdByNameDef(fn, strlen(fn));
+    hwa.fieldId = httpHeaderIdByNameDef(SBuf(fn));
     if (hwa.fieldId == HDR_BAD_HDR)
         hwa.fieldId = HDR_OTHER;
 

=== modified file 'src/external_acl.cc'
--- src/external_acl.cc	2015-07-21 00:12:11 +0000
+++ src/external_acl.cc	2015-07-31 14:14:34 +0000
@@ -244,7 +244,7 @@
     }
 
     format->header = xstrdup(header);
-    format->header_id = httpHeaderIdByNameDef(header, strlen(header));
+    format->header_id = httpHeaderIdByNameDef(SBuf(header));
 }
 
 void

=== modified file 'src/http/Makefile.am'
--- src/http/Makefile.am	2015-01-13 07:25:36 +0000
+++ src/http/Makefile.am	2015-07-31 14:42:48 +0000
@@ -21,6 +21,7 @@
 	MethodType.h \
 	ProtocolVersion.h \
 	RegisteredHeaders.h \
+	RegisteredHeaders.cc \
 	RequestMethod.cc \
 	RequestMethod.h \
 	StatusCode.cc \

=== added file 'src/http/RegisteredHeaders.cc'
--- src/http/RegisteredHeaders.cc	1970-01-01 00:00:00 +0000
+++ src/http/RegisteredHeaders.cc	2015-07-31 19:37:37 +0000
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
+ *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+ */
+
+#include "squid.h"
+#include "RegisteredHeaders.h"
+
+/*
+ * A table with major attributes for every known field.
+ *
+ * Invariant on this table:
+ * for each index in headerTable, (int)headerTable[index] = index
+ */
+const HeaderTableRecord headerTable[] = {
+    {"Accept", HDR_ACCEPT, ftStr},
+    {"Accept-Charset", HDR_ACCEPT_CHARSET, ftStr},
+    {"Accept-Encoding", HDR_ACCEPT_ENCODING, ftStr},
+    {"Accept-Language", HDR_ACCEPT_LANGUAGE, ftStr},
+    {"Accept-Ranges", HDR_ACCEPT_RANGES, ftStr},
+    {"Age", HDR_AGE, ftInt},
+    {"Allow", HDR_ALLOW, ftStr},
+    {"Alternate-Protocol", HDR_ALTERNATE_PROTOCOL, ftStr},
+    {"Authentication-Info", HDR_AUTHENTICATION_INFO, ftStr},
+    {"Authorization", HDR_AUTHORIZATION, ftStr},    /* for now */
+    {"Cache-Control", HDR_CACHE_CONTROL, ftPCc},
+    {"Connection", HDR_CONNECTION, ftStr},
+    {"Content-Base", HDR_CONTENT_BASE, ftStr},
+    {"Content-Disposition", HDR_CONTENT_DISPOSITION, ftStr},  /* for now */
+    {"Content-Encoding", HDR_CONTENT_ENCODING, ftStr},
+    {"Content-Language", HDR_CONTENT_LANGUAGE, ftStr},
+    {"Content-Length", HDR_CONTENT_LENGTH, ftInt64},
+    {"Content-Location", HDR_CONTENT_LOCATION, ftStr},
+    {"Content-MD5", HDR_CONTENT_MD5, ftStr},    /* for now */
+    {"Content-Range", HDR_CONTENT_RANGE, ftPContRange},
+    {"Content-Type", HDR_CONTENT_TYPE, ftStr},
+    {"Cookie", HDR_COOKIE, ftStr},
+    {"Cookie2", HDR_COOKIE2, ftStr},
+    {"Date", HDR_DATE, ftDate_1123},
+    {"ETag", HDR_ETAG, ftETag},
+    {"Expect", HDR_EXPECT, ftStr},
+    {"Expires", HDR_EXPIRES, ftDate_1123},
+    {"Forwarded", HDR_FORWARDED, ftStr},
+    {"From", HDR_FROM, ftStr},
+    {"Host", HDR_HOST, ftStr},
+    {"HTTP2-Settings", HDR_HTTP2_SETTINGS, ftStr}, /* for now */
+    {"If-Match", HDR_IF_MATCH, ftStr},  /* for now */
+    {"If-Modified-Since", HDR_IF_MODIFIED_SINCE, ftDate_1123},
+    {"If-None-Match", HDR_IF_NONE_MATCH, ftStr},    /* for now */
+    {"If-Range", HDR_IF_RANGE, ftDate_1123_or_ETag},
+    {"If-Unmodified-Since", HDR_IF_UNMODIFIED_SINCE, ftDate_1123},
+    {"Keep-Alive", HDR_KEEP_ALIVE, ftStr},
+    {"Key", HDR_KEY, ftStr},
+    {"Last-Modified", HDR_LAST_MODIFIED, ftDate_1123},
+    {"Link", HDR_LINK, ftStr},
+    {"Location", HDR_LOCATION, ftStr},
+    {"Max-Forwards", HDR_MAX_FORWARDS, ftInt64},
+    {"Mime-Version", HDR_MIME_VERSION, ftStr},  /* for now */
+    {"Negotiate", HDR_NEGOTIATE, ftStr},
+    {"Origin", HDR_ORIGIN, ftStr},
+    {"Pragma", HDR_PRAGMA, ftStr},
+    {"Proxy-Authenticate", HDR_PROXY_AUTHENTICATE, ftStr},
+    {"Proxy-Authentication-Info", HDR_PROXY_AUTHENTICATION_INFO, ftStr},
+    {"Proxy-Authorization", HDR_PROXY_AUTHORIZATION, ftStr},
+    {"Proxy-Connection", HDR_PROXY_CONNECTION, ftStr},
+    {"Proxy-support", HDR_PROXY_SUPPORT, ftStr},
+    {"Public", HDR_PUBLIC, ftStr},
+    {"Range", HDR_RANGE, ftPRange},
+    {"Referer", HDR_REFERER, ftStr},
+    {"Request-Range", HDR_REQUEST_RANGE, ftPRange}, /* usually matches HDR_RANGE */
+    {"Retry-After", HDR_RETRY_AFTER, ftStr},    /* for now (ftDate_1123 or ftInt!} */
+    {"Server", HDR_SERVER, ftStr},
+    {"Set-Cookie", HDR_SET_COOKIE, ftStr},
+    {"Set-Cookie2", HDR_SET_COOKIE2, ftStr},
+    {"TE", HDR_TE, ftStr},
+    {"Title", HDR_TITLE, ftStr},
+    {"Trailer", HDR_TRAILER, ftStr},
+    {"Transfer-Encoding", HDR_TRANSFER_ENCODING, ftStr},
+    {"Translate", HDR_TRANSLATE, ftStr},    /* for now. may need to crop */
+    {"Unless-Modified-Since", HDR_UNLESS_MODIFIED_SINCE, ftStr},  /* for now ignore. may need to crop */
+    {"Upgrade", HDR_UPGRADE, ftStr},    /* for now */
+    {"User-Agent", HDR_USER_AGENT, ftStr},
+    {"Vary", HDR_VARY, ftStr},  /* for now */
+    {"Via", HDR_VIA, ftStr},    /* for now */
+    {"Warning", HDR_WARNING, ftStr},    /* for now */
+    {"WWW-Authenticate", HDR_WWW_AUTHENTICATE, ftStr},
+    {"X-Cache", HDR_X_CACHE, ftStr},
+    {"X-Cache-Lookup", HDR_X_CACHE_LOOKUP, ftStr},
+    {"X-Forwarded-For", HDR_X_FORWARDED_FOR, ftStr},
+    {"X-Request-URI", HDR_X_REQUEST_URI, ftStr},
+    {"X-Squid-Error", HDR_X_SQUID_ERROR, ftStr},
+#if X_ACCELERATOR_VARY
+    {"X-Accelerator-Vary", HDR_X_ACCELERATOR_VARY, ftStr},
+#endif
+#if USE_ADAPTATION
+    {"X-Next-Services", HDR_X_NEXT_SERVICES, ftStr},
+#endif
+    {"Surrogate-Capability", HDR_SURROGATE_CAPABILITY, ftStr},
+    {"Surrogate-Control", HDR_SURROGATE_CONTROL, ftPSc},
+    {"Front-End-Https", HDR_FRONT_END_HTTPS, ftStr},
+    {"FTP-Command", HDR_FTP_COMMAND, ftStr},
+    {"FTP-Arguments", HDR_FTP_ARGUMENTS, ftStr},
+    {"FTP-Pre", HDR_FTP_PRE, ftStr},
+    {"FTP-Status", HDR_FTP_STATUS, ftInt},
+    {"FTP-Reason", HDR_FTP_REASON, ftStr},
+    {"Other:", HDR_OTHER, ftStr},    /* ':' will not allow matches */
+    {nullptr, HDR_BAD_HDR}    /* end of table */
+};

=== modified file 'src/http/RegisteredHeaders.h'
--- src/http/RegisteredHeaders.h	2015-05-15 00:38:20 +0000
+++ src/http/RegisteredHeaders.h	2015-07-31 15:05:22 +0000
@@ -12,7 +12,6 @@
 /// recognized or "known" header fields; and the RFC which defines them (or not)
 /// http://www.iana.org/assignments/message-headers/message-headers.xhtml
 typedef enum {
-    HDR_BAD_HDR = -1,
     HDR_ACCEPT = 0,                     /**< RFC 7231 */
     HDR_ACCEPT_CHARSET,                 /**< RFC 7231 */
     HDR_ACCEPT_ENCODING,                /**< RFC 7231 */
@@ -116,8 +115,35 @@
     HDR_FTP_STATUS,                     /**< Internal header for FTP reply status */
     HDR_FTP_REASON,                     /**< Internal header for FTP reply reason */
     HDR_OTHER,                          /**< internal tag value for "unknown" headers */
-    HDR_ENUM_END
+    HDR_ENUM_END,
+    HDR_BAD_HDR = -1
 } http_hdr_type;
 
+/** possible types for http header fields */
+//TODO: move to strongly-typed enums? (enum class)
+typedef enum {
+    ftInvalid = HDR_ENUM_END,   /**< to catch nasty errors with hdr_id<->fld_type clashes */
+    ftInt,
+    ftInt64,
+    ftStr,
+    ftDate_1123,
+    ftETag,
+    ftPCc,
+    ftPContRange,
+    ftPRange,
+    ftPSc,
+    ftDate_1123_or_ETag
+} field_type;
+
+/* POD for headerTable */
+class HeaderTableRecord {
+public:
+    const char *name;
+    http_hdr_type id;
+    field_type type;
+};
+
+extern const HeaderTableRecord headerTable[];
+
 #endif /* SQUID_HTTP_REGISTEREDHEADERS_H */
 

# Begin bundle
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
_______________________________________________
squid-dev mailing list
squid-dev@lists.squid-cache.org
http://lists.squid-cache.org/listinfo/squid-dev

Reply via email to