/* $Id: PubmedArticle.cpp 650858 2022-06-03 16:56:21Z grichenk $
 * ===========================================================================
 *
 *                            PUBLIC DOMAIN NOTICE
 *               National Center for Biotechnology Information
 *
 *  This software/database is a "United States Government Work" under the
 *  terms of the United States Copyright Act.  It was written as part of
 *  the author's official duties as a United States Government employee and
 *  thus cannot be copyrighted.  This software/database is freely available
 *  to the public for use. The National Library of Medicine and the U.S.
 *  Government have not placed any restriction on its use or reproduction.
 *
 *  Although all reasonable efforts have been taken to ensure the accuracy
 *  and reliability of the software and data, the NLM and the U.S.
 *  Government do not and cannot warrant the performance or results that
 *  may be obtained by using this software or data. The NLM and the U.S.
 *  Government disclaim all warranties, express or implied, including
 *  warranties of performance, merchantability or fitness for any particular
 *  purpose.
 *
 *  Please cite the author in any work or product based on this material.
 *
 * ===========================================================================
 *
 * Author:  .......
 *
 * File Description:
 *   .......
 *
 * Remark:
 *   This code was originally generated by application DATATOOL
 *   using the following specifications:
 *   'efetch.dtd'.
 */

 // standard includes
#include <ncbi_pch.hpp>
#include <codecvt>
#include <numeric>
#include <regex>
#include <unordered_map>
#include <objects/pubmed/Pubmed_entry.hpp>
#include <objects/medline/Medline_entry.hpp>
#include <objects/general/Date.hpp>
#include <objects/general/Date_std.hpp>
#include <objects/biblio/biblio__.hpp>
#include <objects/general/Dbtag.hpp>
#include <objects/general/Object_id.hpp>
#include <objects/general/Person_id.hpp>
#include <objects/medline/medline__.hpp>
#include <objtools/eutils/efetch/efetch__.hpp>


// generated includes
#include <objtools/eutils/efetch/PubmedArticle.hpp>

// generated classes

BEGIN_eutils_SCOPE // namespace eutils::

NCBI_USING_NAMESPACE_STD;
USING_NCBI_SCOPE;
USING_SCOPE(objects);

// destructor
CPubmedArticle::~CPubmedArticle(void)
{
}


BEGIN_LOCAL_NAMESPACE;

template <typename StringT>
void s_ToLower(StringT& str) {
    static const auto& s_Facet = get_ctype_facet<typename StringT::value_type>(locale());
    for (auto& cch : str) {
        cch = s_Facet.tolower(cch);
    }
}


template <typename StringT>
void s_ToUpper(StringT& str, const locale& loc = locale("C")) {
    static const auto& s_Facet = get_ctype_facet<typename StringT::value_type>(locale());
    for (auto& cch : str) {
        cch = s_Facet.toupper(cch);
    }
}


static bool s_StringToInt(const string& str, int& i)
{
    static const auto& s_Facet = get_ctype_facet<char>();
    i = 0;
    if (!all_of(str.begin(), str.end(), [](char cch) -> bool { return s_Facet.is(ctype_base::digit, cch); }))
        return false;
    size_t count;
    i = stoi(str, &count, 10);
    if (count != str.size())
        return false;
    return true;
}


static int s_TranslateMonth(const string& month_str)
{
    typedef initializer_list<pair<int, const char*>> int_string_map;
    static const int_string_map s_MonthTable = {
        { 1, "Jan" }, { 1, "January" },
        { 2, "Feb" }, { 2, "February" },
        { 3, "Mar" }, { 3, "March" },
        { 4, "Apr" }, { 4, "April" },
        { 5, "May" }, { 5, "May" },
        { 6, "Jun" }, { 6, "June" },
        { 7, "Jul" }, { 7, "July" },
        { 8, "Aug" }, { 8, "August" },
        { 9, "Sep" }, { 9, "September" },
        { 10, "Oct" }, { 10, "October" },
        { 11, "Nov" }, { 11, "November" },
        { 12, "Dec" }, { 12, "December" }
    };

    if (month_str.empty()) return 0;
    int ret = 0;
    if (s_StringToInt(month_str, ret)) return ret;
    auto p = find_if(s_MonthTable.begin(), s_MonthTable.end(),
        [&month_str](const pair<int, const char*>& x) -> bool { return NStr::EqualNocase(month_str, x.second); });
    return p == s_MonthTable.end() ? 0 : p->first;
}


template <class container_type, class check_type, class proc_type>
void s_ForeachToken(container_type& container, check_type f, proc_type proc)
{
    auto first = begin(container);
    while (first != end(container))
    {
        if (f(*first))
        {
            auto p = find_if_not(first + 1, end(container), f);
            first = proc(first, p);
        }
        else
            first = find_if(first + 1, end(container), f);
    }
}


static const char* s_UTF8LocaleName = "en_US.UTF-8";

static string wstring_to_utf8(const wstring& str)
{
    typedef codecvt<wchar_t, char, mbstate_t> facet_type;
    locale mylocale(s_UTF8LocaleName);
    const facet_type& myfacet = use_facet<facet_type>(mylocale);
    size_t size = str.size() * myfacet.max_length();
    unique_ptr<char[]> str2(new char[size]);
    mbstate_t mystate = mbstate_t();
    const wchar_t* sptr; char* dptr;
    myfacet.out(mystate, str.c_str(), str.c_str() + str.length(), sptr, str2.get(), str2.get() + size, dptr);
    return string(str2.get(), dptr - str2.get());
}

static wstring utf8_to_wstring(const string& str)
{
    typedef codecvt<wchar_t, char, mbstate_t> facet_type;
    locale mylocale(s_UTF8LocaleName);
    const facet_type& myfacet = use_facet<facet_type>(mylocale);
    size_t size = str.size();
    unique_ptr<wchar_t[]> str2(new wchar_t[size]);
    mbstate_t mystate = mbstate_t();
    const char* sptr; wchar_t* dptr;
    myfacet.in(mystate, str.c_str(), str.c_str() + str.length(), sptr, str2.get(), str2.get() + size, dptr);
    return wstring(str2.get(), dptr - str2.get());
}


