123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701 |
- // Copyright (c) 2014-2021 Thomas Fussell
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to deal
- // in the Software without restriction, including without limitation the rights
- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- // copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- // THE SOFTWARE
- //
- // @license: http://www.opensource.org/licenses/mit-license.php
- // @author: see AUTHORS file
- #pragma once
- #include <string>
- #include <unordered_map>
- #include <vector>
- #include <xlnt/utils/datetime.hpp>
- #include <xlnt/utils/numeric.hpp>
- namespace xlnt {
- namespace detail {
- enum class format_color
- {
- black,
- blue,
- cyan,
- green,
- magenta,
- red,
- white,
- yellow,
- color1,
- color2,
- color3,
- color4,
- color5,
- color6,
- color7,
- color8,
- color9,
- color10,
- color11,
- color12,
- color13,
- color14,
- color15,
- color16,
- color17,
- color18,
- color19,
- color20,
- color21,
- color22,
- color23,
- color24,
- color25,
- color26,
- color27,
- color28,
- color29,
- color30,
- color31,
- color32,
- color33,
- color34,
- color35,
- color36,
- color37,
- color38,
- color39,
- color40,
- color41,
- color42,
- color43,
- color44,
- color45,
- color46,
- color47,
- color48,
- color49,
- color50,
- color51,
- color52,
- color53,
- color54,
- color55,
- color56
- };
- enum class format_locale
- {
- arabic = 0x1,
- bulgarian = 0x2,
- catalan = 0x3,
- chinese_simplified = 0x4,
- chinese_simplified_legacy = 0x4,
- czech = 0x5,
- danish = 0x6,
- german = 0x7,
- greek = 0x8,
- english = 0x9,
- spanish = 0xA,
- finnish = 0xB,
- french = 0xC,
- hebrew = 0xD,
- hungarian = 0xE,
- icelandic = 0xF,
- italian = 0x10,
- japanese = 0x11,
- korean = 0x12,
- dutch = 0x13,
- norwegian = 0x14,
- polish = 0x15,
- portuguese = 0x16,
- romansh = 0x17,
- romanian = 0x18,
- russian = 0x19,
- croatian = 0x1A,
- slovak = 0x1B,
- albanian = 0x1C,
- swedish = 0x1D,
- thai = 0x1E,
- turkish = 0x1F,
- urdu = 0x20,
- indonesian = 0x21,
- ukrainian = 0x22,
- belarusian = 0x23,
- slovenian = 0x24,
- estonian = 0x25,
- latvian = 0x26,
- lithuanian = 0x27,
- tajik = 0x28,
- persian = 0x29,
- vietnamese = 0x2A,
- armenian = 0x2B,
- azerbaijani = 0x2C,
- basque = 0x2D,
- upper_sorbian = 0x2E,
- macedonian_fyrom = 0x2F,
- southern_sotho = 0x30,
- tsonga = 0x31,
- setswana = 0x32,
- venda = 0x33,
- isixhosa = 0x34,
- isizulu = 0x35,
- afrikaans = 0x36,
- georgian = 0x37,
- faroese = 0x38,
- hindi = 0x39,
- maltese = 0x3A,
- sami_northern = 0x3B,
- irish = 0x3C,
- yiddish = 0x3D,
- malay = 0x3E,
- kazakh = 0x3F,
- kyrgyz = 0x40,
- kiswahili = 0x41,
- turkmen = 0x42,
- uzbek = 0x43,
- tatar = 0x44,
- bangla = 0x45,
- punjabi = 0x46,
- gujarati = 0x47,
- odia = 0x48,
- tamil = 0x49,
- telugu = 0x4A,
- kannada = 0x4B,
- malayalam = 0x4C,
- assamese = 0x4D,
- marathi = 0x4E,
- sanskrit = 0x4F,
- mongolian = 0x50,
- tibetan = 0x51,
- welsh = 0x52,
- khmer = 0x53,
- lao = 0x54,
- burmese = 0x55,
- galician = 0x56,
- konkani = 0x57,
- manipuri = 0x58,
- sindhi = 0x59,
- syriac = 0x5A,
- sinhala = 0x5B,
- cherokee = 0x5C,
- inuktitut = 0x5D,
- amharic = 0x5E,
- tamazight = 0x5F,
- kashmiri = 0x60,
- nepali = 0x61,
- frisian = 0x62,
- pashto = 0x63,
- filipino = 0x64,
- divehi = 0x65,
- edo = 0x66,
- fulah = 0x67,
- hausa = 0x68,
- ibibio = 0x69,
- yoruba = 0x6A,
- quechua = 0x6B,
- sesotho_sa_leboa = 0x6C,
- bashkir = 0x6D,
- luxembourgish = 0x6E,
- greenlandic = 0x6F,
- igbo = 0x70,
- kanuri = 0x71,
- oromo = 0x72,
- tigrinya = 0x73,
- guarani = 0x74,
- hawaiian = 0x75,
- latin = 0x76,
- somali = 0x77,
- yi = 0x78,
- papiamento = 0x79,
- mapudungun = 0x7A,
- mohawk = 0x7C,
- breton = 0x7E,
- invariant_language_invariant_country = 0x7F,
- uyghur = 0x80,
- maori = 0x81,
- occitan = 0x82,
- corsican = 0x83,
- alsatian = 0x84,
- sakha = 0x85,
- kiche = 0x86,
- kinyarwanda = 0x87,
- wolof = 0x88,
- dari = 0x8C,
- scottish_gaelic = 0x91,
- central_kurdish = 0x92,
- arabic_saudi_arabia = 0x401,
- bulgarian_bulgaria = 0x402,
- catalan_catalan = 0x403,
- chinese_traditional_taiwan = 0x404,
- czech_czech_republic = 0x405,
- danish_denmark = 0x406,
- german_germany = 0x407,
- greek_greece = 0x408,
- english_united_states = 0x409,
- finnish_finland = 0x40B,
- french_france = 0x40C,
- hebrew_israel = 0x40D,
- hungarian_hungary = 0x40E,
- icelandic_iceland = 0x40F,
- italian_italy = 0x410,
- japanese_japan = 0x411,
- korean_korea = 0x412,
- dutch_netherlands = 0x413,
- norwegian_bokml_norway = 0x414,
- polish_poland = 0x415,
- portuguese_brazil = 0x416,
- romansh_switzerland = 0x417,
- romanian_romania = 0x418,
- russian_russia = 0x419,
- croatian_croatia = 0x41A,
- slovak_slovakia = 0x41B,
- albanian_albania = 0x41C,
- swedish_sweden = 0x41D,
- thai_thailand = 0x41E,
- turkish_turkey = 0x41F,
- urdu_islamic_republic_of_pakistan = 0x420,
- indonesian_indonesia = 0x421,
- ukrainian_ukraine = 0x422,
- belarusian_belarus = 0x423,
- slovenian_slovenia = 0x424,
- estonian_estonia = 0x425,
- latvian_latvia = 0x426,
- lithuanian_lithuania = 0x427,
- tajik_cyrillic_tajikistan = 0x428,
- persian_iran = 0x429,
- vietnamese_vietnam = 0x42A,
- armenian_armenia = 0x42B,
- azerbaijani_latin_azerbaijan = 0x42C,
- basque_basque = 0x42D,
- upper_sorbian_germany = 0x42E,
- macedonian_former_yugoslav_republic_of_macedonia = 0x42F,
- southern_sotho_south_africa = 0x430,
- tsonga_south_africa = 0x431,
- setswana_south_africa = 0x432,
- venda_south_africa = 0x433,
- isixhosa_south_africa = 0x434,
- isizulu_south_africa = 0x435,
- afrikaans_south_africa = 0x436,
- georgian_georgia = 0x437,
- faroese_faroe_islands = 0x438,
- hindi_india = 0x439,
- maltese_malta = 0x43A,
- sami_northern_norway = 0x43B,
- yiddish_world = 0x43D,
- malay_malaysia = 0x43E,
- kazakh_kazakhstan = 0x43F,
- kyrgyz_kyrgyzstan = 0x440,
- kiswahili_kenya = 0x441,
- turkmen_turkmenistan = 0x442,
- uzbek_latin_uzbekistan = 0x443,
- tatar_russia = 0x444,
- bangla_india = 0x445,
- punjabi_india = 0x446,
- gujarati_india = 0x447,
- odia_india = 0x448,
- tamil_india = 0x449,
- telugu_india = 0x44A,
- kannada_india = 0x44B,
- malayalam_india = 0x44C,
- assamese_india = 0x44D,
- marathi_india = 0x44E,
- sanskrit_india = 0x44F,
- mongolian_cyrillic_mongolia = 0x450,
- tibetan_prc = 0x451,
- welsh_united_kingdom = 0x452,
- khmer_cambodia = 0x453,
- lao_lao_p_d_r = 0x454,
- burmese_myanmar = 0x455,
- galician_galician = 0x456,
- konkani_india = 0x457,
- manipuri_india = 0x458,
- sindhi_devanagari_india = 0x459,
- syriac_syria = 0x45A,
- sinhala_sri_lanka = 0x45B,
- cherokee_cherokee = 0x45C,
- inuktitut_syllabics_canada = 0x45D,
- amharic_ethiopia = 0x45E,
- central_atlas_tamazight_arabic_morocco = 0x45F,
- kashmiri_perso_arabic = 0x460,
- nepali_nepal = 0x461,
- frisian_netherlands = 0x462,
- pashto_afghanistan = 0x463,
- filipino_philippines = 0x464,
- divehi_maldives = 0x465,
- edo_nigeria = 0x466,
- fulah_nigeria = 0x467,
- hausa_latin_nigeria = 0x468,
- ibibio_nigeria = 0x469,
- yoruba_nigeria = 0x46A,
- quechua_bolivia = 0x46B,
- sesotho_sa_leboa_south_africa = 0x46C,
- bashkir_russia = 0x46D,
- luxembourgish_luxembourg = 0x46E,
- greenlandic_greenland = 0x46F,
- igbo_nigeria = 0x470,
- kanuri_nigeria = 0x471,
- oromo_ethiopia = 0x472,
- tigrinya_ethiopia = 0x473,
- guarani_paraguay = 0x474,
- hawaiian_united_states = 0x475,
- latin_world = 0x476,
- somali_somalia = 0x477,
- yi_prc = 0x478,
- papiamento_caribbean = 0x479,
- mapudungun_chile = 0x47A,
- mohawk_mohawk = 0x47C,
- breton_france = 0x47E,
- uyghur_prc = 0x480,
- maori_new_zealand = 0x481,
- occitan_france = 0x482,
- corsican_france = 0x483,
- alsatian_france = 0x484,
- sakha_russia = 0x485,
- kiche_guatemala = 0x486,
- kinyarwanda_rwanda = 0x487,
- wolof_senegal = 0x488,
- dari_afghanistan = 0x48C,
- scottish_gaelic_united_kingdom = 0x491,
- central_kurdish_iraq = 0x492,
- arabic_iraq = 0x801,
- valencian_spain = 0x803,
- chinese_simplified_prc = 0x804,
- german_switzerland = 0x807,
- english_united_kingdom = 0x809,
- spanish_mexico = 0x80A,
- french_belgium = 0x80C,
- italian_switzerland = 0x810,
- dutch_belgium = 0x813,
- norwegian_nynorsk_norway = 0x814,
- portuguese_portugal = 0x816,
- romanian_moldova = 0x818,
- russian_moldova = 0x819,
- swedish_finland = 0x81D,
- urdu_india = 0x820,
- azerbaijani_cyrillic_azerbaijan = 0x82C,
- lower_sorbian_germany = 0x82E,
- setswana_botswana = 0x832,
- sami_northern_sweden = 0x83B,
- irish_ireland = 0x83C,
- malay_brunei_darussalam = 0x83E,
- uzbek_cyrillic_uzbekistan = 0x843,
- bangla_bangladesh = 0x845,
- punjabi_islamic_republic_of_pakistan = 0x846,
- tamil_sri_lanka = 0x849,
- mongolian_traditional_mongolian_prc = 0x850,
- sindhi_islamic_republic_of_pakistan = 0x859,
- inuktitut_latin_canada = 0x85D,
- tamazight_latin_algeria = 0x85F,
- kashmiri_devanagari_india = 0x860,
- nepali_india = 0x861,
- fulah_latin_senegal = 0x867,
- quechua_ecuador = 0x86B,
- tigrinya_eritrea = 0x873,
- arabic_egypt = 0xC01,
- chinese_traditional_hong_kong_s_a_r = 0xC04,
- german_austria = 0xC07,
- english_australia = 0xC09,
- spanish_spain = 0xC0A,
- french_canada = 0xC0C,
- sami_northern_finland = 0xC3B,
- mongolian_traditional_mongolian_mongolia = 0xC50,
- dzongkha_bhutan = 0xC51,
- quechua_peru = 0xC6B,
- arabic_libya = 0x1001,
- chinese_simplified_singapore = 0x1004,
- german_luxembourg = 0x1007,
- english_canada = 0x1009,
- spanish_guatemala = 0x100A,
- french_switzerland = 0x100C,
- croatian_latin_bosnia_and_herzegovina = 0x101A,
- sami_lule_norway = 0x103B,
- central_atlas_tamazight_tifinagh_morocco = 0x105F,
- arabic_algeria = 0x1401,
- chinese_traditional_macao_s_a_r = 0x1404,
- german_liechtenstein = 0x1407,
- english_new_zealand = 0x1409,
- spanish_costa_rica = 0x140A,
- french_luxembourg = 0x140C,
- bosnian_latin_bosnia_and_herzegovina = 0x141A,
- sami_lule_sweden = 0x143B,
- arabic_morocco = 0x1801,
- english_ireland = 0x1809,
- spanish_panama = 0x180A,
- french_monaco = 0x180C,
- serbian_latin_bosnia_and_herzegovina = 0x181A,
- sami_southern_norway = 0x183B,
- arabic_tunisia = 0x1C01,
- english_south_africa = 0x1C09,
- spanish_dominican_republic = 0x1C0A,
- french_caribbean = 0x1C0C,
- serbian_cyrillic_bosnia_and_herzegovina = 0x1C1A,
- sami_southern_sweden = 0x1C3B,
- arabic_oman = 0x2001,
- english_jamaica = 0x2009,
- spanish_venezuela = 0x200A,
- french_reunion = 0x200C,
- bosnian_cyrillic_bosnia_and_herzegovina = 0x201A,
- sami_skolt_finland = 0x203B,
- arabic_yemen = 0x2401,
- english_caribbean = 0x2409,
- spanish_colombia = 0x240A,
- french_congo_drc = 0x240C,
- serbian_latin_serbia = 0x241A,
- sami_inari_finland = 0x243B,
- arabic_syria = 0x2801,
- english_belize = 0x2809,
- spanish_peru = 0x280A,
- french_senegal = 0x280C,
- serbian_cyrillic_serbia = 0x281A,
- arabic_jordan = 0x2C01,
- english_trinidad_and_tobago = 0x2C09,
- spanish_argentina = 0x2C0A,
- french_cameroon = 0x2C0C,
- serbian_latin_montenegro = 0x2C1A,
- arabic_lebanon = 0x3001,
- english_zimbabwe = 0x3009,
- spanish_ecuador = 0x300A,
- french_cote_divoire = 0x300C,
- serbian_cyrillic_montenegro = 0x301A,
- arabic_kuwait = 0x3401,
- english_philippines = 0x3409,
- spanish_chile = 0x340A,
- french_mali = 0x340C,
- arabic_u_a_e = 0x3801,
- english_indonesia = 0x3809,
- spanish_uruguay = 0x380A,
- french_morocco = 0x380C,
- arabic_bahrain = 0x3C01,
- english_hong_kong_sar = 0x3C09,
- spanish_paraguay = 0x3C0A,
- french_haiti = 0x3C0C,
- arabic_qatar = 0x4001,
- english_india = 0x4009,
- spanish_bolivia = 0x400A,
- english_malaysia = 0x4409,
- spanish_el_salvador = 0x440A,
- english_singapore = 0x4809,
- spanish_honduras = 0x480A,
- spanish_nicaragua = 0x4C0A,
- spanish_puerto_rico = 0x500A,
- spanish_united_states = 0x540A,
- spanish_latin_america = 0x580A,
- spanish_cuba = 0x5C0A,
- bosnian_cyrillic = 0x641A,
- bosnian_latin = 0x681A,
- serbian_cyrillic = 0x6C1A,
- serbian_latin = 0x701A,
- sami_inari = 0x703B,
- azerbaijani_cyrillic = 0x742C,
- sami_skolt = 0x743B,
- chinese = 0x7804,
- norwegian_nynorsk = 0x7814,
- bosnian = 0x781A,
- azerbaijani_latin = 0x782C,
- sami_southern = 0x783B,
- uzbek_cyrillic = 0x7843,
- mongolian_cyrillic = 0x7850,
- inuktitut_syllabics = 0x785D,
- tamazight_tifinagh = 0x785F,
- chinese_traditional = 0x7C04,
- chinese_traditional_legacy = 0x7C04,
- norwegian_bokml = 0x7C14,
- serbian = 0x7C1A,
- tajik_cyrillic = 0x7C28,
- lower_sorbian = 0x7C2E,
- sami_lule = 0x7C3B,
- uzbek_latin = 0x7C43,
- punjabi_arabic = 0x7C46,
- mongolian_traditional_mongolian = 0x7C50,
- sindhi_arabic = 0x7C59,
- inuktitut_latin = 0x7C5D,
- tamazight_latin = 0x7C5F,
- fulah_latin = 0x7C67,
- hausa_latin = 0x7C68,
- central_kurdish_arabic = 0x7C92,
- system_default_time = 0xF400,
- system_default_long_date = 0xF800
- };
- // TODO this really shouldn't be exported...
- struct XLNT_API format_condition
- {
- enum class condition_type
- {
- less_than,
- less_or_equal,
- equal,
- not_equal,
- greater_than,
- greater_or_equal
- } type = condition_type::not_equal;
- double value = 0.0;
- bool satisfied_by(double number) const;
- };
- struct format_placeholders
- {
- enum class placeholders_type
- {
- general,
- text,
- integer_only,
- integer_part,
- fractional_part,
- fraction_integer,
- fraction_numerator,
- fraction_denominator,
- scientific_significand,
- scientific_exponent_plus,
- scientific_exponent_minus
- } type = placeholders_type::general;
- bool use_comma_separator = false;
- bool percentage = false;
- bool scientific = false;
- std::size_t num_zeros = 0; // 0
- std::size_t num_optionals = 0; // #
- std::size_t num_spaces = 0; // ?
- std::size_t thousands_scale = 0;
- };
- struct number_format_token
- {
- enum class token_type
- {
- color,
- locale,
- condition,
- text,
- fill,
- space,
- number,
- datetime,
- end_section,
- end
- } type = token_type::end;
- std::string string;
- };
- struct template_part
- {
- enum class template_type
- {
- text,
- fill,
- space,
- general,
- month_number,
- month_number_leading_zero,
- month_abbreviation,
- month_name,
- month_letter,
- day_number,
- day_number_leading_zero,
- day_abbreviation,
- day_name,
- year_short,
- year_long,
- hour,
- hour_leading_zero,
- minute,
- minute_leading_zero,
- second,
- second_fractional,
- second_leading_zero,
- second_leading_zero_fractional,
- am_pm,
- a_p,
- elapsed_hours,
- elapsed_minutes,
- elapsed_seconds
- } type = template_type::general;
- std::string string;
- format_placeholders placeholders;
- };
- struct format_code
- {
- bool has_color = false;
- format_color color = format_color::black;
- bool has_locale = false;
- format_locale locale = format_locale::english_united_states;
- bool has_condition = false;
- format_condition condition;
- bool is_datetime = false;
- bool is_timedelta = false;
- bool twelve_hour = false;
- std::vector<template_part> parts;
- };
- class number_format_parser
- {
- public:
- number_format_parser(const std::string &format_string);
- const std::vector<format_code> &result() const;
- void reset(const std::string &format_string);
- void parse();
- private:
- void finalize();
- void validate();
- number_format_token parse_next_token();
- format_placeholders parse_placeholders(const std::string &placeholders_string);
- format_color color_from_string(const std::string &color);
- std::pair<format_locale, std::string> locale_from_string(const std::string &locale_string);
- std::size_t position_ = 0;
- std::string format_string_;
- std::vector<format_code> codes_;
- };
- class XLNT_API number_formatter
- {
- public:
- number_formatter(const std::string &format_string, xlnt::calendar calendar);
- std::string format_number(double number);
- std::string format_text(const std::string &text);
- private:
- std::string fill_placeholders(const format_placeholders &p, double number);
- std::string fill_fraction_placeholders(const format_placeholders &numerator,
- const format_placeholders &denominator, double number, bool improper);
- std::string fill_scientific_placeholders(const format_placeholders &integer_part,
- const format_placeholders &fractional_part, const format_placeholders &exponent_part,
- double number);
- std::string format_number(const format_code &format, double number);
- std::string format_text(const format_code &format, const std::string &text);
- number_format_parser parser_;
- std::vector<format_code> format_;
- xlnt::calendar calendar_;
- xlnt::detail::number_serialiser serialiser_;
- };
- } // namespace detail
- } // namespace xlnt
|