// charset_names.cc
// This file is part of libpbe; see http://anyterm.org/
// (C) 2008 Philip Endecott

// Distributed under the Boost Software License, Version 1.0:
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
// 
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

#include "charset/charset_names.hh"

#include <string>
#include <algorithm>
#include <cctype>
#include <cstring>

#include <iostream>

using namespace std;


namespace pbe {

#include "generated/charset_iana_names_body.cc"
#include "generated/charset_mime_names_body.cc"


struct charset_lookup {
  const char* name;
  charset_t cs;
};

static const charset_lookup lookup_table[] = {
#include "generated/charset_lookup_body.cc"
//  {NULL, 0}
};


static bool charset_name_less_than(const charset_lookup& a, string b)
{
  return ::strcmp(a.name,b.c_str())<0;
}

charset_t lookup_charset(const char* name)
{
  string stripped_lc_name;
  bool was_digit=false;
  bool uscore_pending=false;
  for (const char* p = name; *p; ++p) {
    if (isalnum(*p)) {
      if (uscore_pending && isdigit(*p)) {
        stripped_lc_name += '_';
      }
      stripped_lc_name += tolower(*p);
      was_digit = isdigit(*p);
      uscore_pending = false;
    } else if (was_digit) {
      uscore_pending=true;
    }
  }

  const charset_lookup* lookup_table_end = 
    lookup_table+sizeof(lookup_table)/sizeof(charset_lookup);
  const charset_lookup* l =
    lower_bound(&lookup_table[0], lookup_table_end, stripped_lc_name, charset_name_less_than);
  if (l==lookup_table_end || string(l->name)!=stripped_lc_name) {
    throw NoSuchCharacterSet();
  }
  return l->cs;
}


charset_t lookup_charset(string name) {
  return lookup_charset(name.c_str());
}

};