static unordered_map<wchar_t, const wchar_t*> s_AsciiConvTable{
    {0x0020, L" "},
    {0x0021, L"!"}, {0x0022, L"\""}, {0x0023, L"#"},
    {0x0024, L"$"}, {0x0025, L"%"}, {0x0026, L"&"}, {0x0027, L"'"},
    {0x0028, L"("}, {0x0029, L")"}, {0x002A, L"*"}, {0x002B, L"+"},
    {0x002C, L","}, {0x002D, L"-"}, {0x002E, L"."}, {0x002F, L"/"},
    {0x0030, L"0"}, {0x0031, L"1"}, {0x0032, L"2"}, {0x0033, L"3"},
    {0x0034, L"4"}, {0x0035, L"5"}, {0x0036, L"6"}, {0x0037, L"7"},
    {0x0038, L"8"}, {0x0039, L"9"}, {0x003A, L":"}, {0x003B, L";"},
    {0x003C, L"<"}, {0x003D, L"="}, {0x003E, L">"}, {0x003F, L"?"},
    {0x0040, L"@"}, {0x0041, L"A"}, {0x0042, L"B"}, {0x0043, L"C"},
    {0x0044, L"D"}, {0x0045, L"E"}, {0x0046, L"F"}, {0x0047, L"G"},
    {0x0048, L"H"}, {0x0049, L"I"}, {0x004A, L"J"}, {0x004B, L"K"},
    {0x004C, L"L"}, {0x004D, L"M"}, {0x004E, L"N"}, {0x004F, L"O"},
    {0x0050, L"P"}, {0x0051, L"Q"}, {0x0052, L"R"}, {0x0053, L"S"},
    {0x0054, L"T"}, {0x0055, L"U"}, {0x0056, L"V"}, {0x0057, L"W"},
    {0x0058, L"X"}, {0x0059, L"Y"}, {0x005A, L"Z"}, {0x005B, L"["},
    {0x005C, L"\\"}, {0x005D, L"]"}, {0x005E, L";"}, {0x005F, L"_"},
    {0x0060, L";"}, {0x0061, L"a"}, {0x0062, L"b"}, {0x0063, L"c"},
    {0x0064, L"d"}, {0x0065, L"e"}, {0x0066, L"f"}, {0x0067, L"g"},
    {0x0068, L"h"}, {0x0069, L"i"}, {0x006A, L"j"}, {0x006B, L"k"},
    {0x006C, L"l"}, {0x006D, L"m"}, {0x006E, L"n"}, {0x006F, L"o"},
    {0x0070, L"p"}, {0x0071, L"q"}, {0x0072, L"r"}, {0x0073, L"s"},
    {0x0074, L"t"}, {0x0075, L"u"}, {0x0076, L"v"}, {0x0077, L"w"},
    {0x0078, L"x"}, {0x0079, L"y"}, {0x007A, L"z"}, {0x007B, L"{"},
    {0x007C, L"|"}, {0x007D, L"}"}, {0x007E, L"~"}, {0x00A0, L" "},
    {0x00A1, L" inverted exclamation mark"}, {0x00A2, L" cent"},
    {0x00A3, L" pound"}, {0x00A4, L" currency"},
    {0x00A5, L" yen"}, {0x00A6, L"|"}, {0x00A7, L" section sign"}, {0x00A8, L" "},
    {0x00A9, L"(c)"}, {0x00AA, L" feminine"}, {0x00AB, L"<<"}, {0x00AC, L" not"},
    {0x00AD, L"-"}, {0x00AE, L"(R)"}, {0x00AF, L" "}, {0x00B0, L" degrees "},
    {0x00B1, L"+/-"}, {0x00B2, L"(2)"}, {0x00B3, L"(3)"}, {0x00B4, L" "},
    {0x00B5, L"micro"}, {0x00B6, L" paragraph sign"}, {0x00B7, L"."}, {0x00B8, L" "},
    {0x00B9, L"(1)"}, {0x00BA, L" masculine"}, {0x00BB, L">>"}, {0x00BC, L"(1/4)"},
    {0x00BD, L"(1/2)"}, {0x00BE, L"(3/4)"},
    {0x00BF, L" inverted question mark"}, {0x00C0, L"A"},
    {0x00C1, L"A"}, {0x00C2, L"A"}, {0x00C3, L"A"}, {0x00C4, L"A"},
    {0x00C5, L"A"}, {0x00C6, L"AE"}, {0x00C7, L"C"}, {0x00C8, L"E"},
    {0x00C9, L"E"}, {0x00CA, L"E"}, {0x00CB, L"E"}, {0x00CC, L"I"},
    {0x00CD, L"I"}, {0x00CE, L"I"}, {0x00CF, L"I"}, {0x00D0, L"Eth"},
    {0x00D1, L"N"}, {0x00D2, L"O"}, {0x00D3, L"O"}, {0x00D4, L"O"},
    {0x00D5, L"O"}, {0x00D6, L"O"}, {0x00D7, L"x"}, {0x00D8, L"O"},
    {0x00D9, L"U"}, {0x00DA, L"U"}, {0x00DB, L"U"}, {0x00DC, L"U"},
    {0x00DD, L"Y"}, {0x00DE, L"Thorn"}, {0x00DF, L"ss"}, {0x00E0, L"a"},
    {0x00E1, L"a"}, {0x00E2, L"a"}, {0x00E3, L"a"}, {0x00E4, L"a"},
    {0x00E5, L"a"}, {0x00E6, L"ae"}, {0x00E7, L"c"}, {0x00E8, L"e"},
    {0x00E9, L"e"}, {0x00EA, L"e"}, {0x00EB, L"e"}, {0x00EC, L"i"},
    {0x00ED, L"i"}, {0x00EE, L"i"}, {0x00EF, L"i"}, {0x00F0, L"eth"},
    {0x00F1, L"n"}, {0x00F2, L"o"}, {0x00F3, L"o"}, {0x00F4, L"o"},
    {0x00F5, L"o"}, {0x00F6, L"o"}, {0x00F7, L"/"}, {0x00F8, L"o"},
    {0x00F9, L"u"}, {0x00FA, L"u"}, {0x00FB, L"u"}, {0x00FC, L"u"},
    {0x00FD, L"y"}, {0x00FE, L"thorn"}, {0x00FF, L"y"}, {0x0100, L"A"},
    {0x0101, L"a"}, {0x0102, L"A"}, {0x0103, L"a"}, {0x0104, L"A"},
    {0x0105, L"a"}, {0x0106, L"C"}, {0x0107, L"c"}, {0x0108, L"C"},
    {0x0109, L"c"}, {0x010A, L"C"}, {0x010B, L"c"}, {0x010C, L"C"},
    {0x010D, L"c"}, {0x010E, L"D"}, {0x010F, L"d"}, {0x0110, L"D"},
    {0x0111, L"d"}, {0x0112, L"E"}, {0x0113, L"e"}, {0x0114, L"E"},
    {0x0115, L"e"}, {0x0116, L"E"}, {0x0117, L"e"}, {0x0118, L"E"},
    {0x0119, L"e"}, {0x011A, L"E"}, {0x011B, L"e"}, {0x011C, L"G"},
    {0x011D, L"g"}, {0x011E, L"G"}, {0x011F, L"g"}, {0x0120, L"G"},
    {0x0121, L"g"}, {0x0122, L"G"}, {0x0123, L"g"}, {0x0124, L"H"},
    {0x0125, L"h"}, {0x0126, L"H"}, {0x0127, L"h"}, {0x0128, L"I"},
    {0x0129, L"ij"}, {0x012A, L"I"}, {0x012B, L"i"}, {0x012C, L"I"},
    {0x012D, L"i"}, {0x012E, L"I"}, {0x012F, L"i"}, {0x0130, L"I"},
    {0x0131, L"i"}, {0x0132, L"IJ"}, {0x0133, L"ij"}, {0x0134, L"J"},
    {0x0135, L"j"}, {0x0136, L"K"}, {0x0137, L"k"}, {0x0138, L"k"},
    {0x0139, L"L"}, {0x013A, L"l"}, {0x013B, L"L"}, {0x013C, L"l"},
    {0x013D, L"L"}, {0x013E, L"l"}, {0x013F, L"L"}, {0x0140, L"l"},
    {0x0141, L"L"}, {0x0142, L"l"}, {0x0143, L"N"}, {0x0144, L"n"},
    {0x0145, L"N"}, {0x0146, L"n"}, {0x0147, L"N"}, {0x0148, L"n"},
    {0x0149, L"n"}, {0x014A, L" ENG"}, {0x014B, L" eng"}, {0x014C, L"O"},
    {0x014D, L"o"}, {0x014E, L"O"}, {0x014F, L"o"}, {0x0150, L"O"},
    {0x0151, L"o"}, {0x0152, L"OE"}, {0x0153, L"oe"}, {0x0154, L"R"},
    {0x0155, L"r"}, {0x0156, L"R"}, {0x0157, L"r"}, {0x0158, L"R"},
    {0x0159, L"r"}, {0x015A, L"S"}, {0x015B, L"s"}, {0x015C, L"S"},
    {0x015D, L"s"}, {0x015E, L"S"}, {0x015F, L"s"}, {0x0160, L"S"},
    {0x0161, L"s"}, {0x0162, L"T"}, {0x0163, L"t"}, {0x0164, L"T"},
    {0x0165, L"t"}, {0x0166, L"T"}, {0x0167, L"t"}, {0x0168, L"U"},
    {0x0169, L"u"}, {0x016A, L"U"}, {0x016B, L"u"}, {0x016C, L"U"},
    {0x016D, L"u"}, {0x016E, L"U"}, {0x016F, L"u"}, {0x0170, L"U"},
    {0x0171, L"u"}, {0x0172, L"U"}, {0x0173, L"u"}, {0x0174, L"W"},
    {0x0175, L"w"}, {0x0176, L"Y"}, {0x0177, L"y"}, {0x0178, L"Y"},
    {0x0179, L"Z"}, {0x017A, L"z"}, {0x017B, L"Z"}, {0x017C, L"z"},
    {0x017D, L"Z"}, {0x017E, L"z"}, {0x0180, L"b"}, {0x0181, L"B"},
    {0x0187, L"C"}, {0x0188, L"c"}, {0x0189, L"D"}, {0x018A, L"D"},
    {0x0190, L"E"}, {0x0191, L"F"}, {0x0192, L"f"}, {0x0193, L"G"},
    {0x0197, L"I"}, {0x0198, L"K"}, {0x0199, L"k"}, {0x019D, L"N"},
    {0x019E, L"n"}, {0x01A0, L"O"}, {0x01A1, L"o"}, {0x01A4, L"P"},
    {0x01A5, L"p"}, {0x01A6, L"R"}, {0x01AB, L"t"}, {0x01AC, L"T"},
    {0x01AD, L"t"}, {0x01AE, L"T"}, {0x01AF, L"U"}, {0x01B0, L"u"},
    {0x01B3, L"Y"}, {0x01B4, L"y"}, {0x01B5, L"Z"}, {0x01B6, L"z"},
    {0x01B7, L"Z"}, {0x01BA, L"z"}, {0x01C3, L"!"}, {0x01C4, L"DZ"},
    {0x01C5, L"Dz"}, {0x01C6, L"dz"}, {0x01C7, L"LJ"}, {0x01C8, L"Lj"},
    {0x01C9, L"lj"}, {0x01CA, L"NJ"}, {0x01CB, L"Nj"}, {0x01CC, L"nj"},
    {0x01CD, L"A"}, {0x01CE, L"a"}, {0x01CF, L"I"}, {0x01D0, L"i"},
    {0x01D1, L"O"}, {0x01D2, L"o"}, {0x01D3, L"U"}, {0x01D4, L"u"},
    {0x01D5, L"U"}, {0x01D6, L"u"}, {0x01D7, L"U"}, {0x01D8, L"u"},
    {0x01D9, L"U"}, {0x01DA, L"u"}, {0x01DB, L"U"}, {0x01DC, L"u"},
    {0x01DE, L"A"}, {0x01DF, L"a"}, {0x01E0, L"A"}, {0x01E1, L"a"},
    {0x01E2, L"AE"}, {0x01E3, L"ae"}, {0x01E4, L"G"}, {0x01E5, L"g"},
    {0x01E6, L"G"}, {0x01E7, L"g"}, {0x01E8, L"K"}, {0x01E9, L"k"},
    {0x01EA, L"O"}, {0x01EB, L"o"}, {0x01EC, L"O"}, {0x01ED, L"o"},
    {0x01EE, L"Z"}, {0x01EF, L"z"}, {0x01F0, L"j"}, {0x01F1, L"DZ"},
    {0x01F2, L"Dz"}, {0x01F3, L"dz"}, {0x01F4, L"G"}, {0x01F5, L"g"},
    {0x01F8, L"N"}, {0x01F9, L"n"}, {0x01FA, L"A"}, {0x01FB, L"a"},
    {0x01FC, L"AE"}, {0x01FD, L"ae"}, {0x01FE, L"O"}, {0x01FF, L"o"},
    {0x0200, L"A"}, {0x0201, L"a"}, {0x0202, L"A"}, {0x0203, L"a"},
    {0x0204, L"E"}, {0x0205, L"e"}, {0x0206, L"E"}, {0x0207, L"e"},
    {0x0208, L"I"}, {0x0209, L"i"}, {0x020A, L"I"}, {0x020B, L"i"},
    {0x020C, L"O"}, {0x020D, L"o"}, {0x020E, L"O"}, {0x020F, L"o"},
    {0x0210, L"R"}, {0x0211, L"r"}, {0x0212, L"R"}, {0x0213, L"r"},
    {0x0214, L"U"}, {0x0215, L"u"}, {0x0216, L"U"}, {0x0217, L"u"},
    {0x0218, L"S"}, {0x0219, L"s"}, {0x021A, L"T"}, {0x021B, L"t"},
    {0x021E, L"H"}, {0x021F, L"h"}, {0x0224, L"Z"}, {0x0225, L"z"},
    {0x0226, L"A"}, {0x0227, L"a"}, {0x0228, L"E"}, {0x0229, L"e"},
    {0x022A, L"O"}, {0x022B, L"o"}, {0x022C, L"O"}, {0x022D, L"o"},
    {0x022E, L"O"}, {0x022F, L"o"}, {0x0230, L"O"}, {0x0231, L"o"},
    {0x0232, L"Y"}, {0x0233, L"y"}, {0x0251, L"a"}, {0x0254, L"open o"},
    {0x0256, L"d"}, {0x0257, L"d"}, {0x025B, L"varepsilon"}, {0x0260, L"g"},
    {0x0261, L"g"}, {0x0262, L"G"}, {0x0266, L"h"}, {0x0267, L"h"},
    {0x0268, L"i"}, {0x0269, L"i"}, {0x026A, L"I"}, {0x0271, L"m"},
    {0x0273, L"n"}, {0x0274, L"N"}, {0x0280, L"R"}, {0x0282, L"s"},
    {0x0288, L"t"}, {0x0289, L"u"}, {0x028F, L"Y"}, {0x0290, L"Z"},
    {0x0291, L"Z"}, {0x0292, L"z"}, {0x0293, L"z"}, {0x0298, L"O"},
    {0x0299, L"B"}, {0x029B, L"G"}, {0x029C, L"H"}, {0x029D, L"j"},
    {0x029F, L"L"}, {0x02A0, L"q"}, {0x02A3, L"dz"}, {0x02A4, L"dz"},
    {0x02A5, L"dz"}, {0x02A6, L"ts"}, {0x02A7, L"ts"}, {0x02A8, L"tc"},
    {0x02A9, L"fn"}, {0x02AA, L"ls"}, {0x02AB, L"lz"}, {0x02AC, L"ww"},
    {0x02B0, L"h"}, {0x02B1, L"h"}, {0x02B2, L"j"}, {0x02B3, L"r"},
    {0x02B7, L"w"}, {0x02B8, L"y"}, {0x02B9, L"'"}, {0x02BA, L"\""},
    {0x02BB, L"'"}, {0x02BC, L"'"}, {0x02BD, L"'"}, {0x02BE, L"'"},
    {0x02BF, L"'"}, {0x02C0, L"?"}, {0x02C1, L"?"}, {0x02C2, L"<"},
    {0x02C3, L">"}, {0x02C4, L"^"}, {0x02C5, L"v"}, {0x02C6, L"^"},
    {0x02C7, L" "}, {0x02C8, L"'"}, {0x02C9, L"-"}, {0x02CA, L"'"},
    {0x02CB, L"`"}, {0x02CC, L"'"}, {0x02CD, L"_"}, {0x02CE, L"'"},
    {0x02CF, L"`"}, {0x02D2, L"'"}, {0x02D3, L"'"}, {0x02D6, L"+"},
    {0x02D7, L"-"}, {0x02D8, L" "}, {0x02D9, L" "}, {0x02DA, L" "},
    {0x02DB, L" "}, {0x02DC, L" "}, {0x02DD, L" "}, {0x02DF, L"x"},
    {0x02F1, L"l"}, {0x02F2, L"s"}, {0x02F3, L"x"}, {0x02FC, L"v"},
    {0x02FD, L"="}, {0x02FE, L"\""}, {0x0386, L"Alpha"}, {0x0388, L"Epsilon"},
    {0x0389, L"Eta"}, {0x038A, L"Iota"}, {0x038C, L"Omicron"}, {0x038E, L"Upsilon"},
    {0x038F, L"Omega"}, {0x0390, L"iota"}, {0x0391, L"Alpha"}, {0x0392, L"Beta"},
    {0x0393, L"Gamma"}, {0x0394, L"Delta"}, {0x0395, L"Epsilon"}, {0x0396, L"Zeta"},
    {0x0397, L"Eta"}, {0x0398, L"Theta"}, {0x0399, L"Iota"}, {0x039A, L"Kappa"},
    {0x039B, L"Lambda"}, {0x039C, L"Mu"}, {0x039D, L"Nu"}, {0x039E, L"Xi"},
    {0x039F, L"Omicron"}, {0x03A0, L"Pi"}, {0x03A1, L"Rho"}, {0x03A3, L"Sigma"},
    {0x03A4, L"Tau"}, {0x03A5, L"Upsilon"}, {0x03A6, L"Phi"}, {0x03A7, L"Chi"},
    {0x03A8, L"Psi"}, {0x03A9, L"Omega"}, {0x03AA, L"Iota"}, {0x03AB, L"Upsilon"},
    {0x03AC, L"alpha"}, {0x03AD, L"epsilon"}, {0x03AE, L"eta"}, {0x03AF, L"iota"},
    {0x03B0, L"upsilon"}, {0x03B1, L"alpha"}, {0x03B2, L"beta"}, {0x03B3, L"gamma"},
    {0x03B4, L"delta"}, {0x03B5, L"epsilon"}, {0x03B6, L"zeta"}, {0x03B7, L"eta"},
    {0x03B8, L"theta"}, {0x03B9, L"iota"}, {0x03BA, L"kappa"}, {0x03BB, L"lambda"},
    // {0x03BC, L"\xCE\xBC"},
    {0x03BC, L"mu"},
    {0x03BD, L"nu"}, {0x03BE, L"xi"},
    {0x03BF, L"omicron"}, {0x03C0, L"pi"}, {0x03C1, L"rho"}, {0x03C2, L"varsigma"},
    {0x03C3, L"sigma"}, {0x03C4, L"tau"}, {0x03C5, L"upsilon"}, {0x03C6, L"phi"},
    {0x03C7, L"chi"}, {0x03C8, L"psi"}, {0x03C9, L"omega"}, {0x03CA, L"iota"},
    {0x03CB, L"upsilon"}, {0x03CC, L"omicron"},
    {0x03CD, L"upsilon"}, {0x03CE, L"omega"},
    {0x03D1, L"vartheta"}, {0x03D2, L"Upsilon"},
    {0x03D5, L"varphi"}, {0x03D6, L"varpi"},
    {0x03DC, L"digamma"}, {0x03DD, L"digamma"},
    {0x03F0, L"varkappa"}, {0x03F1, L"varrho"},
    {0x0401, L"capital IO, Russian"}, {0x0402, L"capital DJE, Serbian"},
    {0x0403, L"capital GJE Macedonian"}, {0x0404, L"capital JE, Ukrainian"},
    {0x0405, L"capital DSE, Macedonian"}, {0x0406, L"capital I, Ukrainian"},
    {0x0407, L"capital YI, Ukrainian"}, {0x0408, L"capital JE, Serbian"},
    {0x0409, L"capital LJE, Serbian"}, {0x040A, L"capital NJE, Serbian"},
    {0x040B, L"capital TSHE, Serbian"}, {0x040C, L"capital KJE, Macedonian"},
    {0x040E, L"capital U, Byelorussian"}, {0x040F, L"capital dze, Serbian"},
    {0x0410, L"capital A, Cyrillic"}, {0x0411, L"capital BE, Cyrillic"},
    {0x0412, L"capital VE, Cyrillic"}, {0x0413, L"capital GHE, Cyrillic"},
    {0x0414, L"capital DE, Cyrillic"}, {0x0415, L"capital IE, Cyrillic"},
    {0x0416, L"capital ZHE, Cyrillic"}, {0x0417, L"capital ZE, Cyrillic"},
    {0x0418, L"capital I, Cyrillic"}, {0x0419, L"capital short I, Cyrillic"},
    {0x041A, L"capital KA, Cyrillic"}, {0x041B, L"capital EL, Cyrillic"},
    {0x041C, L"capital EM, Cyrillic"}, {0x041D, L"capital EN, Cyrillic"},
    {0x041E, L"capital O, Cyrillic"}, {0x041F, L"capital PE, Cyrillic"},
    {0x0420, L"capital ER, Cyrillic"}, {0x0421, L"capital ES, Cyrillic"},
    {0x0422, L"capital TE, Cyrillic"}, {0x0423, L"capital U, Cyrillic"},
    {0x0424, L"capital EF, Cyrillic"}, {0x0425, L"capital HA, Cyrillic"},
    {0x0426, L"capital TSE, Cyrillic"}, {0x0427, L"capital CHE, Cyrillic"},
    {0x0428, L"capital SHA, Cyrillic"}, {0x0429, L"capital SHCHA, Cyrillic"},
    {0x042A, L"capital HARD sign, Cyrillic"}, {0x042B, L"capital YERU, Cyrillic"},
    {0x042C, L"capital SOFT sign, Cyrillic"}, {0x042D, L"capital E, Cyrillic"},
    {0x042E, L"capital YU, Cyrillic"}, {0x042F, L"capital YA, Cyrillic"},
    {0x0430, L"small a, Cyrillic"}, {0x0431, L"small be, Cyrillic"},
    {0x0432, L"small ve, Cyrillic"}, {0x0433, L"small ghe, Cyrillic"},
    {0x0434, L"small de, Cyrillic"}, {0x0435, L"small ie, Cyrillic"},
    {0x0436, L"small zhe, Cyrillic"}, {0x0437, L"small ze, Cyrillic"},
    {0x0438, L"small i, Cyrillic"}, {0x0439, L"small short i, Cyrillic"},
    {0x043A, L"small ka, Cyrillic"}, {0x043B, L"small el, Cyrillic"},
    {0x043C, L"small em, Cyrillic"}, {0x043D, L"small en, Cyrillic"},
    {0x043E, L"small o, Cyrillic"}, {0x043F, L"small pe, Cyrillic"},
    {0x0440, L"small er, Cyrillic"}, {0x0441, L"small es, Cyrillic"},
    {0x0442, L"small te, Cyrillic"}, {0x0443, L"small u, Cyrillic"},
    {0x0444, L"small ef, Cyrillic"}, {0x0445, L"small ha, Cyrillic"},
    {0x0446, L"small tse, Cyrillic"}, {0x0447, L"small che, Cyrillic"},
    {0x0448, L"small sha, Cyrillic"}, {0x0449, L"small shcha, Cyrillic"},
    {0x044A, L"small hard sign, Cyrillic"}, {0x044B, L"small yeru, Cyrillic"},
    {0x044C, L"small soft sign, Cyrillic"}, {0x044D, L"small e, Cyrillic"},
    {0x044E, L"small yu, Cyrillic"}, {0x044F, L"small ya, Cyrillic"},
    {0x0451, L"small io, Russian"}, {0x0452, L"small dje, Serbian"},
    {0x0453, L"small gje, Macedonian"}, {0x0454, L"small je, Ukrainian"},
    {0x0455, L"small dse, Macedonian"}, {0x0456, L"small i, Ukrainian"},
    {0x0457, L"small yi, Ukrainian"}, {0x0458, L"small je, Serbian"},
    {0x0459, L"small lje, Serbian"}, {0x045A, L"small nje, Serbian"},
    {0x045B, L"small tshe, Serbian"}, {0x045C, L"small kje Macedonian"},
    {0x045E, L"small u, Byelorussian"}, {0x045F, L"small dze, Serbian"},
    {0x1E00, L"A"}, {0x1E01, L"a"}, {0x1E02, L"B"}, {0x1E03, L"b"},
    {0x1E04, L"B"}, {0x1E05, L"b"}, {0x1E06, L"B"}, {0x1E07, L"b"},
    {0x1E08, L"C"}, {0x1E09, L"c"}, {0x1E0A, L"D"}, {0x1E0B, L"d"},
    {0x1E0C, L"D"}, {0x1E0D, L"d"}, {0x1E0E, L"D"}, {0x1E0F, L"d"},
    {0x1E10, L"D"}, {0x1E11, L"d"}, {0x1E12, L"D"}, {0x1E13, L"d"},
    {0x1E14, L"E"}, {0x1E15, L"e"}, {0x1E16, L"E"}, {0x1E17, L"e"},
    {0x1E18, L"E"}, {0x1E19, L"e"}, {0x1E1A, L"E"}, {0x1E1B, L"e"},
    {0x1E1C, L"E"}, {0x1E1D, L"e"}, {0x1E1E, L"F"}, {0x1E1F, L"f"},
    {0x1E20, L"G"}, {0x1E21, L"g"}, {0x1E22, L"H"}, {0x1E23, L"h"},
    {0x1E24, L"H"}, {0x1E25, L"h"}, {0x1E26, L"H"}, {0x1E27, L"h"},
    {0x1E28, L"H"}, {0x1E29, L"h"}, {0x1E2A, L"H"}, {0x1E2B, L"h"},
    {0x1E2C, L"I"}, {0x1E2D, L"i"}, {0x1E2E, L"I"}, {0x1E2F, L"i"},
    {0x1E30, L"K"}, {0x1E31, L"k"}, {0x1E32, L"K"}, {0x1E33, L"k"},
    {0x1E34, L"K"}, {0x1E35, L"k"}, {0x1E36, L"L"}, {0x1E37, L"l"},
    {0x1E38, L"L"}, {0x1E39, L"l"}, {0x1E3A, L"L"}, {0x1E3B, L"l"},
    {0x1E3C, L"L"}, {0x1E3D, L"l"}, {0x1E3E, L"M"}, {0x1E3F, L"m"},
    {0x1E40, L"M"}, {0x1E41, L"m"}, {0x1E42, L"M"}, {0x1E43, L"m"},
    {0x1E44, L"N"}, {0x1E45, L"n"}, {0x1E46, L"N"}, {0x1E47, L"n"},
    {0x1E48, L"N"}, {0x1E49, L"n"}, {0x1E4A, L"N"}, {0x1E4B, L"n"},
    {0x1E4C, L"O"}, {0x1E4D, L"o"}, {0x1E4E, L"O"}, {0x1E4F, L"o"},
    {0x1E50, L"O"}, {0x1E51, L"o"}, {0x1E52, L"O"}, {0x1E53, L"o"},
    {0x1E54, L"P"}, {0x1E55, L"p"}, {0x1E56, L"P"}, {0x1E57, L"p"},
    {0x1E58, L"R"}, {0x1E59, L"r"}, {0x1E5A, L"R"}, {0x1E5B, L"r"},
    {0x1E5C, L"R"}, {0x1E5D, L"r"}, {0x1E5E, L"R"}, {0x1E5F, L"r"},
    {0x1E60, L"S"}, {0x1E61, L"s"}, {0x1E62, L"S"}, {0x1E63, L"s"},
    {0x1E64, L"S"}, {0x1E65, L"s"}, {0x1E66, L"S"}, {0x1E67, L"s"},
    {0x1E68, L"S"}, {0x1E69, L"s"}, {0x1E6A, L"T"}, {0x1E6B, L"t"},
    {0x1E6C, L"T"}, {0x1E6D, L"t"}, {0x1E6E, L"T"}, {0x1E6F, L"t"},
    {0x1E70, L"T"}, {0x1E71, L"t"}, {0x1E72, L"U"}, {0x1E73, L"u"},
    {0x1E74, L"U"}, {0x1E75, L"u"}, {0x1E76, L"U"}, {0x1E77, L"u"},
    {0x1E78, L"U"}, {0x1E79, L"u"}, {0x1E7A, L"U"}, {0x1E7B, L"u"},
    {0x1E7C, L"V"}, {0x1E7D, L"v"}, {0x1E7E, L"V"}, {0x1E7F, L"v"},
    {0x1E80, L"W"}, {0x1E81, L"w"}, {0x1E82, L"W"}, {0x1E83, L"w"},
    {0x1E84, L"W"}, {0x1E85, L"w"}, {0x1E86, L"W"}, {0x1E87, L"w"},
    {0x1E88, L"W"}, {0x1E89, L"w"}, {0x1E8A, L"X"}, {0x1E8B, L"x"},
    {0x1E8C, L"X"}, {0x1E8D, L"x"}, {0x1E8E, L"Y"}, {0x1E8F, L"y"},
    {0x1E90, L"Z"}, {0x1E91, L"z"}, {0x1E92, L"Z"}, {0x1E93, L"z"},
    {0x1E94, L"Z"}, {0x1E95, L"z"}, {0x1E96, L"h"}, {0x1E97, L"t"},
    {0x1E98, L"w"}, {0x1E99, L"y"}, {0x1E9A, L"a"}, {0x1E9B, L"f"},
    {0x1EA0, L"A"}, {0x1EA1, L"a"}, {0x1EA2, L"A"}, {0x1EA3, L"a"},
    {0x1EA4, L"A"}, {0x1EA5, L"a"}, {0x1EA6, L"A"}, {0x1EA7, L"a"},
    {0x1EA8, L"A"}, {0x1EA9, L"a"}, {0x1EAA, L"A"}, {0x1EAB, L"a"},
    {0x1EAC, L"A"}, {0x1EAD, L"a"}, {0x1EAE, L"A"}, {0x1EAF, L"a"},
    {0x1EB0, L"A"}, {0x1EB1, L"a"}, {0x1EB2, L"A"}, {0x1EB3, L"a"},
    {0x1EB4, L"A"}, {0x1EB5, L"a"}, {0x1EB6, L"A"}, {0x1EB7, L"a"},
    {0x1EB8, L"E"}, {0x1EB9, L"e"}, {0x1EBA, L"E"}, {0x1EBB, L"e"},
    {0x1EBC, L"E"}, {0x1EBD, L"e"}, {0x1EBE, L"E"}, {0x1EBF, L"e"},
    {0x1EC0, L"E"}, {0x1EC1, L"e"}, {0x1EC2, L"E"}, {0x1EC3, L"e"},
    {0x1EC4, L"E"}, {0x1EC5, L"e"}, {0x1EC6, L"E"}, {0x1EC7, L"e"},
    {0x1EC8, L"I"}, {0x1EC9, L"i"}, {0x1ECA, L"I"}, {0x1ECB, L"i"},
    {0x1ECC, L"O"}, {0x1ECD, L"o"}, {0x1ECE, L"O"}, {0x1ECF, L"o"},
    {0x1ED0, L"O"}, {0x1ED1, L"o"}, {0x1ED2, L"O"}, {0x1ED3, L"o"},
    {0x1ED4, L"O"}, {0x1ED5, L"o"}, {0x1ED6, L"O"}, {0x1ED7, L"o"},
    {0x1ED8, L"O"}, {0x1ED9, L"o"}, {0x1EDA, L"O"}, {0x1EDB, L"o"},
    {0x1EDC, L"O"}, {0x1EDD, L"o"}, {0x1EDE, L"O"}, {0x1EDF, L"o"},
    {0x1EE0, L"O"}, {0x1EE1, L"o"}, {0x1EE2, L"O"}, {0x1EE3, L"o"},
    {0x1EE4, L"U"}, {0x1EE5, L"u"}, {0x1EE6, L"U"}, {0x1EE7, L"u"},
    {0x1EE8, L"U"}, {0x1EE9, L"u"}, {0x1EEA, L"U"}, {0x1EEB, L"u"},
    {0x1EEC, L"U"}, {0x1EED, L"u"}, {0x1EEE, L"U"}, {0x1EEF, L"u"},
    {0x1EF0, L"U"}, {0x1EF1, L"u"}, {0x1EF2, L"Y"}, {0x1EF3, L"y"},
    {0x1EF4, L"Y"}, {0x1EF5, L"y"}, {0x1EF6, L"Y"}, {0x1EF7, L"y"},
    {0x1EF8, L"Y"}, {0x1EF9, L"y"}, {0x2002, L" "}, {0x2003, L" "},
    {0x2004, L" "}, {0x2005, L" "}, {0x2007, L" "}, {0x2008, L" "},
    {0x2009, L" "}, {0x200A, L" "}, {0x2010, L"-"}, {0x2013, L"-"},
    {0x2014, L"-"}, {0x2015, L"-"}, {0x2016, L" ||"}, {0x2018, L"'"},
    {0x2019, L"'"}, {0x201A, L"'"}, {0x201C, L"\""}, {0x201D, L"\""},
    {0x201E, L"\""}, {0x2020, L"dagger"}, {0x2021, L"double dagger"}, {0x2022, L"*"},
    {0x2025, L".."}, {0x2026, L"..."},
    {0x2030, L" per thousand"}, {0x2031, L"per 10 thousand"},
    {0x2032, L"'"}, {0x2033, L"''"}, {0x2034, L"'''"}, {0x2035, L"'"},
    {0x2041, L"insertion mark"}, {0x2043, L" rectangle"},
    // JIRA: PM-989
    {0x2070, L"(0)"}, {0x2071, L"(i)"}, {0x2074, L"(4)"}, {0x2075, L"(5)"},
    {0x2076, L"(6)"}, {0x2077, L"(7)"}, {0x2078, L"(8)"}, {0x2079, L"(9)"},
    {0x207A, L"(+)"}, {0x207B, L"(-)"}, {0x207C, L"(=)"}, {0x207D, L"(()"},
    {0x207E, L"())"}, {0x207F, L"(n)"},
    {0x2080, L"(0)"}, {0x2081, L"(1)"}, {0x2082, L"(2)"}, {0x2083, L"(3)"},
    {0x2084, L"(4)"}, {0x2085, L"(5)"}, {0x2086, L"(6)"}, {0x2087, L"(7)"},
    {0x2088, L"(8)"}, {0x2089, L"(9)"}, {0x208A, L"(+)"}, {0x208B, L"(-)"},
    {0x208C, L"(=)"}, {0x208D, L"(()"}, {0x208E, L"())"},
    {0x2090, L"(a)"}, {0x2091, L"(e)"}, {0x2092, L"(o)"}, {0x2093, L"(x)"},
    {0x2095, L"(h)"}, {0x2096, L"(k)"}, {0x2097, L"(l)"},
    {0x2098, L"(m)"}, {0x2099, L"(n)"}, {0x209A, L"(p)"}, {0x209B, L"(s)"},
    {0x209C, L"(t)"},
    // END JIRA: PM-989
    {0x20AC, L"euro"},
    {0x20DB, L"..."}, {0x20DC, L"Dot;"},
    {0x2102, L"C"}, {0x2105, L"in-care-of"}, {0x210B, L"H"}, {0x210C, L"H"},
    {0x210F, L"variant Planck's over 2pi"}, {0x2110, L"I"},
    {0x2111, L" imaginary"}, {0x2112, L" Lgrangian "},
    {0x2113, L"l"}, {0x2115, L"N"},
    {0x2116, L"numero sign"}, {0x2117, L"sound recording copyright sign"},
    {0x2118, L"Weierstrass p"}, {0x2119, L"P"}, {0x211A, L"Q"}, {0x211C, L"Re"},
    {0x211D, L"R"}, {0x211E, L"Rx"}, {0x2122, L""}, {0x2124, L"Z"},
    {0x2126, L" ohm"}, {0x2127, L"conductance"},
    {0x2129, L"inverted iota"}, {0x212B, L"A"},
    {0x212C, L" Bernoulli function"}, {0x212F, L"e"}, {0x2130, L"E"}, {0x2131, L"F"},
    {0x2133, L"M"}, {0x2134, L"o"}, {0x2135, L"aleph"}, {0x2136, L" beth"},
    {0x2137, L"gimel"}, {0x2138, L" daleth"}, {0x2153, L"(1/3)"}, {0x2154, L"(2/3)"},
    {0x2155, L"(1/5)"}, {0x2156, L"(2/5)"}, {0x2157, L"(3/5)"}, {0x2158, L"(4/5)"},
    {0x2159, L"(1/6)"}, {0x215A, L"(5/6)"}, {0x215B, L"(1/8)"}, {0x215C, L"(3/8)"},
    {0x215D, L"(5/8)"}, {0x215E, L"(7/8)"},
    {0x2190, L"<--"}, {0x2191, L" upward arrow"},
    {0x2192, L"-->"}, {0x2193, L" downward arrow"},
    {0x2194, L"<-->"}, {0x2195, L"up and down arrow "},
    {0x2196, L"NW pointing arrow "}, {0x2197, L"nearrow "},
    {0x2198, L"SE pointing arrow"}, {0x2199, L"SW pointing arrow"},
    {0x219A, L"not left arrow "}, {0x219B, L"not right arrow "},
    {0x219E, L"two head left arrow"}, {0x219F, L"up two-headed arrow"},
    {0x21A0, L"two head right arrow"}, {0x21A1, L"down two-headed arrow"},
    {0x21A2, L"left arrow-tailed "}, {0x21A3, L"right arrow-tailed"},
    {0x21A6, L"mapsto"}, {0x21A9, L"left arrow-hooked "},
    {0x21AA, L"right arrow-hooked "}, {0x21AB, L"left arrow-looped "},
    {0x21AC, L"right arrow-looped "}, {0x21AD, L"left and right squig arrow "},
    {0x21AE, L"not l&r arrow "}, {0x21B0, L"Lsh"},
    {0x21B1, L"Rsh"}, {0x21B2, L"left down angled arrow"},
    {0x21B3, L"right down angled arrow"}, {0x21B6, L"left curved arrow "},
    {0x21B7, L"right curved arrow "}, {0x21BA, L"left arrow in circle "},
    {0x21BB, L"right arrow in circle "}, {0x21BC, L"left harpoon-up "},
    {0x21BD, L"left harpoon-down "}, {0x21BE, L"up harp-right"},
    {0x21BF, L"up harpoon-left "}, {0x21C0, L"right harpoon-up "},
    {0x21C1, L"right harpoon-down "}, {0x21C2, L"down harpoon-right "},
    {0x21C3, L"down harpoon-left "}, {0x21C4, L"right arrow over left arrow"},
    {0x21C5, L"up arrow, down arrow "}, {0x21C6, L"left arrow over right arrow"},
    {0x21C7, L"two left arrows"}, {0x21C8, L"two up arrows"},
    {0x21C9, L"two right arrows"}, {0x21CA, L"two down arrows"},
    {0x21CB, L"left harpoon over right harpoon"}, {0x21CC, L"right harpoon over left harpoon"},
    {0x21CD, L"not implied by"}, {0x21CE, L"not l&r dbl arr "},
    {0x21CF, L"not implies"}, {0x21D0, L"<--"},
    {0x21D1, L"up dbl arrow "}, {0x21D2, L"-->"},
    {0x21D3, L"down double arrow "}, {0x21D4, L"<-->"},
    {0x21D5, L"up and down dbl arrow "}, {0x21D6, L"NW pointing dbl arrow"},
    {0x21D7, L"NE pointing double arrow"}, {0x21D8, L"SE pointing double arrow"},
    {0x21D9, L"SW pointing dbl arrow"}, {0x21DA, L"left triple arrow "},
    {0x21DB, L"right triple arrow "}, {0x21DD, L"right arrow-wavy"},
    {0x2200, L" for all"}, {0x2201, L" complement"},
    {0x2202, L" partial differential"}, {0x2203, L" exists"},
    {0x2204, L"negated exists"}, {0x2205, L"slashed circle"},
    {0x2207, L"nabla"}, {0x2208, L"in"},
    {0x2209, L" negated set membership"}, {0x220B, L"contains"},
    {0x220C, L"negated contains, variant"}, {0x220F, L" product operator"},
    {0x2210, L" coproduct operator"}, {0x2211, L" summation operator"},
    {0x2212, L"-"}, {0x2213, L"-/+"},
    {0x2214, L" plus sign, dot above"}, {0x2216, L"\\"},
    {0x2217, L" *"}, {0x2218, L" composite function"},
    {0x221A, L" radical"}, {0x221D, L" proportional, variant"},
    {0x221E, L"infinity"}, {0x221F, L"right (90 degree) angle"},
    {0x2220, L" angle"}, {0x2221, L" measured angle"},
    {0x2222, L"angle-spherical"}, {0x2223, L"mid R:"},
    {0x2224, L" nmid"}, {0x2225, L" parallel"},
    {0x2226, L" not parallel"}, {0x2227, L"wedge"},
    {0x2228, L" logical or"}, {0x2229, L" intersection"},
    {0x222A, L" union or logical sum"}, {0x222B, L"integral"},
    {0x222C, L"double integral operator"}, {0x222D, L"triple integral"},
    {0x222E, L" contour integral operator"}, {0x222F, L"double contour integral operator"},
    {0x2230, L"triple contour integral operator"}, {0x2231, L"clockwise integral"},
    {0x2232, L"contour integral, clockwise"}, {0x2233, L"contour integral, anti-clockwise"},
    {0x2234, L" therefore"}, {0x2235, L" because"},
    {0x2236, L"ratio"}, {0x2237, L"Colon, two colons"},
    {0x2238, L"minus sign, dot above"}, {0x223A, L"minus with four dots, geometric properties"},
    {0x223B, L"homothetic"}, {0x223C, L" approximately "},
    {0x223D, L" reverse similar"}, {0x223E, L"most positive"},
    {0x2240, L" wreath product"}, {0x2241, L" not similar"},
    {0x2242, L"equals, similar"}, {0x2243, L" approximately "},
    {0x2244, L" not similar, equals"}, {0x2245, L" congruent with"},
    {0x2246, L"similar, not equals"}, {0x2247, L" not congruent with"},
    {0x2248, L" approximately "}, {0x2249, L" not approximate"},
    {0x224A, L"approximate, equals"}, {0x224B, L"approximately identical to"},
    {0x224C, L" everse congruent"}, {0x224D, L" asymptotically equal to"},
    {0x224E, L" bumpy equals"}, {0x224F, L" bumpy equals, equals"},
    {0x2250, L"equals, single dot above"}, {0x2251, L"=..."},
    {0x2252, L" falling dots"}, {0x2253, L" rising dots"},
    {0x2254, L":="}, {0x2255, L"=:"},
    {0x2256, L" circle on equals sign"}, {0x2257, L"o="},
    {0x2259, L" wedge"}, {0x225A, L"logical or, equals"},
    {0x225B, L"equal, asterisk above"}, {0x225C, L" triangle, equals"},
    {0x225F, L"equal with questionmark"}, {0x2260, L" not equal"},
    {0x2261, L" identical with"}, {0x2262, L" not identical with"},
    {0x2264, L"</="}, {0x2265, L">/="},
    {0x2266, L"<=="}, {0x2267, L">=="},
    {0x2268, L" less, not double equals"}, {0x2269, L" greater, not dbl equals"},
    {0x226A, L"<<"}, {0x226B, L">>"},
    {0x226C, L" between"}, {0x226E, L" not less-than"},
    {0x226F, L"not greater-than"}, {0x2270, L" not less, dbl equals"},
    {0x2271, L"not gt-or-eq, slanted"}, {0x2272, L" less, similar"},
    {0x2273, L" greater, similar"}, {0x2274, L"not less, similar"},
    {0x2275, L"not greater, similar"}, {0x2276, L"<>"},
    {0x2277, L"><"}, {0x2278, L"not less, greater"},
    {0x2279, L"not greater, less"}, {0x227A, L" precedes"},
    {0x227B, L" succeeds"}, {0x227C, L"precedes, curly equals"},
    {0x227D, L" succeeds, equals"}, {0x227E, L" similar"},
    {0x227F, L" succeeds, similar"}, {0x2280, L" not precedes"},
    {0x2281, L" not succeeds"}, {0x2282, L" subset"},
    {0x2283, L" superset"}, {0x2284, L"not subset"},
    {0x2285, L" not superset"}, {0x2286, L" subset, dbl equals"},
    {0x2287, L" superset, dbl equals"}, {0x2288, L" not subset, dbl eq"},
    {0x2289, L" not superset, equals"}, {0x228A, L" subset, not equals"},
    {0x228B, L" superset, not dbl eq"}, {0x228D, L"union, with dot"},
    {0x228E, L" plus sign in union"}, {0x228F, L" square subset"},
    {0x2290, L" square superset"}, {0x2291, L" square subset, equals"},
    {0x2292, L" square superset, eq"}, {0x2293, L" square intersection"},
    {0x2294, L"square union"}, {0x2295, L" plus sign in circle"},
    {0x2296, L" minus sign in circle"}, {0x2297, L"multiply sign in circle"},
    {0x2298, L" solidus in circle"}, {0x2299, L"middle dot in circle"},
    {0x229A, L" open dot in circle"}, {0x229B, L" asterisk in circle"},
    {0x229D, L" hyphen in circle"}, {0x229E, L" plus sign in box"},
    {0x229F, L" minus sign in box"}, {0x22A0, L" multiply sign in box"},
    {0x22A1, L" small dot in box"}, {0x22A2, L" vertical, dash"},
    {0x22A3, L" dash, vertical"}, {0x22A4, L" inverted perpendicular"},
    {0x22A5, L" perpendicular"}, {0x22A7, L"models R:"},
    {0x22A8, L" vertical, dbl dash"}, {0x22A9, L" dbl vertical, dash"},
    {0x22AA, L" triple vertical, dash"}, {0x22AB, L"dbl vertical, dbl dash"},
    {0x22AC, L" not vertical, dash"}, {0x22AD, L" not vertical, dbl dash"},
    {0x22AE, L" not dbl vertical, dash"}, {0x22AF, L" not dbl vert, dbl dash"},
    {0x22B0, L"element precedes under relation"}, {0x22B2, L" left tri, open, var"},
    {0x22B3, L" right tri, open, var"}, {0x22B4, L" left triangle, eq"},
    {0x22B5, L" right tri, eq"}, {0x22B6, L"original of"},
    {0x22B7, L"image of"}, {0x22B8, L"multimap"},
    {0x22B9, L"hermitian conjugate matrix"}, {0x22BA, L" intercal"},
    {0x22BB, L" logical or, bar below"}, {0x22BC, L" logical and, bar above"},
    {0x22BD, L"bar, vee"}, {0x22BE, L"right angle, variant"},
    {0x22C0, L"logical or operator"}, {0x22C1, L"logical and operator"},
    {0x22C2, L"intersection operator"}, {0x22C3, L"union operator"},
    {0x22C4, L" open diamond"}, {0x22C6, L" small star, filled"},
    {0x22C7, L" division on times"}, {0x22C8, L" bowtie R"},
    {0x22C9, L" times sign, left closed"}, {0x22CA, L" times sign, right closed"},
    {0x22CB, L" leftthreetimes"}, {0x22CC, L" rightthreetimes "},
    {0x22CD, L" reverse similar"}, {0x22CE, L" curly logical or"},
    {0x22CF, L" curly logical and"}, {0x22D0, L" double subset"},
    {0x22D1, L" dbl superset"}, {0x22D2, L" dbl intersection"},
    {0x22D3, L" dbl union"}, {0x22D4, L" pitchfork"},
    {0x22D5, L"equal or parallel"}, {0x22D6, L"less than, with dot"},
    {0x22D7, L"greater than, with dot"}, {0x22D8, L"<<<"},
    {0x22D9, L">>>"}, {0x22DA, L"<=>"}, {0x22DB, L">=<"}, {0x22DC, L"=/<"},
    {0x22DD, L"=/>"}, {0x22DE, L" precedes"},
    {0x22DF, L" succeeds"}, {0x22E6, L" less, not similar"},
    {0x22E7, L" greater, not similar"}, {0x22E8, L" precedes, not approx"},
    {0x22E9, L" succeeds, not approx"}, {0x22EA, L" not left triangle"},
    {0x22EB, L" not rt triangle"}, {0x22EC, L" not l tri, eq"},
    {0x22ED, L" not r tri, eq"}, {0x22EE, L" vertical ellipsis"},
    {0x22EF, L"cdots, three dots, centered"}, {0x22F0, L"three dots, ascending"},
    {0x22F1, L"ddots, three dots, descending"}, {0x2306, L" log and, dbl bar"},
    {0x2308, L" left ceiling"}, {0x2309, L" right ceiling"},
    {0x230A, L" left floor"}, {0x230B, L" right floor"},
    {0x230C, L"downward right crop mark "}, {0x230D, L"downward left crop mark "},
    {0x230E, L"upward right crop mark "}, {0x230F, L"upward left crop mark "},
    {0x2310, L"reverse not"}, {0x2312, L"profile of a line"},
    {0x2313, L"profile of a surface"}, {0x2315, L"telephone recorder symbol"},
    {0x2316, L"register mark or target"}, {0x231C, L" upper left corner"},
    {0x231D, L" upper right corner"}, {0x231E, L" downward left corner"},
    {0x231F, L" downward right corner"}, {0x2322, L" down curve"},
    {0x2323, L" up curve"}, {0x232D, L"cylindricity"},
    {0x232E, L"all-around profile"}, {0x2336, L"top and bottom"},
    {0x2423, L" "}, {0x244A, L"\\"},
    {0x2460, L"1 in circle"}, {0x2461, L"2 in circle"},
    {0x2462, L"3 in circle"}, {0x2463, L"4 in circle"},
    {0x24C8, L"S in circle"}, {0x2500, L" horizontal line "},
    {0x2502, L" vertical line"}, {0x250C, L" lower right quadrant"},
    {0x2510, L" lower left quadrant"}, {0x2514, L" upper right quadrant"},
    {0x2518, L" upper left quadrant"}, {0x251C, L" upper and lower right quadrants"},
    {0x2524, L" upper and lower left quadrants"}, {0x252C, L" lower left and right quadrants"},
    {0x2534, L" upper left and right quadrants"}, {0x253C, L" all four quadrants"},
    {0x2550, L" horizontal line"}, {0x2551, L" vertical line"},
    {0x2552, L" lower right quadrant"}, {0x2553, L" lower right quadrant"},
    {0x2554, L" lower right quadrant"}, {0x2555, L" lower left quadrant"},
    {0x2556, L" lower left quadrant"}, {0x2557, L" lower left quadrant"},
    {0x2558, L" upper right quadrant"}, {0x2559, L" upper right quadrant"},
    {0x255A, L" upper right quadrant"}, {0x255B, L" upper left quadrant"},
    {0x255C, L" upper left quadrant"}, {0x255D, L" upper left quadrant"},
    {0x255E, L" upper and lower right quadrants"}, {0x255F, L" upper and lower right quadrants"},
    {0x2560, L" upper and lower right quadrants"}, {0x2561, L" upper and lower left quadrants"},
    {0x2562, L" upper and lower left quadrants"}, {0x2563, L" upper and lower left quadrants"},
    {0x2564, L" lower left and right quadrants"}, {0x2565, L" lower left and right quadrants"},
    {0x2566, L" lower left and right quadrants"}, {0x2567, L" upper left and right quadrants"},
    {0x2568, L" upper left and right quadrants"}, {0x2569, L" upper left and right quadrants"},
    {0x256A, L" all four quadrants"}, {0x256B, L" all four quadrants"},
    {0x256C, L" all four quadrants"}, {0x2580, L"upper half block"},
    {0x2584, L"lower half block"}, {0x2588, L"full block"},
    {0x2591, L"25% shaded block"}, {0x2592, L"50% shaded block"},
    {0x2593, L"75% shaded block"}, {0x25A1, L" square"},
    {0x25AA, L"blacksquare, square, filled"}, {0x25AD, L"rectangle"},
    {0x25AE, L"histogram marker"}, {0x25B3, L" big up tri, open"},
    {0x25B4, L"black triangle"}, {0x25B5, L"triangle up"},
    {0x25B8, L"black triangle right"}, {0x25B9, L" triangle right"},
    {0x25BD, L" big dn tri, open"}, {0x25BE, L"black triangle down"},
    {0x25BF, L"triangle down"}, {0x25C2, L"black triangle left"},
    {0x25C3, L" triangle left"}, {0x25CA, L" lozenge"},
    {0x25CB, L"o"}, {0x25EC, L"dot in triangle"},
    {0x25EF, L" large circle"}, {0x2605, L" bigstar"},
    {0x260E, L"telephone symbol"}, {0x2640, L"female symbol"},
    {0x2642, L"male symbol"}, {0x2660, L"spades"},
    {0x2661, L"heart"}, {0x2663, L"club suit symbol"},
    {0x2666, L"diamond"}, {0x266A, L"music note"},
    {0x266D, L"musical flat"}, {0x266E, L" music natural"},
    {0x266F, L"musical sharp"}, {0x2713, L"check mark"},
    {0x2717, L"ballot cross"}, {0x2720, L"maltese cross"},
    {0x2736, L"sextile"}, {0x3008, L"<"},
    {0x3009, L">"}, {0x300A, L"left angle bracket, double"},
    {0x300B, L"right angle bracket, double"}, {0x3014, L"left broken bracket"},
    {0x3015, L"right broken bracket"}, {0x3018, L"left open angular bracket"},
    {0x3019, L"right open angular bracket"}, {0x301A, L"left open bracket"},
    {0x301B, L"right open bracket"}, {0xE000, L"slashed integral"},
    {0xE001, L"square with times sign"}, {0xE002, L"square"},
    {0xE003, L"square"}, {0xE004, L"square"},
    {0xE005, L"white square"}, {0xE006, L"white square"},
    {0xE007, L"white square"}, {0xE008, L"white square"},
    {0xE009, L"striped box"}, {0xE00A, L"filled semicircle"},
    {0xE00B, L"3 asterisks"}, {0xE00C, L"circle"},
    {0xE00D, L"up arrow"}, {0xE00E, L"slashed line"},
    {0xE00F, L"slashed line"}, {0xE010, L"striped box"},
    {0xE011, L"double ended arrow"}, {0xE012, L"^^^"},
    {0xE013, L"left arrowhead"}, {0xE014, L"down arrowhead"},
    {0xE015, L"left arrowhead"}, {0xE016, L"up arrowhead"},
    {0xE017, L"down arrow"}, {0xE018, L"bond"},
    {0xE019, L"double bond"}, {0xE01A, L"triple bond"},
    {0xE01B, L"=="}, {0xE01D, L"bardot"},
    {0xE01E, L"diamond with dot"}, {0xE01F, L"hourglass"},
    {0xE020, L"slashed lambda"}, {0xE021, L"white octagon"},
    {0xE022, L"octagon"}, {0xE023, L"circle"},
    {0xE024, L"upper semicircle"}, {0xE025, L"bottom semicircle"},
    {0xE026, L"box with dots"}, {0xE027, L"box with crosscheck"},
    {0xE028, L"striped box"}, {0xE029, L"triangle with dots"},
    {0xE02A, L"striped box"}, {0xE02B, L"box with dots"},
    {0xE02C, L"box with dots"}, {0xE02D, L"gray box"},
    {0xE02E, L"striped box"}, {0xE02F, L"striped box"},
    {0xE030, L"striped box"}, {0xE031, L"circle with dots"},
    {0xE032, L"striped circle"}, {0xE033, L"bold circle"},
    {0xE034, L"striped box"}, {0xE036, L"1 in circle"},
    {0xE037, L"2 in circle"}, {0xE038, L"3 in circle"},
    {0xE039, L"4 in circle"}, {0xE03A, L"5 in circle"},
    {0xE03B, L"heavy cross"}, {0xE03C, L"6-point star"},
    {0xE03D, L"5-point star"}, {0xE03E, L"5-point star"},
    {0xE03F, L"right arrow"}, {0xE040, L"right arrowhead"},
    {0xE041, L"heavy x"}, {0xE042, L"6-point star"},
    {0xE043, L"*"}, {0xE044, L"*"}, {0xE045, L"right arrowhead"}, {0xE046, L"cross"},
    {0xE047, L"*"}, {0xE048, L"right arrow"},
    {0xE049, L"right arrow"}, {0xE04A, L"right arrow"},
    {0xE04B, L"right arrow"}, {0xE04C, L"pentagon"},
    {0xE04D, L"plank's constant"}, {0xE04F, L"chempt"},
    {0xE051, L"circle"}, {0xE05C, L"vector"}, {0xE05D, L"h"}, {0xE05E, L".."},
    {0xE05F, L"k"}, {0xE063, L"outline cross"},
    {0xE065, L"up arrowhead"}, {0xE066, L"solid bar"},
    {0xE067, L"scissor"}, {0xE068, L"triangle"},
    {0xE069, L"diamond"}, {0xE06A, L"circle"},
    {0xE06B, L"diamond"}, {0xE06C, L"L"},
    {0xE200, L"long left double arrow "}, {0xE201, L"long left arrow"},
    {0xE202, L"long left and right double arrow"}, {0xE203, L"long left and right arrow "},
    {0xE204, L"long right double arrow "}, {0xE205, L"long right arrow"},
    {0xE206, L"left double broken arrow"}, {0xE207, L"right doubly broken arrow"},
    {0xE208, L"long mapsto"}, {0xE209, L"two-headed right broken arrow"},
    {0xE20A, L"SW arrow-hooked"}, {0xE20B, L"SE arrow-hooken"},
    {0xE20C, L"NW arrow-hooked"}, {0xE20D, L"NE arrow-hooked"},
    {0xE20E, L"NE/SE arrows"}, {0xE20F, L"SE/SW arrows"},
    {0xE210, L"SW/NW arrows"}, {0xE211, L"NW/NE arrows"},
    {0xE212, L"two-headed mapsto"}, {0xE214, L"left fish tail"},
    {0xE215, L"right fish tail"}, {0xE216, L"down arrow, up arrow "},
    {0xE217, L"down harpoon, up harpoon "}, {0xE218, L"up harp, down harp "},
    {0xE219, L"right down curved arrow"}, {0xE21A, L"left down curved arrow"},
    {0xE21B, L"not right arrow-wavy"}, {0xE21C, L"right arrow-curved"},
    {0xE21D, L"not right arrow-curved"}, {0xE21E, L"right arrow, plus "},
    {0xE220, L"left arrow-bar, filled square "}, {0xE221, L"right arrow-bar, filled square "},
    {0xE222, L"left arrow, filled square "}, {0xE223, L"right arrow, filled square"},
    {0xE224, L"right harpoon-up over right harpoon-down"}, {0xE225, L"left harpoon-up over left harpoon-down"},
    {0xE226, L"up harpoon-left, up harpoon-right "}, {0xE227, L"down harpoon-left, down harpoon-right "},
    {0xE228, L"left-down, right-up harpoon "}, {0xE229, L"left-up-right-down harpoon"},
    {0xE22A, L"right harpoon-up over left harpoon-up"}, {0xE22B, L"left harpoon-up over right harpoon-up"},
    {0xE22C, L"left harpoon-down over right harpoon-down"}, {0xE22D, L"right harpoon-down over left harpoon-down"},
    {0xE22E, L"left harpoon-up over long dash"}, {0xE22F, L"right harpoon-down below long dash"},
    {0xE230, L"right harpoon-up over long dash"}, {0xE231, L"left harpoon-down below long dash"},
    {0xE232, L"short right arrow"}, {0xE233, L"short left arrow"},
    {0xE234, L"similar, right arrow below "}, {0xE235, L"approximate, right arrow above "},
    {0xE236, L"equal, right arrow below "}, {0xE237, L"up two-headed arrow above circle"},
    {0xE238, L"right arrow with dotted stem"}, {0xE239, L"right two-headed arrow with tail"},
    {0xE23B, L"right double arrow-tail"}, {0xE23C, L"left arrow-tail"},
    {0xE23D, L"left double arrow-tail"}, {0xE23E, L"left, curved, down arrow "},
    {0xE23F, L"left arrow, plus "}, {0xE240, L"left and right arrow with a circle"},
    {0xE241, L"right open arrow"}, {0xE242, L"left open arrow"},
    {0xE243, L"horizontal open arrow"}, {0xE244, L"right zig-zag arrow"},
    {0xE248, L"angle with down zig-zag arrow"}, {0xE249, L"curved right arrow with minus"},
    {0xE24A, L"curved left arrow with plus"}, {0xE24B, L"up fish tail"},
    {0xE24C, L"down fish tail"}, {0xE24D, L"right arrow, similar "},
    {0xE24E, L"left arrow, similar "}, {0xE24F, L"mid, circle below "},
    {0xE250, L"circle, mid below "}, {0xE251, L" amalgamation or coproduct"},
    {0xE259, L"intprod"}, {0xE25A, L"plus sign, dot below"},
    {0xE25B, L"minus sign, dot below"}, {0xE25C, L"plus sign in left half circle"},
    {0xE25D, L"plus sign in right half circle"}, {0xE25E, L"multiply sign in left half circle "},
    {0xE25F, L"multiply sign in right half circle"}, {0xE260, L"circle with horizontal bar"},
    {0xE261, L"intersection, with dot"}, {0xE262, L"subset, with dot"},
    {0xE263, L"superset, with dot"}, {0xE264, L"smash product"},
    {0xE265, L"wedge, bar below"}, {0xE266, L"plus, small circle above"},
    {0xE267, L"plus, equals"}, {0xE268, L"equal, plus"},
    {0xE269, L"plus, two; Nim-addition"}, {0xE26A, L"plus, circumflex accent above"},
    {0xE26B, L"plus, similar above"}, {0xE26C, L"plus, similar below"},
    {0xE26D, L"times, dot"}, {0xE26E, L"union above intersection"},
    {0xE26F, L"intersection above union"}, {0xE270, L"union, bar, intersection"},
    {0xE271, L"intersection, bar, union"}, {0xE272, L"union, union, joined"},
    {0xE273, L"intersection, intersection, joined"}, {0xE274, L"union, serifs"},
    {0xE275, L"intersection, serifs"}, {0xE276, L"square union, serifs"},
    {0xE277, L"square intersection, serifs"}, {0xE278, L"closed union, serifs"},
    {0xE279, L"closed intersection, serifs"}, {0xE27A, L"closed union, serifs, smash product"},
    {0xE27B, L"plus in triangle"}, {0xE27C, L"minus in triangle"},
    {0xE27D, L"multiply in triangle"}, {0xE27E, L"triangle, serifs at bottom"},
    {0xE27F, L"slash in square"}, {0xE280, L"reverse solidus in square"},
    {0xE281, L"intersection, and"}, {0xE282, L"union, or"},
    {0xE283, L"bar, union"}, {0xE284, L"bar, intersection"},
    {0xE285, L"divide in circle"}, {0xE286, L"dot, solidus, dot in circle"},
    {0xE287, L"filled circle in circle"}, {0xE288, L"less-than in circle"},
    {0xE289, L"greater-than in circle"}, {0xE28A, L"parallel in circle"},
    {0xE28B, L"perpendicular in circle"}, {0xE28C, L"multiply sign in double circle"},
    {0xE28D, L"multiply sign in circle, circumflex accent"}, {0xE28E, L"multiply sign, bar below"},
    {0xE290, L"most positive, two lines below"}, {0xE291, L" right paren, gt"},
    {0xE292, L"left parenthesis, lt"}, {0xE293, L"rmoustache"},
    {0xE294, L"lmoustache"}, {0xE295, L"dbl right parenthesis, less"},
    {0xE296, L"dbl left parenthesis, greater"}, {0xE297, L"left angle, dot"},
    {0xE298, L"right angle, dot"}, {0xE299, L"left bracket, equal"},
    {0xE29A, L"right bracket, equal"}, {0xE29B, L"left bracket, solidus top corner"},
    {0xE29C, L"right bracket, solidus bottom corner"}, {0xE29D, L"left bracket, solidus bottom corner"},
    {0xE29E, L"right bracket, solidus top corner"}, {0xE29F, L"greater, not approximate"},
    {0xE2A1, L" gt, vert, not dbl eq"}, {0xE2A2, L" less, not approximate"},
    {0xE2A4, L" less, vert, not dbl eq"}, {0xE2A6, L" not greater-than-or-equal"},
    {0xE2A7, L" not less-than-or-equal"}, {0xE2AA, L" nshortmid"},
    {0xE2AB, L" not short par"}, {0xE2B3, L" precedes, not dbl eq"},
    {0xE2B5, L" succeeds, not dbl eq"}, {0xE2B8, L" subset not dbl eq, var"},
    {0xE2B9, L" subset, not eq, var"}, {0xE2BA, L" superset, not eq, var"},
    {0xE2BB, L" super not dbl eq, var"}, {0xE2BC, L"not approximately identical to"},
    {0xE2C5, L"not congruent, dot"}, {0xE2C6, L"not, vert, approximate"},
    {0xE2C7, L"not approximately equal or equal to"}, {0xE2C8, L"parallel, similar"},
    {0xE2C9, L"not, vert, much less than"}, {0xE2CA, L"not, vert, much greater than"},
    {0xE2CB, L"not much less than, variant"}, {0xE2CC, L"not much greater than, variant"},
    {0xE2CD, L"not triple less than"}, {0xE2CE, L"not triple greater than"},
    {0xE2CF, L"not, vert, right triangle, equals"}, {0xE2D0, L"not, vert, left triangle, equals"},
    {0xE2D1, L"reverse nmid"}, {0xE2D4, L"j"},
    {0xE2D5, L"Planck's over 2pi"}, {0xE2D6, L"angle, equal"},
    {0xE2D7, L"reverse angle, equal"}, {0xE2D8, L"not, vert, angle"},
    {0xE2D9, L"angle-measured, arrow, up, right"}, {0xE2DA, L"angle-measured, arrow, up, left"},
    {0xE2DB, L"angle-measured, arrow, down, right"}, {0xE2DC, L"angle-measured, arrow, down, left"},
    {0xE2DD, L"angle-measured, arrow, right, up"}, {0xE2DE, L"angle-measured, arrow, left, up"},
    {0xE2DF, L"angle-measured, arrow, right, down"}, {0xE2E0, L"angle-measured, arrow, left, down"},
    {0xE2E1, L"right angle-measured, dot"}, {0xE2E2, L"upper right triangle"},
    {0xE2E3, L"lower right triangle"}, {0xE2E4, L"upper left triangle"},
    {0xE2E5, L"lower left triangle"}, {0xE2E6, L"two joined squares"},
    {0xE2E7, L"circle, slash, bar above"}, {0xE2E8, L"circle, slash, small circle above"},
    {0xE2E9, L"circle, slash, right arrow above"}, {0xE2EA, L"circle, slash, left arrow above"},
    {0xE2EB, L"vertical zig-zag line"}, {0xE2EC, L"trapezium"},
    {0xE2ED, L"reverse semi-colon"}, {0xE2EE, L"bottom square bracket"},
    {0xE2EF, L"top square bracket"}, {0xE2F6, L">/="},
    {0xE2FA, L"</="}, {0xE2FE, L" precedes, equals"},
    {0xE301, L"shortmid R:"}, {0xE302, L" short parallel"},
    {0xE306, L" thick approximate"}, {0xE309, L"equal with four dots"},
    {0xE30A, L"mlcp"}, {0xE30B, L"similar, less"},
    {0xE30C, L"similar, greater"}, {0xE30D, L"dbl vert, bar (under)"},
    {0xE30E, L"double colon, equals"}, {0xE30F, L"dbl dash, vertical"},
    {0xE310, L"vert, dbl bar (under)"}, {0xE311, L"vert, dbl bar (over)"},
    {0xE312, L"dbl bar, vert over and under"}, {0xE313, L"vertical, dash (long)"},
    {0xE314, L"congruent, dot"}, {0xE316, L"bump, equals"},
    {0xE317, L"equal, similar"}, {0xE318, L"equivalent, four dots above"},
    {0xE319, L"equal, dot below"}, {0xE31A, L"minus, comma above"},
    {0xE31B, L"fork, variant"}, {0xE31C, L"fork with top"},
    {0xE31D, L"less-than-or-equal, slanted, dot inside"}, {0xE31E, L"greater-than-or-equal, slanted, dot inside"},
    {0xE31F, L"less-than-or-equal, slanted, dot above"},
    {0xE320, L"greater-than-or-equal, slanted, dot above"},
    {0xE321, L"less-than-or-equal, slanted, dot above right"}, {0xE322, L"greater-than-or-equal, slanted, dot above left"},
    {0xE323, L"equal-or-less, slanted, dot inside"},
    {0xE324, L"equal-or-greater, slanted, dot inside"},
    {0xE325, L"less than, circle inside"}, {0xE326, L"greater than, circle inside"},
    {0xE327, L"equal-or-less"}, {0xE328, L"equal-or-greater"},
    {0xE329, L"less than, questionmark above"}, {0xE32A, L"greater than, questionmark above"},
    {0xE32B, L"less, equal, slanted, greater"}, {0xE32C, L"greater, equal, slanted, less"},
    {0xE32D, L"less, greater, equal"}, {0xE32E, L"greater, less, equal"},
    {0xE32F, L"greater, less, overlapping"}, {0xE330, L"greater, less, apart"},
    {0xE331, L"less, equal, slanted, greater, equal, slanted"}, {0xE332, L"greater, equal, slanted, less, equal, slanted"},
    {0xE333, L"less, similar, equal"}, {0xE334, L"greater, similar, equal"},
    {0xE335, L"less, similar, greater"}, {0xE336, L"greater, similar, less"},
    {0xE337, L"similar, less, equal"}, {0xE338, L"similar, greater, equal"},
    {0xE339, L"smaller than"}, {0xE33A, L"larger than"},
    {0xE33B, L"smaller than or equal"}, {0xE33C, L"larger than or equal"},
    {0xE33D, L"smaller than or equal, slanted"}, {0xE33E, L"larger than or equal, slanted"},
    {0xE33F, L"subset, right arrow"}, {0xE340, L"superset, left arrow"},
    {0xE341, L"subset, plus"}, {0xE342, L"superset, plus"},
    {0xE343, L"subset, multiply"}, {0xE344, L"superset, multiply"},
    {0xE345, L"subset, similar"}, {0xE346, L"superset, similar"},
    {0xE347, L"subset above superset"}, {0xE348, L"superset above subset"},
    {0xE349, L"subset above subset"}, {0xE34A, L"superset above superset"},
    {0xE34B, L"superset, subset"}, {0xE34C, L"superset, subset, dash joining them"},
    {0xE34D, L"reverse solidus, subset"}, {0xE34E, L"superset, solidus"},
    {0xE34F, L"subset, equals, dot"}, {0xE350, L"superset, equals, dot"},
    {0xE351, L"subset, closed"}, {0xE352, L"superset, closed"},
    {0xE353, L"subset, closed, equals"}, {0xE354, L"superset, closed, equals"},
    {0xE355, L"less than, closed by curve"}, {0xE356, L"greater than, closed by curve"},
    {0xE357, L"less than, closed by curve, equal, slanted"}, {0xE358, L"greater than, closed by curve, equal, slanted"},
    {0xE359, L"right triangle above left triangle"}, {0xE35C, L"dbl precedes"},
    {0xE35D, L"dbl succeeds"}, {0xE35E, L"less than, left arrow"},
    {0xE35F, L"greater than, right arrow"}, {0xE365, L" if"},
    {0xE36E, L"two logical and"}, {0xE36F, L"two logical or"},
    {0xE371, L"quadruple prime"}, {0xE372, L"infinity sign, incomplete"},
    {0xE374, L"dbl logical and"}, {0xE375, L"dbl logical or"},
    {0xE376, L"integral around a point operator"}, {0xE377, L"quaternion integral"},
    {0xE378, L"quadruple integral"}, {0xE379, L"left open parenthesis"},
    {0xE37A, L"right open parenthesis"}, {0xE37B, L"negated set membership, variant"},
    {0xE37C, L"negated set membership, variant"}, {0xE37D, L"contains, variant"},
    {0xE37E, L"contains, variant"}, {0xE380, L"straightness"},
    {0xE381, L"flatness"}, {0xE382, L"parallel, slanted"},
    {0xE383, L"top, circle below"}, {0xE384, L"homothetically congruent to"},
    {0xE385, L"similar, parallel, slanted, equal"}, {0xE386, L"congruent and parallel"},
    {0xE387, L"reverse not equivalent"}, {0xE388, L"reverse not equal"},
    {0xE389, L"not parallel, slanted"}, {0xE38A, L"not equal, dot"},
    {0xE38B, L"similar, dot"}, {0xE38C, L"approximate, circumflex accent"},
    {0xE38D, L"not, horizontal, parallel"}, {0xE38E, L"not, vert, infinity"},
    {0xE390, L"not partial differential"}, {0xE391, L"and with middle stem"},
    {0xE392, L"or with middle stem"}, {0xE393, L"or, horizontal dash"},
    {0xE394, L"and, horizontal dash"}, {0xE395, L"circulation function"},
    {0xE396, L"finite part integral"}, {0xE397, L"line integration, rectangular path around pole"},
    {0xE398, L"line integration, semi-circular path around pole"}, {0xE399, L"line integration, not including the pole"},
    {0xE39A, L"integral, left arrow with hook"},
    {0xE39B, L"anti clock-wise integration"},
    {0xE39C, L"set membership, dot above"}, {0xE39D, L"negated set membership, dot above"},
    {0xE39E, L"set membership, two horizontal strokes"}, {0xE3A0, L"set membership, long horizontal stroke"},
    {0xE3A1, L"contains, long horizontal stroke"}, {0xE3A2, L"large set membership, vertical bar on horizontal stroke"},
    {0xE3A3, L"contains"}, {0xE3A4, L"set membership, vertical bar on horizontal stroke"},
    {0xE3A5, L"contains, vertical bar on horizontal stroke"}, {0xE3A6, L"ac current"},
    {0xE3A7, L"electrical intersection"}, {0xE3A8, L"circle, cross"},
    {0xE3A9, L"solidus, bar above"}, {0xE3AA, L"large downward pointing angle"},
    {0xE3AB, L"large upward pointing angle"}, {0xE3AC, L"not with two horizontal strokes"},
    {0xE3AD, L"reverse not with two horizontal strokes"}, {0xE3AE, L"sloping large or"},
    {0xE3B2, L" fj "}, {0xE400, L"right, curved, down arrow "},
    {0xE402, L"left broken arrow"}, {0xE405, L"right broken arrow"},
    {0xE409, L"large circle in circle"}, {0xE40A, L"vertical bar in circle"},
    {0xE40C, L"reverse most positive, line below"}, {0xE415, L"not, vert, similar"},
    {0xE416, L"solidus, bar through"}, {0xE418, L"right angle-measured"},
    {0xE419, L"bottom above top square bracket"}, {0xE41A, L"reversed circle, slash"},
    {0xE41B, L"circle, two horizontal stroked to the right"}, {0xE41C, L"circle, small circle to the right"},
    {0xE429, L" thick similar"}, {0xE500, L"A"}, {0xE501, L"B"}, {0xE503, L"D"},
    {0xE504, L"E"}, {0xE505, L"F"}, {0xE506, L"G"}, {0xE507, L"H"},
    {0xE508, L"I"}, {0xE509, L"J"}, {0xE50A, L"K"}, {0xE50B, L"L"},
    {0xE50C, L"M"}, {0xE50D, L"negated set membership, two horizontal strokes"},
    {0xE50E, L"O"}, {0xE512, L"S"},
    {0xE513, L"T"}, {0xE514, L"U"}, {0xE515, L"V"}, {0xE516, L"W"},
    {0xE517, L"X"}, {0xE518, L"Y"}, {0xE520, L"A"}, {0xE522, L"C"},
    {0xE523, L"D"}, {0xE526, L"G"}, {0xE529, L"J"}, {0xE52A, L"K"},
    {0xE52D, L"N"}, {0xE52E, L"O"}, {0xE52F, L"P"}, {0xE530, L"Q"},
    {0xE531, L"R"}, {0xE532, L"S"}, {0xE533, L"T"}, {0xE534, L"U"},
    {0xE535, L"V"}, {0xE536, L"W"}, {0xE537, L"X"}, {0xE538, L"Y"},
    {0xE539, L"Z"}, {0xE540, L"a"}, {0xE541, L"b"}, {0xE542, L"c"},
    {0xE543, L"d"}, {0xE545, L"f"}, {0xE546, L"g"}, {0xE547, L"h"},
    {0xE548, L"i"}, {0xE549, L"j"}, {0xE54A, L"k"}, {0xE54B, L"l"},
    {0xE54C, L"m"}, {0xE54D, L"n"}, {0xE54F, L"p"}, {0xE550, L"q"},
    {0xE551, L"r"}, {0xE552, L"s"}, {0xE553, L"t"}, {0xE554, L"u"},
    {0xE555, L"v"}, {0xE556, L"w"}, {0xE557, L"x"}, {0xE558, L"y"},
    {0xE559, L"z"}, {0xE560, L"A"}, {0xE561, L"B"}, {0xE562, L"C"},
    {0xE563, L"D"}, {0xE564, L"E"}, {0xE565, L"F"}, {0xE566, L"G"},
    {0xE569, L"J"}, {0xE56A, L"K"}, {0xE56B, L"L"}, {0xE56C, L"M"},
    {0xE56D, L"N"}, {0xE56E, L"O"}, {0xE56F, L"P"}, {0xE570, L"Q"},
    {0xE572, L"S"}, {0xE573, L"T"}, {0xE574, L"U"}, {0xE575, L"V"},
    {0xE576, L"W"}, {0xE577, L"X"}, {0xE578, L"Y"}, {0xE579, L"Z"},
    {0xE580, L"a"}, {0xE581, L"b"}, {0xE582, L"c"}, {0xE583, L"d"},
    {0xE584, L"e"}, {0xE585, L"f"}, {0xE586, L"g"}, {0xE587, L"h"},
    {0xE588, L"i"}, {0xE589, L"j"}, {0xE58A, L"k"}, {0xE58B, L"l"},
    {0xE58C, L"m"}, {0xE58D, L"n"}, {0xE58E, L"o"}, {0xE58F, L"p"},
    {0xE590, L"q"}, {0xE591, L"r"}, {0xE592, L"s"}, {0xE593, L"t"},
    {0xE594, L"u"}, {0xE595, L"v"}, {0xE596, L"w"}, {0xE597, L"x"},
    {0xE598, L"y"}, {0xE599, L"z"},
    {0xE5DC, L" not precedes, equals"}, {0xE5F1, L" not succeeds, equals"},
    {0xE800, L" such that"}, {0xE80B, L" black lozenge"},
    {0xE838, L"circle with vertical bar"}, {0xE844, L"\\"},
    {0xEA00, L"1"}, {0xEA01, L"1"}, {0xEA02, L"2"}, {0xEA03, L"2"},
    {0xEA04, L"3"}, {0xEA05, L"3"}, {0xEA06, L"4"}, {0xEA07, L"a"},
    {0xEA08, L"a"}, {0xEA09, L"A"}, {0xEA0A, L"a"}, {0xEA0B, L"A"},
    {0xEA0C, L"AB"}, {0xEA0D, L"alpha"}, {0xEA0E, L"alpha"}, {0xEA0F, L"alpha"},
    {0xEA10, L"b"}, {0xEA11, L"B"}, {0xEA12, L"b"}, {0xEA13, L"B"},
    {0xEA14, L"B"}, {0xEA15, L"B"}, {0xEA16, L"BC"}, {0xEA17, L"beta"},
    {0xEA18, L"beta"}, {0xEA19, L"c"}, {0xEA1A, L"c"}, {0xEA1B, L"c"},
    {0xEA1C, L"C"}, {0xEA1D, L"c"}, {0xEA1E, L"c"}, {0xEA1F, L"c"},
    {0xEA20, L"c"}, {0xEA21, L"c"}, {0xEA22, L"chi"}, {0xEA23, L"chi"},
    {0xEA24, L"chi"}, {0xEA25, L"d"}, {0xEA26, L"D"}, {0xEA27, L"d"},
    {0xEA28, L"D"}, {0xEA29, L"d"}, {0xEA2A, L"D"}, {0xEA2B, L"D"},
    {0xEA2C, L"Delta"}, {0xEA2D, L"delta"}, {0xEA2E, L"delta"}, {0xEA2F, L"dl"},
    {0xEA30, L"e"}, {0xEA31, L"e"}, {0xEA32, L"l"}, {0xEA33, L"l"},
    {0xEA34, L"f"}, {0xEA35, L"f"}, {0xEA36, L"F"}, {0xEA37, L"f"},
    {0xEA38, L"F"}, {0xEA39, L"f"}, {0xEA3A, L"F"}, {0xEA3B, L"sigma"},
    {0xEA3C, L"sigma"}, {0xEA3D, L"g"}, {0xEA3E, L"g"}, {0xEA3F, L"G"},
    {0xEA40, L"g"}, {0xEA41, L"G"}, {0xEA42, L"Gamma"}, {0xEA43, L"gamma"},
    {0xEA44, L"gamma"}, {0xEA45, L"gamma"}, {0xEA46, L"H"}, {0xEA47, L"h"},
    {0xEA48, L"h"}, {0xEA49, L"i"}, {0xEA4A, L"I"}, {0xEA4B, L"j"},
    {0xEA4C, L"J"}, {0xEA4D, L"J"}, {0xEA4E, L"J"}, {0xEA4F, L"k"},
    {0xEA50, L"k"}, {0xEA51, L"k"}, {0xEA52, L"K"}, {0xEA53, L"K"},
    {0xEA54, L"k"}, {0xEA55, L"l"}, {0xEA56, L"L"}, {0xEA57, L"l"},
    {0xEA58, L"lambda"}, {0xEA59, L"lambda"}, {0xEA5A, L"Lambda"}, {0xEA5B, L"lnV"},
    {0xEA5C, L"m"}, {0xEA5D, L"M"}, {0xEA5E, L"m"}, {0xEA5F, L"m"},
    //{0xEA60, L"\xCE\xBC"},
    {0xEA60, L"mu"},
    //{0xEA61, L"\xCE\xBC"},
    {0xEA61, L"mu"},
    //{0xEA62, L"\xCE\xBC"},
    {0xEA62, L"mu"},
    {0xEA63, L"n"}, {0xEA64, L"n"},
    {0xEA65, L"N"}, {0xEA66, L"n"}, {0xEA67, L"N"}, {0xEA68, L"n"},
    {0xEA69, L"n"}, {0xEA6A, L"N"}, {0xEA6B, L"nabla"}, {0xEA6C, L"nu"},
    {0xEA6D, L"nv"}, {0xEA6E, L"O"}, {0xEA6F, L"O"}, {0xEA70, L"O"},
    {0xEA71, L"omega"}, {0xEA72, L"F"}, {0xEA73, L"p"}, {0xEA74, L"P"},
    {0xEA75, L"p"}, {0xEA76, L"P"}, {0xEA77, L"p"}, {0xEA78, L"P"},
    {0xEA79, L"p"}, {0xEA7A, L"P"}, {0xEA7B, L"phi"}, {0xEA7C, L"phi"},
    {0xEA7D, L"Phi"}, {0xEA7E, L"phi"}, {0xEA7F, L"pi"}, {0xEA80, L"pi"},
    {0xEA81, L"pi"}, {0xEA82, L"Pi"}, {0xEA83, L"pi"}, {0xEA84, L"pi"},
    {0xEA85, L"pi"}, {0xEA86, L"pi"}, {0xEA87, L"psi"}, {0xEA88, L"psi"},
    {0xEA89, L"psi"}, {0xEA8A, L"Psi"}, {0xEA8B, L"psi"}, {0xEA8C, L"Psi"},
    {0xEA8D, L"q"}, {0xEA8E, L"Q"}, {0xEA8F, L"q"}, {0xEA90, L"q"},
    {0xEA91, L"Q"}, {0xEA92, L"q"}, {0xEA93, L"Q"}, {0xEA94, L"q"},
    {0xEA95, L"q"}, {0xEA96, L"q"}, {0xEA97, L"Q"}, {0xEA98, L"r"},
    {0xEA99, L"R"}, {0xEA9A, L"R"}, {0xEA9B, L"r"}, {0xEA9C, L"R"},
    {0xEA9D, L"R"}, {0xEA9E, L"r"}, {0xEA9F, L"R"}, {0xEAA0, L"r"},
    {0xEAA1, L"r"}, {0xEAA2, L"R"}, {0xEAA3, L"r"}, {0xEAA4, L"r1"},
    {0xEAA5, L"RE"}, {0xEAA6, L"rho"}, {0xEAA7, L"rho"}, {0xEAA8, L"rho"},
    {0xEAA9, L"ri"}, {0xEAAA, L"rj"}, {0xEAAB, L"rN"}, {0xEAAC, L"s"},
    {0xEAAD, L"S"}, {0xEAAE, L"S"}, {0xEAAF, L"s"}, {0xEAB0, L"S"},
    {0xEAB1, L"s"}, {0xEAB2, L"S"}, {0xEAB3, L"S"}, {0xEAB4, L"B"},
    {0xEAB5, L"E"}, {0xEAB6, L"G"}, {0xEAB7, L"P"}, {0xEAB8, L"Q"},
    {0xEAB9, L"t"}, {0xEABA, L"T"}, {0xEABB, L"T"}, {0xEABC, L"t"},
    {0xEABD, L"T"}, {0xEABE, L"t"}, {0xEABF, L"T"}, {0xEAC0, L"tau"},
    {0xEAC1, L"tau"}, {0xEAC2, L"theta"}, {0xEAC3, L"theta"}, {0xEAC4, L"times"},
    {0xEAC5, L"TT"}, {0xEAC6, L"u"}, {0xEAC7, L"u"}, {0xEAC8, L"U"},
    {0xEAC9, L"u"}, {0xEACA, L"u"}, {0xEACB, L"upsilon"}, {0xEACC, L"V"},
    {0xEACD, L"v"}, {0xEACE, L"v"}, {0xEACF, L"V"}, {0xEAD0, L"v"},
    {0xEAD1, L"V"}, {0xEAD2, L"v"}, {0xEAD3, L"v"}, {0xEAD4, L"V"},
    {0xEAD5, L"v"}, {0xEAD6, L"epsilon"}, {0xEAD7, L"epsilon"}, {0xEAD8, L"epsilon"},
    {0xEAD9, L"phi"}, {0xEADA, L"phi"}, {0xEADB, L"theta"}, {0xEADC, L"w"},
    {0xEADD, L"w"}, {0xEADE, L"w"}, {0xEADF, L"x"}, {0xEAE0, L"X"},
    {0xEAE1, L"x"}, {0xEAE2, L"X"}, {0xEAE3, L"x"}, {0xEAE4, L"x"},
    {0xEAE5, L"X"}, {0xEAE6, L"x"}, {0xEAE7, L"xi"}, {0xEAE8, L"y"},
    {0xEAE9, L"Y"}, {0xEAEA, L"y"}, {0xEAEB, L"Y"}, {0xEAEC, L"y"},
    {0xEAED, L"y"}, {0xEAEE, L"z"}, {0xEAEF, L"Z"}, {0xEAF0, L"z"},
    {0xEAF1, L"z"}, {0xEAF2, L"Z"}, {0xEAF3, L"z"}, {0xEAF4, L"z"},
    {0xEAF5, L"zeta"}, {0xEAF6, L"zeta"}, {0xEAF7, L"xbscrsv"}, {0xEAF8, L"xbscrtv"},
    {0xEAF9, L"xescr1v"}, {0xEAFA, L"xescr2v"}, {0xEAFB, L"ngrmi"}, {0xEAFC, L"B"},
    {0xEAFE, L"sigma with tilde"}, {0xEAFF, L"A"},
    {0xEB00, L"Lambda"}, {0xEB01, L"Lambda with umlaut"},
    {0xEB02, L"down triangle with a dot"}, {0xEB03, L"tau with tilde"},
    {0xEB04, L"w"}, {0xEB05, L"m"},
    {0xEB06, L"M"}, {0xEB07, L"E"}, {0xEB08, L"W"}, {0xEB09, L"kappa"},
    {0xEB0A, L"h"}, {0xEB0B, L"n"}, {0xEB0C, L"underlined kappa"}, {0xEB0D, L"H"},
    {0xEB0E, L"Theta"}, {0xEB0F, L"M"}, {0xEB10, L"m"}, {0xEB11, L"Z"},
    {0xEB12, L"g"}, {0xEB13, L"partial"}, {0xEB14, L"C"}, {0xEB15, L"E"},
    {0xEB16, L"sfgrvect"}, {0xEB17, L"bgrvect"}, {0xEB18, L"xogrvect"}, {0xEB19, L"W"},
    {0xEB1A, L"a"}, {0xEB1B, L"b"}, {0xEB1C, L"S"}, {0xEB1D, L"otimesmac"},
    {0xEB1E, L"J"}, {0xEB1F, L"b"}, {0xEB20, L"Z"}, {0xEB21, L"L"},
    {0xEB22, L"g"}, {0xEB23, L"Delta with circumflex"},
    {0xEB24, L"omega with tilde"}, {0xEB25, L"Lambda with circumflex"},
    {0xEB26, L"var phiv with circumflex"}, {0xEB27, L"Delta with tilde"},
    {0xEB28, L"lambda with macron"}, {0xEB29, L"pi with macron"},
    {0xEB2A, L"Q"}, {0xEB2B, L"1"}, {0xEB2C, L"3"}, {0xEB2D, L"E"},
    {0xEB2E, L"e"}, {0xEB2F, L"g"}, {0xEB30, L"j"}, {0xEB31, L"raised chempoint"},
    {0xEB32, L"epsilon-vector"}, {0xEB33, L"l"}, {0xEB34, L"M"}, {0xEB35, L"l"},
    {0xEB36, L"A"}, {0xEB37, L"phi"}, {0xEB38, L"pupsil"}, {0xEB39, L"h with umlaut"},
    {0xEB3A, L"- - - -"}, {0xEB3B, L"F with hat"},
    {0xEB3C, L"rectangle"}, {0xEB3D, L"bold dash"},
    {0xEB3E, L"diamond"}, {0xEB3F, L"R"}, {0xEB40, L"omega"}, {0xEB41, L"r"},
    {0xEB42, L"circle w/criscross"}, {0xEB43, L"n"}, {0xEB44, L"j"}, {0xEB45, L"d"},
    {0xEB46, L"g"}, {0xEB47, L"o"}, {0xEB48, L"c"}, {0xEB49, L"dotted_times"},
    {0xEB4A, L"large asterisk"}, {0xFB00, L" ff "},
    {0xFB01, L" fi "}, {0xFB02, L" fl "},
    {0xFB03, L" ffi "}, {0xFB04, L" ffl "}
};


