reSIProcate/stack  9694
testHashCasen.cxx
Go to the documentation of this file.
00001 #include <iostream>
00002 #include <string>
00003 #include <assert.h>
00004 
00005 // djb2 hash swiped from the net, credited to bernstein
00006 unsigned int
00007 hash(const char *str, unsigned int len)
00008 {
00009    unsigned int hash = 5381;
00010    int c;
00011    int i = 0;
00012 
00013    while (c = *str++)
00014    {
00015       if (i == len)
00016       {
00017          break;
00018       }
00019       hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
00020    }
00021    hash = ((hash << 5) + hash) + len;
00022    return hash;
00023 }
00024 
00025 // unrolled and case insensitized
00026 unsigned int 
00027 hashcasen(const char* data, 
00028           unsigned int len)
00029 {
00030    unsigned int x = 5381;
00031    switch (len)
00032    {
00033       case 1 :
00034          return (x << 5) + x + (0x40 | *data);
00035       case 2 : 
00036       {
00037          x = (x << 5) + x + (0x40 | *data);
00038          return (x << 5) + x + (0x40 | *(data+1));
00039       }
00040       case 3 : 
00041       {
00042          x = (x << 5) + x + (0x40 | *data);
00043          x = (x << 5) + x + (0x40 | *(data+1));
00044          return (x << 5) + x + (0x40 | *(data+2));
00045       }
00046       default :
00047       {
00048          x = (x << 5) + x + (0x40 | *data);
00049          x = (x << 5) + x + (0x40 | *(data+len-1));
00050          x = (x << 5) + x + (0x40 | *(data+2));
00051          x = (x << 5) + x + (0x40 | *(data+len-2));
00052          return (x << 5) + x + len;
00053       }
00054    }
00055 }
00056 
00057 // strategy:
00058 // use sparse parallel arrays of size num_buckets + 1
00059 // name => enum
00060 // the name is stored by hashcasen(name) % num_buckets
00061 // if the position is occupied, move up the array until a free spot is found
00062 // on lookup:
00063 //    if the name array [hash] is empty, return UNKNOWN
00064 //    if the name array[hash] is occupied and equal, found, return enum[hash]
00065 //    if the name array[hash] is occupied and !equal, try hash++
00066 
00067 int 
00068 main()
00069 {
00070    std::string parameters[17] = 
00071       {
00072          "transport",
00073          "user",
00074          "method",
00075          "ttl",
00076          "maddr",
00077          "lr",
00078          "q",
00079          "purpose",
00080          "expires",
00081          "handling",
00082          "tag",
00083          "duration",
00084          "branch",
00085          "received",
00086          "comp",
00087          "rport"
00088       };
00089 
00090    std::string PARAMETERS[17] = 
00091       {
00092          "TRANSPORT",
00093          "USER",
00094          "METHOD",
00095          "TTL",
00096          "MADDR",
00097          "LR",
00098          "Q",
00099          "PURPOSE",
00100          "EXPIRES",
00101          "HANDLING",
00102          "TAG",
00103          "DURATION",
00104          "BRANCH",
00105          "RECEIVED",
00106          "COMP",
00107          "RPORT"
00108       };
00109 
00110 
00111    for (int i = 0; i < 16; i++)
00112    {
00113       std::cerr << parameters[i] << " => " << hashcasen(parameters[i].c_str(), parameters[i].size()) % 73 << std::endl;
00114       assert(hashcasen(parameters[i].c_str(), parameters[i].size()) == hashcasen(parameters[i].c_str(), PARAMETERS[i].size()));
00115    }
00116    std::cerr << std::endl;
00117    std::cerr << std::endl;
00118 
00119    std::string headers[] = 
00120       {
00121          "Body",
00122          "CSeq",
00123          "Call_ID",
00124          "Contact",
00125          "Content_Length",
00126          "Expires",
00127          "From",
00128          "Max_Forwards",
00129          "Route",
00130          "Subject",
00131          "To",
00132          "Via",
00133          "Accept",
00134          "Accept_Encoding",
00135          "Accept_Language",
00136          "Alert_Info",
00137          "Allow",
00138          "Authentication_Info",
00139          "Authorization",
00140          "Call_Info",
00141          "Content_Disposition",
00142          "Content_Encoding",
00143          "Content_Language",
00144          "Content_Type",
00145          "Date",
00146          "Error_Info",
00147          "In_Reply_To",
00148          "Min_Expires",
00149          "MIME_Version",
00150          "Organization",
00151          "Priority",
00152          "Proxy_Authenticate",
00153          "Proxy_Authorization",
00154          "Proxy_Require",
00155          "Record_Route",
00156          "Reply_To",
00157          "Require",
00158          "Retry_After",
00159          "Server",
00160          "Supported",
00161          "Timestamp",
00162          "Unsupported",
00163          "User_Agent",
00164          "Warning",
00165          "WWW_Authenticate",
00166          "Subscription_State"
00167       };
00168 
00169    for (int i = 0; i < 46; i++)
00170    {
00171       std::cerr << headers[i] << " => " << hashcasen(headers[i].c_str(), headers[i].size()) % 505 << std::endl;
00172    }
00173 }
00174 
00175 
00176 
00177 
00178 /* ====================================================================
00179  * The Vovida Software License, Version 1.0 
00180  * 
00181  * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
00182  * 
00183  * Redistribution and use in source and binary forms, with or without
00184  * modification, are permitted provided that the following conditions
00185  * are met:
00186  * 
00187  * 1. Redistributions of source code must retain the above copyright
00188  *    notice, this list of conditions and the following disclaimer.
00189  * 
00190  * 2. Redistributions in binary form must reproduce the above copyright
00191  *    notice, this list of conditions and the following disclaimer in
00192  *    the documentation and/or other materials provided with the
00193  *    distribution.
00194  * 
00195  * 3. The names "VOCAL", "Vovida Open Communication Application Library",
00196  *    and "Vovida Open Communication Application Library (VOCAL)" must
00197  *    not be used to endorse or promote products derived from this
00198  *    software without prior written permission. For written
00199  *    permission, please contact vocal@vovida.org.
00200  *
00201  * 4. Products derived from this software may not be called "VOCAL", nor
00202  *    may "VOCAL" appear in their name, without prior written
00203  *    permission of Vovida Networks, Inc.
00204  * 
00205  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
00206  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00207  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
00208  * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
00209  * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
00210  * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
00211  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00212  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00213  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
00214  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00215  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
00216  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
00217  * DAMAGE.
00218  * 
00219  * ====================================================================
00220  * 
00221  * This software consists of voluntary contributions made by Vovida
00222  * Networks, Inc. and many individuals on behalf of Vovida Networks,
00223  * Inc.  For more information on Vovida Networks, Inc., please see
00224  * <http://www.vovida.org/>.
00225  *
00226  */