text: /*
   * Copyright (c) 2013, Peter Thorson. All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions are met:
   *     * Redistributions of source code must retain the above copyright
   *       notice, this list of conditions and the following disclaimer.
   *     * Redistributions in binary form must reproduce the above copyright
   *       notice, this list of conditions and the following disclaimer in the
   *       documentation and/or other materials provided with the distribution.
   *     * Neither the name of the WebSocket++ Project nor the
   *       names of its contributors may be used to endorse or promote products
   *       derived from this software without specific prior written permission.
   *
   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   * ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY
   * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   *
   */
  
  #ifndef HTTP_CONSTANTS_HPP
  #define HTTP_CONSTANTS_HPP
  
  #include <map>
  #include <string>
  #include <vector>
  
  namespace websocketpp {
  namespace http {
      /// The type of an HTTP attribute list
      /**
       * The attribute list is an unordered key/value map. Encoded attribute
       * values are delimited by semicolons.
       */
      typedef std::map<std::string,std::string> attribute_list;
  
      /// The type of an HTTP parameter list
      /**
       * The parameter list is an ordered pairing of a parameter and its
       * associated attribute list. Encoded parameter values are delimited by
       * commas.
       */
      typedef std::vector< std::pair<std::string,attribute_list> > parameter_list;
  
      /// Literal value of the HTTP header delimiter
      static char const header_delimiter[] = "\r\n";
  
      /// Literal value of the HTTP header separator
      static char const header_separator[] = ":";
  
      /// Literal value of an empty header
      static std::string const empty_header = "";
  
      /// Maximum size in bytes before rejecting an HTTP header as too big.
      size_t const max_header_size = 16000;
  
      /// Number of bytes to use for temporary istream read buffers
      size_t const istream_buffer = 512;
  
      /// invalid HTTP token characters
      /**
       * 0x00 - 0x32, 0x7f-0xff
       * ( ) < > @ , ; : \ " / [ ] ? = { }
       */
      static char const header_token[] = {
          0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 00..0f
          0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 10..1f
          0,1,0,1,1,1,1,1,0,0,1,1,0,1,1,0, // 20..2f
          1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0, // 30..3f
          0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 40..4f
          1,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1, // 50..5f
          1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 60..6f
          1,1,1,1,1,1,1,1,1,1,1,0,1,0,1,0, // 70..7f
          0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 80..8f
          0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 90..9f
          0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // a0..af
          0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // b0..bf
          0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // c0..cf
          0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // d0..df
          0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // e0..ef
          0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // f0..ff
      };
  
      /// Is the character a token
      inline bool is_token_char(unsigned char c) {
          return (header_token[c] == 1);
      }
  
      /// Is the character a non-token
      inline bool is_not_token_char(unsigned char c) {
          return !header_token[c];
      }
  
      /// Is the character whitespace
      /**
       * whitespace is space (32) or horizontal tab (9)
       */
      inline bool is_whitespace_char(unsigned char c) {
          return (c == 9 || c == 32);
      }
  
      /// Is the character non-whitespace
      inline bool is_not_whitespace_char(unsigned char c) {
          return (c != 9 && c != 32);
      }
  
      /// HTTP Status codes
      namespace status_code {
          enum value {
              uninitialized = 0,
  
              continue_code = 100,
              switching_protocols = 101,
  
              ok = 200,
              created = 201,
              accepted = 202,
              non_authoritative_information = 203,
              no_content = 204,
              reset_content = 205,
              partial_content = 206,
  
              multiple_choices = 300,
              moved_permanently = 301,
              found = 302,
              see_other = 303,
              not_modified = 304,
              use_proxy = 305,
              temporary_redirect = 307,
  
              bad_request = 400,
              unauthorized = 401,
              payment_required = 402,
              forbidden = 403,
              not_found = 404,
              method_not_allowed = 405,
              not_acceptable = 406,
              proxy_authentication_required = 407,
              request_timeout = 408,
              conflict = 409,
              gone = 410,
              length_required = 411,
              precondition_failed = 412,
              request_entity_too_large = 413,
              request_uri_too_long = 414,
              unsupported_media_type = 415,
              request_range_not_satisfiable = 416,
              expectation_failed = 417,
              im_a_teapot = 418,
              upgrade_required = 426,
              precondition_required = 428,
              too_many_requests = 429,
              request_header_fields_too_large = 431,
  
              internal_server_error = 500,
              not_implemented = 501,
              bad_gateway = 502,
              service_unavailable = 503,
              gateway_timeout = 504,
              http_version_not_supported = 505,
              not_extended = 510,
              network_authentication_required = 511
          };
  
          // TODO: should this be inline?
          inline std::string get_string(value c) {
              switch (c) {
                  case uninitialized:
                      return "Uninitialized";
                  case continue_code:
                      return "Continue";
                  case switching_protocols:
                      return "Switching Protocols";
                  case ok:
                      return "OK";
                  case created:
                      return "Created";
                  case accepted:
                      return "Accepted";
                  case non_authoritative_information:
                      return "Non Authoritative Information";
                  case no_content:
                      return "No Content";
                  case reset_content:
                      return "Reset Content";
                  case partial_content:
                      return "Partial Content";
                  case multiple_choices:
                      return "Multiple Choices";
                  case moved_permanently:
                      return "Moved Permanently";
                  case found:
                      return "Found";
                  case see_other:
                      return "See Other";
                  case not_modified:
                      return "Not Modified";
                  case use_proxy:
                      return "Use Proxy";
                  case temporary_redirect:
                      return "Temporary Redirect";
                  case bad_request:
                      return "Bad Request";
                  case unauthorized:
                      return "Unauthorized";
                  case payment_required:
                      return "Payment Required";
                  case forbidden:
                      return "Forbidden";
                  case not_found:
                      return "Not Found";
                  case method_not_allowed:
                      return "Method Not Allowed";
                  case not_acceptable:
                      return "Not Acceptable";
                  case proxy_authentication_required:
                      return "Proxy Authentication Required";
                  case request_timeout:
                      return "Request Timeout";
                  case conflict:
                      return "Conflict";
                  case gone:
                      return "Gone";
                  case length_required:
                      return "Length Required";
                  case precondition_failed:
                      return "Precondition Failed";
                  case request_entity_too_large:
                      return "Request Entity Too Large";
                  case request_uri_too_long:
                      return "Request-URI Too Long";
                  case unsupported_media_type:
                      return "Unsupported Media Type";
                  case request_range_not_satisfiable:
                      return "Requested Range Not Satisfiable";
                  case expectation_failed:
                      return "Expectation Failed";
                  case im_a_teapot:
                      return "I'm a teapot";
                  case upgrade_required:
                      return "Upgrade Required";
                  case precondition_required:
                      return "Precondition Required";
                  case too_many_requests:
                      return "Too Many Requests";
                  case request_header_fields_too_large:
                      return "Request Header Fields Too Large";
                  case internal_server_error:
                      return "Internal Server Error";
                  case not_implemented:
                      return "Not Implimented";
                  case bad_gateway:
                      return "Bad Gateway";
                  case service_unavailable:
                      return "Service Unavailable";
                  case gateway_timeout:
                      return "Gateway Timeout";
                  case http_version_not_supported:
                      return "HTTP Version Not Supported";
                  case not_extended:
                      return "Not Extended";
                  case network_authentication_required:
                      return "Network Authentication Required";
                  default:
                      return "Unknown";
              }
          }
      }
  
      class exception : public std::exception {
      public:
          exception(const std::string& log_msg,
                    status_code::value error_code,
                    const std::string& error_msg = "",
                    const std::string& body = "")
            : m_msg(log_msg)
            , m_error_msg(error_msg)
            , m_body(body)
            , m_error_code(error_code) {}
  
          ~exception() throw() {}
  
          virtual const char* what() const throw() {
              return m_msg.c_str();
          }
  
          std::string         m_msg;
          std::string         m_error_msg;
          std::string         m_body;
          status_code::value  m_error_code;
      };
  }
  }
  
  #endif // HTTP_CONSTANTS_HPP
  