static string s_TranslateToAscii(const wstring& str)
{
    wstring result;
    for (wchar_t cch : str)
    {
        if (cch >= L'\u0001' && cch <= L'\u007F')
            result.push_back(cch);
        else
        {
            auto p = s_AsciiConvTable.find(cch);
            if (p != s_AsciiConvTable.end())
                result.append(p->second);
        }
    }
    return wstring_to_utf8(result);
}


template<class TE>
wstring s_TextListToWstring(const list<CRef<TE>>& text_list)
{
    return utf8_to_wstring(s_TextListToString(text_list));
}


static wstring s_GetInitialsFromForeName(wstring fore_name)
{
    static const locale s_Locale(s_UTF8LocaleName);
    static const auto& s_CType = use_facet<ctype<wchar_t>>(s_Locale);
    s_ToUpper(fore_name, s_Locale);
    vector<wstring> tokens;
    s_ForeachToken(fore_name, [](wchar_t x)->bool { return !s_CType.is(ctype_base::space, x); },
        [&tokens](wstring::iterator p, wstring::iterator q) -> wstring::iterator {
        wstring s(p, q);
        if (!s.empty() && s != L"D'" && s != L"DE" && s != L"DER" && s != L"LA" && s != L"IBN")
            tokens.push_back(s);
        return q;
    });
    if (tokens.size() >= 2) {
        // PM-4068
        // return tokens[0].substr(0,1) + tokens[1].substr(0,1);
        return accumulate(tokens.begin(), tokens.end(), wstring(),
            [](const wstring& x, const wstring& y) { return x + y.substr(0, 1); });
    }
    else if (tokens.size() == 1) {
        auto p = find(tokens.front().begin(), tokens.front().end(), L'-');
        if (p != tokens.front().end() && p + 1 != tokens.front().end())
            return tokens.front().substr(0, 1) + wstring(1, p[1]);
        else
            return tokens.front().substr(0, 1);
    }
    return L"";
}


struct pubmed_date_t {
    int _year = 0;
    int _month = 0;
    int _day = 0;
};


static pubmed_date_t s_GetPubmedDate(const CPubDate& pub_date)
{
    pubmed_date_t pubmed_date;
    static const auto& s_Facet = get_ctype_facet<char>();
    try {
        if (pub_date.IsYM()) {
            auto& ym = pub_date.GetYM();
            pubmed_date._year = NStr::StringToNumeric<int>(ym.GetYear().Get());
            if (ym.IsSetMS() && ym.GetMS().IsMD()) {
                auto& md = ym.GetMS().GetMD();
                pubmed_date._month = s_TranslateMonth(md.GetMonth());
                if (pubmed_date._month >= 1 && pubmed_date._month <= 12 && md.IsSetDay()) {
                    pubmed_date._day = NStr::StringToNumeric<int>(md.GetDay().Get());
                }
            }
        }
        else if (pub_date.IsMedlineDate()) {
            string medline_date = pub_date.GetMedlineDate();
            s_ForeachToken(medline_date, [](char cch) -> bool { return s_Facet.is(ctype_base::alnum, cch); },
                [&pubmed_date](string::iterator p, string::iterator q) -> string::iterator {
                string str(p, q);
                int num = 0;
                if (s_StringToInt(str, num)) {
                    if (pubmed_date._year == 0 && num >= 1800 && num <= 2100)
                        pubmed_date._year = num;
                    else if (pubmed_date._month == 0 && num >= 1 && num <= 12)
                        pubmed_date._month = num;
                    else if (pubmed_date._month != 0 && pubmed_date._day == 0 && num >= 1 && num <= 31)
                        pubmed_date._day = num;
                }
                else if (pubmed_date._month == 0) {
                    pubmed_date._month = s_TranslateMonth(str);
                }
                return q;
            });
        }
    }
    catch (...) {
    }
    return pubmed_date;
}


static CRef<CDate> s_GetDateFromArticleDate(const CArticleDate& adate)
{
    CRef<CDate> date(new CDate());
    try {
        // Try integer values
        CDate_std& std_date = date->SetStd();
        std_date.SetYear(NStr::StringToNumeric<CDate_std::TYear>(adate.GetYear().Get()));
        std_date.SetMonth(NStr::StringToNumeric<CDate_std::TMonth>(adate.GetMonth().Get()));
        std_date.SetDay(NStr::StringToNumeric<CDate_std::TDay>(adate.GetDay().Get()));
    }
    catch (...) {
        // Use string values
        string str_date = adate.GetYear();
        if (!adate.GetMonth().Get().empty()) str_date += " " + adate.GetMonth();
        if (!adate.GetDay().Get().empty()) str_date += " " + adate.GetDay();
        date->SetStr(str_date);
    }
    return date;
}


static CRef<CTitle> s_GetJournalTitle(const CPubmedArticle& pubmed_article)
{
    const CMedlineCitation& medlineCitation = pubmed_article.GetMedlineCitation();
    const CJournal& journal = medlineCitation.GetArticle().GetJournal();
    CRef<CTitle> title(new CTitle());

    if (journal.IsSetISOAbbreviation()) {
        CRef<CTitle::C_E> iso(new CTitle::C_E());
        iso->SetIso_jta(journal.GetISOAbbreviation());
        title->Set().push_back(iso);
    }

    CRef<CTitle::C_E> mljta(new CTitle::C_E());
    mljta->SetMl_jta(medlineCitation.GetMedlineJournalInfo().GetMedlineTA());
    title->Set().push_back(mljta);

    if (journal.IsSetISSN()) {
        CRef<CTitle::C_E> issn(new CTitle::C_E());
        issn->SetIssn(journal.GetISSN());
        title->Set().push_back(issn);
    }

    if (journal.IsSetTitle()) {
        CRef<CTitle::C_E> name(new CTitle::C_E());
        name->SetName(journal.GetTitle());
        title->Set().push_back(name);
    }

    return title;
}


static bool s_SetCommentCorrection(
    CRef<CImprint>& imprint,
    const CCommentsCorrectionsList& comments_corrections,
    CCitRetract::EType type,
    const string& ref_type)
{
    for (auto ref : comments_corrections.GetCommentsCorrections()) {
        string attr_ref_type = CCommentsCorrections::C_Attlist::GetTypeInfo_enum_EAttlist_RefType()->
            FindName(ref->GetAttlist().GetRefType(), false);
        if (attr_ref_type == ref_type) {
            CRef<CCitRetract> citretract(new CCitRetract);
            string temp = s_TranslateToAscii(utf8_to_wstring(ref->GetRefSource()));
            if (ref->IsSetNote()) temp += ". " + s_TranslateToAscii(utf8_to_wstring(ref->GetNote()));
            if (ref->IsSetPMID()) temp += ". PMID: " + ref->GetPMID();
            citretract->SetType(type);
            citretract->SetExp(temp);
            imprint->SetRetract(*citretract);
            return true;
        }
    }
    return false;
}


static int s_GetPublicationStatusId(const string& publication_status)
{
    static const unordered_map<string, int> s_PubStatusId {
        { "received", ePubStatus_received },
        { "accepted", ePubStatus_accepted },
        { "epublish", ePubStatus_epublish },
        { "ppublish", ePubStatus_ppublish },
        { "revised", ePubStatus_revised },
        { "pmc", ePubStatus_pmc },
        { "pmcr", ePubStatus_pmcr },
        { "pubmed", ePubStatus_pubmed },
        { "pubmedr", ePubStatus_pubmedr },
        { "aheadofprint", ePubStatus_aheadofprint },
        { "premedline", ePubStatus_premedline },
        { "medline", ePubStatus_medline },
    };
    auto p = s_PubStatusId.find(publication_status);
    return p == s_PubStatusId.end() ? ePubStatus_other : p->second;
}


static CRef<CImprint> s_GetImprint(const CPubmedArticle& pubmed_article)
{
    CRef<CImprint> imprint(new CImprint());

    const CMedlineCitation& medline_citation = pubmed_article.GetMedlineCitation();
    const CPubmedData& pubmed_data = pubmed_article.GetPubmedData();
    const CArticle& article = medline_citation.GetArticle();
    const CJournal& journal = article.GetJournal();
    const CJournalIssue& jissue = journal.GetJournalIssue();

    // Pub date
    string pub_model = CArticle::C_Attlist::GetTypeInfo_enum_EAttlist_PubModel()->
        FindName(article.GetAttlist().GetPubModel(), false);
    if (pub_model == "Electronic-Print" || pub_model == "Electronic-eCollection") {
        for (auto d : article.GetArticleDate()) {
            if (d->GetAttlist().IsSetDateType() && d->GetAttlist().GetDateType() == CArticleDate::C_Attlist::eAttlist_DateType_Electronic) {
                imprint->SetDate(*s_GetDateFromArticleDate(*d));
                break;
            }
        }
    }
    else {
        imprint->SetDate(*s_GetDateFromPubDate(jissue.GetPubDate()));
    }

    string volume = jissue.IsSetVolume() ? jissue.GetVolume().Get() : "";
    if (!volume.empty()) imprint->SetVolume(volume);

    string issue = jissue.IsSetIssue() ? jissue.GetIssue().Get() : "";
    if (!issue.empty()) imprint->SetIssue(issue);

    string pages = article.GetPE_2().IsPE() ? s_GetPagination(article.GetPE_2().GetPE().GetPagination()) : "";
    if (!pages.empty()) imprint->SetPages(pages);

    auto list_language = medline_citation.GetArticle().GetLanguage();
    string languages;
    if (!list_language.empty())
        languages = accumulate(next(list_language.begin()), list_language.end(), list_language.front()->Get(),
            [](const auto& s, const auto& e) -> string { return s + "," + e->Get(); });
    imprint->SetLanguage(languages);

    if (medline_citation.IsSetCommentsCorrectionsList()) {
        s_SetCommentCorrection(imprint, medline_citation.GetCommentsCorrectionsList(), CCitRetract::eType_retracted, "RetractionIn")
            || s_SetCommentCorrection(imprint, medline_citation.GetCommentsCorrectionsList(), CCitRetract::eType_in_error, "ErratumIn")
            || s_SetCommentCorrection(imprint, medline_citation.GetCommentsCorrectionsList(), CCitRetract::eType_erratum, "ErratumFor")
            || s_SetCommentCorrection(imprint, medline_citation.GetCommentsCorrectionsList(), CCitRetract::eType_notice, "RetractionOf");
    }

    // PubStatus
    imprint->SetPubstatus(s_GetPublicationStatusId(pubmed_data.GetPublicationStatus()));

    // History
    if (pubmed_data.IsSetHistory())
    {
        CRef<CPubStatusDateSet> date_set(new CPubStatusDateSet());
        for (auto pub_date : pubmed_data.GetHistory().GetPubMedPubDate()) {
            CRef<CPubStatusDate> pub_stat_date(new CPubStatusDate());
            string pub_status = CPubMedPubDate::C_Attlist::GetTypeInfo_enum_EAttlist_PubStatus()->
                FindName(pub_date->GetAttlist().GetPubStatus(), false);
            pub_stat_date->SetPubstatus(s_GetPublicationStatusId(pub_status));
            pub_stat_date->SetDate(*s_GetDateFromPubMedPubDate(*pub_date));
            date_set->Set().push_back(pub_stat_date);
        }
        imprint->SetHistory(*date_set);
    }

    return imprint;
}


static CRef<CCit_jour> s_GetJournalCitation(const CPubmedArticle& pubmed_article)
{
    CRef<CCit_jour> cit_journal(new CCit_jour());
    cit_journal->SetTitle(*s_GetJournalTitle(pubmed_article));
    cit_journal->SetImp(*s_GetImprint(pubmed_article));
    return cit_journal;
}


inline bool s_IsValidYN(const CAuthor& auth)
{
    return auth.GetAttlist().IsSetValidYN() &&
        auth.GetAttlist().GetValidYN() == CAuthor::C_Attlist::eAttlist_ValidYN_Y;
}


static CRef<CAuth_list> s_GetAuthorList(const CArticle& article)
{
    CRef<CAuth_list> author_list;
    if (!article.IsSetAuthorList()) return author_list;
    auto& list_author = article.GetAuthorList().GetAuthor();
    bool has_authors = any_of(list_author.begin(), list_author.end(),
        [](const CRef<CAuthor>& auth)->bool { return s_IsValidYN(*auth); });
    if (has_authors) {
        bool std_format = any_of(list_author.begin(), list_author.end(), [](const CRef<CAuthor>& auth)->bool {
            return s_IsValidYN(*auth) && (auth->GetLC().IsCollectiveName() ||
                    (auth->IsSetAffiliationInfo() && !auth->GetAffiliationInfo().empty())); });
        author_list.Reset(new CAuth_list());
        CRef<CAuth_list::C_Names> auth_names(new CAuth_list::C_Names());
        for (auto author : list_author) {
            if (s_IsValidYN(*author)) {
                if (std_format) {
                    CRef<CPerson_id> person(new CPerson_id());
                    if (author->GetLC().IsCollectiveName()) {
                        person->SetConsortium(s_TranslateToAscii(
                            s_TextListToWstring(author->GetLC().GetCollectiveName().Get())));
                    }
                    else {
                        person->SetMl(s_TranslateToAscii(utf8_to_wstring(s_GetAuthorMedlineName(*author))));
                    }
                    CRef<objects::CAuthor> auth(new objects::CAuthor());
                    auth->SetName(*person);
                    auto& list_affiliation_info = author->GetAffiliationInfo();
                    if (!list_affiliation_info.empty()) {
                        list<string> affiliations;
                        for (auto affiliation_info : list_affiliation_info) {
                            string affiliation = s_TranslateToAscii(
                                s_TextListToWstring(affiliation_info->GetAffiliation().Get()));
                            if (!affiliation.empty()) affiliations.emplace_back(move(affiliation));
                        }
                        if (!affiliations.empty()) {
                            CRef<CAffil> affil(new CAffil());
                            affil->SetStr(accumulate(next(affiliations.begin()), affiliations.end(), affiliations.front(),
                                [](const string& s1, const string& s2)->string { return s1 + "; " + s2; }));
                            auth->SetAffil(*affil);
                        }
                    }
                    auth_names->SetStd().push_back(auth);
                }
                else {
                    auth_names->SetMl().push_back(s_TranslateToAscii(utf8_to_wstring(s_GetAuthorMedlineName(*author))));
                }
            }
        }
        if (!article.GetAuthorList().GetAttlist().IsSetCompleteYN() ||
            article.GetAuthorList().GetAttlist().GetCompleteYN() != CAuthorList::C_Attlist::eAttlist_CompleteYN_Y) {
            if (std_format) {
                CRef<CPerson_id> person(new CPerson_id());
                person->SetMl("et al");
                CRef<objects::CAuthor> auth(new objects::CAuthor());
                auth->SetName(*person);
                auth_names->SetStd().push_back(auth);
            }
            else {
                auth_names->SetMl().push_back("et al");
            }
        }
        author_list->SetNames(*auth_names);
    }
    return author_list;
}


static objects::CArticleId::E_Choice s_GetArticleIdTypeId(const CArticleId& article_id)
{
    static const unordered_map<CArticleId::C_Attlist::EAttlist_IdType, objects::CArticleId::E_Choice> s_ArticleIdTypeId = {
        { CArticleId::C_Attlist::eAttlist_IdType_pubmed, objects::CArticleId::e_Pubmed },
        { CArticleId::C_Attlist::eAttlist_IdType_medline, objects::CArticleId::e_Medline },
        { CArticleId::C_Attlist::eAttlist_IdType_doi, objects::CArticleId::e_Doi },
        { CArticleId::C_Attlist::eAttlist_IdType_pii, objects::CArticleId::e_Pii },
        { CArticleId::C_Attlist::eAttlist_IdType_pmcid, objects::CArticleId::e_Pmcid },
        { CArticleId::C_Attlist::eAttlist_IdType_pmcpid, objects::CArticleId::e_Pmcpid },
        { CArticleId::C_Attlist::eAttlist_IdType_pmpid, objects::CArticleId::e_Pmpid },
    };
    if (!article_id.GetAttlist().IsSetIdType()) return objects::CArticleId::e_not_set;
    auto id_type = article_id.GetAttlist().GetIdType();
    auto p = s_ArticleIdTypeId.find(id_type);
    return p != s_ArticleIdTypeId.end() ? p->second : objects::CArticleId::e_Other;
}


static CRef<CCit_art> s_GetCitation(const CPubmedArticle& pubmed_article)
{
    auto& medline_citation = pubmed_article.GetMedlineCitation();
    CRef<CCit_art> cit_article(new CCit_art());
    CRef<CTitle> title = s_GetTitle(medline_citation.GetArticle());
    if (title) cit_article->SetTitle(*title);
    auto author_list = s_GetAuthorList(medline_citation.GetArticle());
    if (author_list) cit_article->SetAuthors(*author_list);
    CRef<CCit_art::C_From> from(new CCit_art::C_From());
    from->SetJournal(*s_GetJournalCitation(pubmed_article));
    cit_article->SetFrom(*from);
    cit_article->SetIds(*s_GetArticleIdSet(
        pubmed_article.GetPubmedData().GetArticleIdList(),
        &pubmed_article.GetMedlineCitation().GetArticle()));
    return cit_article;
}


static void s_FillMesh(CMedline_entry::TMesh& mesh, const CMeshHeadingList& mesh_heading_list)
{
    for (auto mesh_heading_it : mesh_heading_list.GetMeshHeading()) {
        CRef<CMedline_mesh> medline_mesh(new CMedline_mesh());
        auto& desc_name = mesh_heading_it->GetDescriptorName();
        if (desc_name.GetAttlist().IsSetMajorTopicYN() &&
            desc_name.GetAttlist().GetMajorTopicYN() == CDescriptorName::C_Attlist::eAttlist_MajorTopicYN_Y)
            medline_mesh->SetMp(true);
        medline_mesh->SetTerm(desc_name.GetDescriptorName());
        for (auto qualifier_name_it : mesh_heading_it->GetQualifierName()) {
            CRef<CMedline_qual> qual(new CMedline_qual());
            if (qualifier_name_it->GetAttlist().IsSetMajorTopicYN() &&
                qualifier_name_it->GetAttlist().GetMajorTopicYN() == CQualifierName::C_Attlist::eAttlist_MajorTopicYN_Y)
                qual->SetMp(true);
            qual->SetSubh(qualifier_name_it->GetQualifierName());
            medline_mesh->SetQual().push_back(qual);
        }
        mesh.push_back(medline_mesh);
    }
}


static void s_FillChem(CMedline_entry::TSubstance& chems, const CChemicalList& chemical_list)
{
    for (auto chemical_it : chemical_list.GetChemical()) {
        CRef<CMedline_rn> chem(new CMedline_rn());
        chem->SetName(chemical_it->GetNameOfSubstance());
        // Registry number and type
        string registry_number = chemical_it->GetRegistryNumber();
        if (registry_number.empty() || registry_number == "0")
            chem->SetType(chem->eType_nameonly);
        else if (registry_number.size() > 2 && toupper(registry_number[0]) == 'E' && toupper(registry_number[1]) == 'C') {
            chem->SetCit(registry_number.c_str() + 2 + strspn(registry_number.c_str() + 2, " "));
            chem->SetType(chem->eType_ec);
        }
        else {
            chem->SetCit(registry_number);
            chem->SetType(chem->eType_cas);
        }
        chems.push_back(chem);
    }
}


static int s_GetDatabankTypeId(const string& databank_name)
{
    static const unordered_map<string, int> s_DatabankTypeId {
        { "ddbj", CMedline_si::eType_ddbj },
        { "carbbank", CMedline_si::eType_carbbank },
        { "embl", CMedline_si::eType_embl },
        { "hdb", CMedline_si::eType_hdb },
        { "genbank", CMedline_si::eType_genbank },
        { "hgml", CMedline_si::eType_hgml },
        { "mim", CMedline_si::eType_mim },
        { "msd", CMedline_si::eType_msd },
        { "pdb", CMedline_si::eType_pdb },
        { "pir", CMedline_si::eType_pir },
        { "prfseqdb", CMedline_si::eType_prfseqdb },
        { "psd", CMedline_si::eType_psd },
        { "swissprot", CMedline_si::eType_swissprot },
        { "gdb", CMedline_si::eType_gdb },
    };
    auto p = s_DatabankTypeId.find(databank_name);
    return p == s_DatabankTypeId.end() ? -1 : p->second;
}


static void s_FillXref(CMedline_entry::TXref& refs, const CDataBankList& databank_list)
{
    for (auto databank_it : databank_list.GetDataBank()) {
        string databank_name = databank_it->GetDataBankName();
        s_ToLower(databank_name);
        int type_id = s_GetDatabankTypeId(databank_name);
        if (type_id >= 0) {
            if (databank_it->IsSetAccessionNumberList()) {
                for (auto& accession_number_it : databank_it->GetAccessionNumberList().GetAccessionNumber()) {
                    CRef<CMedline_si> si(new CMedline_si());
                    si->SetType((CMedline_si::EType)type_id);
                    si->SetCit(accession_number_it->Get());
                    refs.push_back(si);
                }
            }
            else {
                CRef<CMedline_si> si(new CMedline_si());
                si->SetType((CMedline_si::EType)type_id);
                refs.push_back(si);
            }
        }
    }
}


static void s_FillGenes(CMedline_entry::TGene& mgenes, const CGeneSymbolList& gene_symbol_list)
{
    for (auto& gene_symbol_it : gene_symbol_list.GetGeneSymbol()) {
        mgenes.push_back(gene_symbol_it->Get());
    }
}


static void s_FillPubtypeList(
    CMedline_entry::TPub_type& pub_types,
    const CPublicationTypeList& publication_type_list)
{
    for (auto publication_type_it : publication_type_list.GetPublicationType()) {
        pub_types.push_back(publication_type_it->GetPublicationType());
    }
}


static CRef<CPubMedPubDate> s_FindPubDateStatus(
    const list<CRef<CPubMedPubDate>>& pubmed_pubdates,
    CPubMedPubDate::C_Attlist::EAttlist_PubStatus status)
{
    for (auto pub_date : pubmed_pubdates) {
        if (pub_date->GetAttlist().GetPubStatus() == status) {
            return pub_date;
        }
    }
    return CRef<CPubMedPubDate>();
}


static string s_GetAbstractText(const CAbstract& abstr)
{
    string abstract_text;
    for (auto abstract_text_it : abstr.GetAbstractText())
    {
        string label = abstract_text_it->GetAttlist().IsSetLabel() ?
            abstract_text_it->GetAttlist().GetLabel() + ": " : "";
        if (!abstract_text.empty()) abstract_text.append(" ");
        abstract_text.append(label + s_TextListToString(abstract_text_it->GetAbstractText()));
    }
    return abstract_text;
}


static CRef<CMedline_entry> s_GetMedlineEntry(const CPubmedArticle& pubmed_article)
{
    CRef<CMedline_entry> medline_entry(new CMedline_entry());
    CRef<CPubMedPubDate> entrez_date = s_FindPubDateStatus(
        pubmed_article.GetPubmedData().GetHistory().GetPubMedPubDate(),
        CPubMedPubDate::C_Attlist::eAttlist_PubStatus_entrez);
    if (!entrez_date) {
        entrez_date = s_FindPubDateStatus(
            pubmed_article.GetPubmedData().GetHistory().GetPubMedPubDate(),
            CPubMedPubDate::C_Attlist::eAttlist_PubStatus_pubmed);
    }
    if (entrez_date)
        medline_entry->SetEm(*s_GetDateFromPubMedPubDate(*entrez_date));
    medline_entry->SetCit(*s_GetCitation(pubmed_article));

    auto& cit = pubmed_article.GetMedlineCitation();
    if (cit.GetArticle().IsSetAbstract())
        medline_entry->SetAbstract(s_CleanupText(s_GetAbstractText(cit.GetArticle().GetAbstract())));
    if (cit.IsSetMeshHeadingList())
        s_FillMesh(medline_entry->SetMesh(), cit.GetMeshHeadingList());
    if (cit.IsSetChemicalList())
        s_FillChem(medline_entry->SetSubstance(), cit.GetChemicalList());
    if (cit.GetArticle().IsSetDataBankList())
        s_FillXref(medline_entry->SetXref(), cit.GetArticle().GetDataBankList());
    if (cit.GetArticle().IsSetGrantList())
        s_FillGrants(medline_entry->SetIdnum(), cit.GetArticle().GetGrantList());
    if (cit.IsSetGeneSymbolList())
        s_FillGenes(medline_entry->SetGene(), cit.GetGeneSymbolList());
    medline_entry->SetPmid(CPubMedId(NStr::StringToNumeric<TEntrezId>(cit.GetPMID().GetPMID(), NStr::fConvErr_NoThrow)));
    s_FillPubtypeList(medline_entry->SetPub_type(), cit.GetArticle().GetPublicationTypeList());

    CMedlineCitation::C_Attlist::TStatus status = cit.GetAttlist().GetStatus();
    if (status == CMedlineCitation::C_Attlist::eAttlist_Status_Publisher)
        medline_entry->SetStatus(medline_entry->eStatus_publisher);
    else if (status == CMedlineCitation::C_Attlist::eAttlist_Status_Completed ||
        status == CMedlineCitation::C_Attlist::eAttlist_Status_MEDLINE ||
        status == CMedlineCitation::C_Attlist::eAttlist_Status_OLDMEDLINE)
        medline_entry->SetStatus(medline_entry->eStatus_medline);
    else
        medline_entry->SetStatus(medline_entry->eStatus_premedline);
    return medline_entry;
};

END_LOCAL_NAMESPACE;


string s_CleanupText(string str)
{
    str = s_TranslateToAscii(utf8_to_wstring(str));
    for (char& cch : str) {
        if (cch == '\r' || cch == '\n' || cch == '\t')
            cch = ' ';
    }
    return str;
}


CRef<CDate> s_GetDateFromPubDate(const CPubDate& pub_date)
{
    static const char* s_SeasonTab[] = { "Winter", "Spring", "Summer", "Autumn" };
    pubmed_date_t pm_pub_date = s_GetPubmedDate(pub_date);
    CRef<CDate> date(new CDate());
    CDate_std& date_std = date->SetStd();
    date_std.SetYear(pm_pub_date._year);
    if (pm_pub_date._month != 0) {
        if (pm_pub_date._month < 13) {
            date_std.SetMonth(pm_pub_date._month);
            if (pm_pub_date._day != 0)
                date_std.SetDay(pm_pub_date._day);
        }
        else {
            date_std.SetSeason(s_SeasonTab[pm_pub_date._month - 13]);
        }
    }
    return date;
}


CRef<CDate> s_GetDateFromPubMedPubDate(const CPubMedPubDate& pdate)
{
    CRef<CDate> date(new CDate());
    try {
        // Try integer values
        CDate_std& std_date = date->SetStd();
        std_date.SetYear(NStr::StringToNumeric<CDate_std::TYear>(pdate.GetYear().Get()));
        std_date.SetMonth(NStr::StringToNumeric<CDate_std::TMonth>(pdate.GetMonth().Get()));
        std_date.SetDay(NStr::StringToNumeric<CDate_std::TDay>(pdate.GetDay().Get()));
        if (pdate.IsSetHM()) {
            try {
                // Try integer time, ignore on error
                auto& hm = pdate.GetHM();
                std_date.SetHour(NStr::StringToNumeric<CDate_std::THour>(hm.GetHour().Get()));
                if (hm.IsSetMS()) {
                    auto& ms = hm.GetMS();
                    std_date.SetMinute(NStr::StringToNumeric<CDate_std::TMinute>(ms.GetMinute().Get()));
                    if (ms.IsSetSecond()) {
                        std_date.SetSecond(NStr::StringToNumeric<CDate_std::TSecond>(ms.GetSecond().Get()));
                    }
                }
            }
            catch (...) {}
        }
    }
    catch (...) {
        // Use string values
        string str_date = pdate.GetYear();
        if (!pdate.GetMonth().Get().empty()) str_date += " " + pdate.GetMonth();
        if (!pdate.GetDay().Get().empty()) str_date += " " + pdate.GetDay();
        date->SetStr(str_date);
    }
    return date;
}


string s_GetArticleTitleStr(const CArticleTitle& article_title)
{
    return article_title.IsSetArticleTitle() ?
        s_TranslateToAscii(s_TextListToWstring(article_title.GetArticleTitle())) : "";
}


string s_GetVernacularTitleStr(const CVernacularTitle& vernacular_title)
{
    return s_TranslateToAscii(s_TextListToWstring(vernacular_title.Get()));
}


CRef<CTitle> s_MakeTitle(const string& title_str, const string& vernacular_title_str)
{
    CRef<CTitle> title;
    if (!title_str.empty() || !vernacular_title_str.empty()) {
        title.Reset(new CTitle());
        if (!title_str.empty()) {
            CRef<CTitle::C_E> name(new CTitle::C_E());
            name->SetName(title_str);
            title->Set().push_back(name);
        }
        if (!vernacular_title_str.empty()) {
            CRef<CTitle::C_E> name(new CTitle::C_E());
            name->SetTrans(vernacular_title_str);
            title->Set().push_back(name);
        }
    }
    return title;
}


string s_GetAuthorMedlineName(const CAuthor& author)
{
    wstring author_medline_name;
    if (author.GetLC().IsCollectiveName()) {
        author_medline_name = s_TextListToWstring(author.GetLC().GetCollectiveName().Get());
        if (!author_medline_name.empty() && author_medline_name.back() != L'.')
            author_medline_name.append(L".");
    }
    else if (author.GetLC().IsLFIS()) {
        // Personal name;
        auto& lfis = author.GetLC().GetLFIS();
        author_medline_name = utf8_to_wstring(lfis.GetLastName());
        // Initials
        wstring initials;
        if (lfis.IsSetInitials())
            initials = utf8_to_wstring(lfis.GetInitials());
        else if (lfis.IsSetForeName())
            initials = s_GetInitialsFromForeName(utf8_to_wstring(lfis.GetForeName()));
        if (!initials.empty())
            author_medline_name.append(L" " + initials);
        if (lfis.IsSetSuffix())
            author_medline_name.append(L" " + s_TextListToWstring(lfis.GetSuffix().Get()));
    }
    return s_TranslateToAscii(author_medline_name);
}


string s_GetPagination(const CPagination& pagination)
{
    if (pagination.IsSEM()) {
        auto& sem = pagination.GetSEM();
        if (sem.IsSetStartPage()) {
            if (sem.IsSetEndPage()) return sem.GetStartPage() + "-" + sem.GetEndPage();
            else return sem.GetStartPage();
        }
    }

    string pages = pagination.GetMedlinePgn();
    list<string> parts;
    s_ForeachToken(pages, [](char cch) -> bool { return cch != ','; },
        [&parts](string::iterator p, string::iterator q)->string::iterator {
        string x(p, q);
        x = regex_replace(x, regex("\\s+"), "");
        if (!x.empty()) {
            regex r("^(.*?)-(.*)$");
            smatch ma;
            regex_search(x, ma, r);
            if (ma.empty() || ma.str(1).length() <= ma.str(2).length())
                parts.push_back(x);
            else
                parts.push_back(ma.str(1) + "-" + ma.str(1).substr(0, ma.str(1).length() - ma.str(2).length()) + ma.str(2));
        }
        return q;
    });
    return parts.empty() ? "" : accumulate(next(parts.begin()), parts.end(), parts.front(),
            [](const string& s1, const string& s2)->string { return s1 + ',' + s2; });
}


CRef<CArticleIdSet> s_GetArticleIdSet(const CArticleIdList& article_id_list, const CArticle* article)
{
    CRef<CArticleIdSet> id_set(new CArticleIdSet());
    for (auto article_id_it : article_id_list.GetArticleId()) {
        CRef<objects::CArticleId> id(new objects::CArticleId());
        try {
            const string& str_id = article_id_it->GetArticleId();
            switch (s_GetArticleIdTypeId(*article_id_it)) {
            case objects::CArticleId::e_Pubmed:
                id->SetPubmed(CPubMedId(NStr::StringToNumeric<TEntrezId>(str_id)));
                break;
            case objects::CArticleId::e_Medline:
                continue;
            case objects::CArticleId::e_Doi:
                id->SetDoi(CDOI(str_id));
                break;
            case objects::CArticleId::e_Pii:
                id->SetPii(CPII(str_id));
                break;
            case objects::CArticleId::e_Pmcid:
                id->SetPmcid(CPmcID(NStr::StringToNumeric<TEntrezId>(str_id)));
                break;
            case objects::CArticleId::e_Pmcpid:
                id->SetPmcpid(CPmcPid(str_id));
                break;
            case objects::CArticleId::e_Pmpid:
                id->SetPmpid(CPmPid(str_id));
                break;
            case objects::CArticleId::e_Other: {
                string db = CArticleId::C_Attlist::GetTypeInfo_enum_EAttlist_IdType()->
                    FindName(article_id_it->GetAttlist().GetIdType(), false);
                CRef<CDbtag> db_tag(new CDbtag());
                db_tag->SetDb(db);
                CRef<CObject_id> obj_id(new CObject_id());
                obj_id->SetStr(str_id);
                db_tag->SetTag(*obj_id);
                id->SetOther(*db_tag);
                break;
            }
            default:
                continue;
            }
            id_set->Set().push_back(id);
        }
        catch (...) {}
    }
    if (article) {
        // JIRA: PM-966
        const list<CRef<CELocationID>>* eloc_ids = nullptr;
        if (article->GetPE_2().IsELocationID()) {
            eloc_ids = &article->GetPE_2().GetELocationID();
        }
        else {
            if (article->GetPE_2().GetPE().IsSetELocationID()) eloc_ids = &article->GetPE_2().GetPE().GetELocationID();
        }
        if (eloc_ids) {
            for (auto elocation_id_it : *eloc_ids) {
                string str_eid_type = CELocationID::C_Attlist::GetTypeInfo_enum_EAttlist_EIdType()->
                    FindName(elocation_id_it->GetAttlist().GetEIdType(), false);
                string type = "ELocationID " + str_eid_type;
                string value = elocation_id_it->GetELocationID();
                CRef<objects::CArticleId> id(new objects::CArticleId());
                CRef<CDbtag> db_tag(new CDbtag());
                db_tag->SetDb(type);
                CRef<CObject_id> obj_id(new CObject_id());
                obj_id->SetStr(value);
                db_tag->SetTag(*obj_id);
                id->SetOther(*db_tag);
                id_set->Set().push_back(id);
            }
        }
    }
    return id_set;
}


void s_FillGrants(list<string>& id_nums, const CGrantList& grant_list)
{
    for (auto grant_it : grant_list.GetGrant()) {
        wstring id;
        if (grant_it->IsSetGrantID())
            id = utf8_to_wstring(grant_it->GetGrantID());
        if (grant_it->IsSetAcronym())
            id += id.empty() ? utf8_to_wstring(grant_it->GetAcronym()) : L"/" + utf8_to_wstring(grant_it->GetAcronym());
        if (grant_it->IsSetAgency() && !grant_it->GetAgency().Get().empty())
            id += id.empty() ? utf8_to_wstring(grant_it->GetAgency()) : L"/" + utf8_to_wstring(grant_it->GetAgency());
        string id2 = s_TranslateToAscii(id);
        if (!id2.empty())
            id_nums.push_back(id2);
    }
}


CRef<CPubmed_entry> CPubmedArticle::ToPubmed_entry(void) const
{
    CRef<CPubmed_entry> pubmed_entry(new CPubmed_entry());

    pubmed_entry->SetPmid(CPubMedId(NStr::StringToNumeric<TEntrezId>(
        GetMedlineCitation().GetPMID().GetPMID(), NStr::fConvErr_NoThrow)));
    pubmed_entry->SetMedent(*s_GetMedlineEntry(*this));
    return pubmed_entry;
}


END_eutils_SCOPE // namespace eutils::

/* Original file checksum: lines: 53, chars: 1696, CRC32: 3b4b74a1 */
