countries_instance.cpp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530
  1. /*
  2. This file is part of Telegram Desktop,
  3. the official desktop application for the Telegram messaging service.
  4. For license and copyright information please follow this link:
  5. https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
  6. */
  7. #include "countries/countries_instance.h"
  8. #include "base/qt/qt_common_adapters.h"
  9. #include "base/qt/qt_string_view.h"
  10. namespace Countries {
  11. namespace {
  12. auto SingleInstance = CountriesInstance();
  13. const std::array<Info, 231> FallbackList = { {
  14. { "Andorra", "AD", "", { CallingCodeInfo{ "376", {}, { "XX XX XX" } } }, false },
  15. { "United Arab Emirates", "AE", "", { CallingCodeInfo{ "971", {}, { "XX XXX XXXX" } } }, false },
  16. { "Afghanistan", "AF", "", { CallingCodeInfo{ "93", {}, { "XXX XXX XXX" } } }, false },
  17. { "Antigua & Barbuda", "AG", "", { CallingCodeInfo{ "1268", {}, { "XXX XXXX" } } }, false },
  18. { "Anguilla", "AI", "", { CallingCodeInfo{ "1264", {}, { "XXX XXXX" } } }, false },
  19. { "Albania", "AL", "", { CallingCodeInfo{ "355", {}, { "XX XXX XXXX" } } }, false },
  20. { "Armenia", "AM", "", { CallingCodeInfo{ "374", {}, { "XX XXX XXX" } } }, false },
  21. { "Angola", "AO", "", { CallingCodeInfo{ "244", {}, { "XXX XXX XXX" } } }, false },
  22. { "Argentina", "AR", "", { CallingCodeInfo{ "54", {}, {} } }, false },
  23. { "American Samoa", "AS", "", { CallingCodeInfo{ "1684", {}, { "XXX XXXX" } } }, false },
  24. { "Austria", "AT", "", { CallingCodeInfo{ "43", {}, { "X XXXXXXXX" } } }, false },
  25. { "Australia", "AU", "", { CallingCodeInfo{ "61", {}, { "X XXXX XXXX" } } }, false },
  26. { "Aruba", "AW", "", { CallingCodeInfo{ "297", {}, { "XXX XXXX" } } }, false },
  27. { "Azerbaijan", "AZ", "", { CallingCodeInfo{ "994", {}, { "XX XXX XXXX" } } }, false },
  28. { "Bosnia & Herzegovina", "BA", "", { CallingCodeInfo{ "387", {}, { "XX XXX XXX" } } }, false },
  29. { "Barbados", "BB", "", { CallingCodeInfo{ "1246", {}, { "XXX XXXX" } } }, false },
  30. { "Bangladesh", "BD", "", { CallingCodeInfo{ "880", {}, { "XX XXX XXX" } } }, false },
  31. { "Belgium", "BE", "", { CallingCodeInfo{ "32", {}, { "XXX XX XX XX" } } }, false },
  32. { "Burkina Faso", "BF", "", { CallingCodeInfo{ "226", {}, { "XX XX XX XX" } } }, false },
  33. { "Bulgaria", "BG", "", { CallingCodeInfo{ "359", {}, {} } }, false },
  34. { "Bahrain", "BH", "", { CallingCodeInfo{ "973", {}, { "XXXX XXXX" } } }, false },
  35. { "Burundi", "BI", "", { CallingCodeInfo{ "257", {}, { "XX XX XXXX" } } }, false },
  36. { "Benin", "BJ", "", { CallingCodeInfo{ "229", {}, { "XX XXX XXX" } } }, false },
  37. { "Bermuda", "BM", "", { CallingCodeInfo{ "1441", {}, { "XXX XXXX" } } }, false },
  38. { "Brunei Darussalam", "BN", "", { CallingCodeInfo{ "673", {}, { "XXX XXXX" } } }, false },
  39. { "Bolivia", "BO", "", { CallingCodeInfo{ "591", {}, { "X XXX XXXX" } } }, false },
  40. { "Bonaire, Sint Eustatius & Saba", "BQ", "", { CallingCodeInfo{ "599", {}, {} } }, false },
  41. { "Brazil", "BR", "", { CallingCodeInfo{ "55", {}, { "XX XXXXX XXXX" } } }, false },
  42. { "Bahamas", "BS", "", { CallingCodeInfo{ "1242", {}, { "XXX XXXX" } } }, false },
  43. { "Bhutan", "BT", "", { CallingCodeInfo{ "975", {}, { "XX XXX XXX" } } }, false },
  44. { "Botswana", "BW", "", { CallingCodeInfo{ "267", {}, { "XX XXX XXX" } } }, false },
  45. { "Belarus", "BY", "", { CallingCodeInfo{ "375", {}, { "XX XXX XXXX" } } }, false },
  46. { "Belize", "BZ", "", { CallingCodeInfo{ "501", {}, {} } }, false },
  47. { "Canada", "CA", "", { CallingCodeInfo{ "1", { "403" }, { "XXX XXX XXXX" } } }, false },
  48. { "Congo (Dem. Rep.)", "CD", "", { CallingCodeInfo{ "243", {}, { "XX XXX XXXX" } } }, false },
  49. { "Central African Rep.", "CF", "", { CallingCodeInfo{ "236", {}, { "XX XX XX XX" } } }, false },
  50. { "Congo (Rep.)", "CG", "", { CallingCodeInfo{ "242", {}, { "XX XXX XXXX" } } }, false },
  51. { "Switzerland", "CH", "", { CallingCodeInfo{ "41", {}, { "XX XXX XXXX" } } }, false },
  52. { "Côte d'Ivoire", "CI", "", { CallingCodeInfo{ "225", {}, { "XX XX XX XXXX" } } }, false },
  53. { "Cook Islands", "CK", "", { CallingCodeInfo{ "682", {}, {} } }, false },
  54. { "Chile", "CL", "", { CallingCodeInfo{ "56", {}, { "X XXXX XXXX" } } }, false },
  55. { "Cameroon", "CM", "", { CallingCodeInfo{ "237", {}, { "XXXX XXXX" } } }, false },
  56. { "China", "CN", "", { CallingCodeInfo{ "86", {}, { "XXX XXXX XXXX" } } }, false },
  57. { "Colombia", "CO", "", { CallingCodeInfo{ "57", {}, { "XXX XXX XXXX" } } }, false },
  58. { "Costa Rica", "CR", "", { CallingCodeInfo{ "506", {}, { "XXXX XXXX" } } }, false },
  59. { "Cuba", "CU", "", { CallingCodeInfo{ "53", {}, { "X XXX XXXX" } } }, false },
  60. { "Cape Verde", "CV", "", { CallingCodeInfo{ "238", {}, { "XXX XXXX" } } }, false },
  61. { "Curaçao", "CW", "", { CallingCodeInfo{ "599", { "9" }, {} } }, false },
  62. { "Cyprus", "CY", "", { CallingCodeInfo{ "357", {}, { "XXXX XXXX" } } }, false },
  63. { "Czech Republic", "CZ", "", { CallingCodeInfo{ "420", {}, { "XXX XXX XXX" } } }, false },
  64. { "Germany", "DE", "", { CallingCodeInfo{ "49", {}, { "XXXX XXXXXXX" } } }, false },
  65. { "Djibouti", "DJ", "", { CallingCodeInfo{ "253", {}, { "XX XX XX XX" } } }, false },
  66. { "Denmark", "DK", "", { CallingCodeInfo{ "45", {}, { "XXXX XXXX" } } }, false },
  67. { "Dominica", "DM", "", { CallingCodeInfo{ "1767", {}, { "XXX XXXX" } } }, false },
  68. { "Dominican Rep.", "DO", "", { CallingCodeInfo{ "1809", {}, { "XXX XXXX" } } }, false },
  69. { "Algeria", "DZ", "", { CallingCodeInfo{ "213", {}, { "XXX XX XX XX" } } }, false },
  70. { "Ecuador", "EC", "", { CallingCodeInfo{ "593", {}, { "XX XXX XXXX" } } }, false },
  71. { "Estonia", "EE", "", { CallingCodeInfo{ "372", {}, { "XXXX XXXX" } } }, false },
  72. { "Egypt", "EG", "", { CallingCodeInfo{ "20", {}, { "XX XXXX XXXX" } } }, false },
  73. { "Eritrea", "ER", "", { CallingCodeInfo{ "291", {}, { "X XXX XXX" } } }, false },
  74. { "Spain", "ES", "", { CallingCodeInfo{ "34", {}, { "XXX XXX XXX" } } }, false },
  75. { "Ethiopia", "ET", "", { CallingCodeInfo{ "251", {}, { "XX XXX XXXX" } } }, false },
  76. { "Finland", "FI", "", { CallingCodeInfo{ "358", {}, {} } }, false },
  77. { "Fiji", "FJ", "", { CallingCodeInfo{ "679", {}, { "XXX XXXX" } } }, false },
  78. { "Falkland Islands", "FK", "", { CallingCodeInfo{ "500", {}, {} } }, false },
  79. { "Micronesia", "FM", "", { CallingCodeInfo{ "691", {}, {} } }, false },
  80. { "Faroe Islands", "FO", "", { CallingCodeInfo{ "298", {}, { "XXX XXX" } } }, false },
  81. { "France", "FR", "", { CallingCodeInfo{ "33", {}, { "X XX XX XX XX" } } }, false },
  82. { "Gabon", "GA", "", { CallingCodeInfo{ "241", {}, { "X XX XX XX" } } }, false },
  83. { "United Kingdom", "GB", "", { CallingCodeInfo{ "44", {}, { "XXXX XXXXXX" } } }, false },
  84. { "Grenada", "GD", "", { CallingCodeInfo{ "1473", {}, { "XXX XXXX" } } }, false },
  85. { "Georgia", "GE", "", { CallingCodeInfo{ "995", {}, { "XXX XXX XXX" } } }, false },
  86. { "French Guiana", "GF", "", { CallingCodeInfo{ "594", {}, {} } }, false },
  87. { "Ghana", "GH", "", { CallingCodeInfo{ "233", {}, { "XX XXX XXXX" } } }, false },
  88. { "Gibraltar", "GI", "", { CallingCodeInfo{ "350", {}, { "XXXX XXXX" } } }, false },
  89. { "Greenland", "GL", "", { CallingCodeInfo{ "299", {}, { "XXX XXX" } } }, false },
  90. { "Gambia", "GM", "", { CallingCodeInfo{ "220", {}, { "XXX XXXX" } } }, false },
  91. { "Guinea", "GN", "", { CallingCodeInfo{ "224", {}, { "XXX XXX XXX" } } }, false },
  92. { "Guadeloupe", "GP", "", { CallingCodeInfo{ "590", {}, { "XXX XX XX XX" } } }, false },
  93. { "Equatorial Guinea", "GQ", "", { CallingCodeInfo{ "240", {}, { "XXX XXX XXX" } } }, false },
  94. { "Greece", "GR", "", { CallingCodeInfo{ "30", {}, { "XXX XXX XXXX" } } }, false },
  95. { "Guatemala", "GT", "", { CallingCodeInfo{ "502", {}, { "X XXX XXXX" } } }, false },
  96. { "Guam", "GU", "", { CallingCodeInfo{ "1671", {}, { "XXX XXXX" } } }, false },
  97. { "Guinea-Bissau", "GW", "", { CallingCodeInfo{ "245", {}, { "XXX XXXX" } } }, false },
  98. { "Guyana", "GY", "", { CallingCodeInfo{ "592", {}, {} } }, false },
  99. { "Hong Kong", "HK", "", { CallingCodeInfo{ "852", {}, { "X XXX XXXX" } } }, false },
  100. { "Honduras", "HN", "", { CallingCodeInfo{ "504", {}, { "XXXX XXXX" } } }, false },
  101. { "Croatia", "HR", "", { CallingCodeInfo{ "385", {}, { "XX XXX XXX" } } }, false },
  102. { "Haiti", "HT", "", { CallingCodeInfo{ "509", {}, { "XXXX XXXX" } } }, false },
  103. { "Hungary", "HU", "", { CallingCodeInfo{ "36", {}, { "XXX XXX XXX" } } }, false },
  104. { "Indonesia", "ID", "", { CallingCodeInfo{ "62", {}, { "XXX XXXXXX" } } }, false },
  105. { "Ireland", "IE", "", { CallingCodeInfo{ "353", {}, { "XX XXX XXXX" } } }, false },
  106. { "Israel", "IL", "", { CallingCodeInfo{ "972", {}, { "XX XXX XXXX" } } }, false },
  107. { "India", "IN", "", { CallingCodeInfo{ "91", {}, { "XXXXX XXXXX" } } }, false },
  108. { "Diego Garcia", "IO", "", { CallingCodeInfo{ "246", {}, { "XXX XXXX" } } }, false },
  109. { "Iraq", "IQ", "", { CallingCodeInfo{ "964", {}, { "XXX XXX XXXX" } } }, false },
  110. { "Iran", "IR", "", { CallingCodeInfo{ "98", {}, { "XXX XXX XXXX" } } }, false },
  111. { "Iceland", "IS", "", { CallingCodeInfo{ "354", {}, { "XXX XXXX" } } }, false },
  112. { "Italy", "IT", "", { CallingCodeInfo{ "39", {}, { "XXX XXX XXX" } } }, false },
  113. { "Jamaica", "JM", "", { CallingCodeInfo{ "1876", {}, { "XXX XXXX" } } }, false },
  114. { "Jordan", "JO", "", { CallingCodeInfo{ "962", {}, { "X XXXX XXXX" } } }, false },
  115. { "Japan", "JP", "", { CallingCodeInfo{ "81", {}, { "XX XXXX XXXX" } } }, false },
  116. { "Kenya", "KE", "", { CallingCodeInfo{ "254", {}, { "XXX XXX XXX" } } }, false },
  117. { "Kyrgyzstan", "KG", "", { CallingCodeInfo{ "996", {}, { "XXX XXXXXX" } } }, false },
  118. { "Cambodia", "KH", "", { CallingCodeInfo{ "855", {}, { "XX XXX XXX" } } }, false },
  119. { "Kiribati", "KI", "", { CallingCodeInfo{ "686", {}, { "XXXX XXXX" } } }, false },
  120. { "Comoros", "KM", "", { CallingCodeInfo{ "269", {}, { "XXX XXXX" } } }, false },
  121. { "Saint Kitts & Nevis", "KN", "", { CallingCodeInfo{ "1869", {}, { "XXX XXXX" } } }, false },
  122. { "North Korea", "KP", "", { CallingCodeInfo{ "850", {}, {} } }, false },
  123. { "South Korea", "KR", "", { CallingCodeInfo{ "82", {}, { "XX XXXX XXX" } } }, false },
  124. { "Kuwait", "KW", "", { CallingCodeInfo{ "965", {}, { "XXXX XXXX" } } }, false },
  125. { "Cayman Islands", "KY", "", { CallingCodeInfo{ "1345", {}, { "XXX XXXX" } } }, false },
  126. { "Kazakhstan", "KZ", "", { CallingCodeInfo{ "7", { "6" }, { "XXX XXX XX XX" } } }, false },
  127. { "Laos", "LA", "", { CallingCodeInfo{ "856", {}, { "XX XX XXX XXX" } } }, false },
  128. { "Lebanon", "LB", "", { CallingCodeInfo{ "961", {}, { "XX XXX XXX" } } }, false },
  129. { "Saint Lucia", "LC", "", { CallingCodeInfo{ "1758", {}, { "XXX XXXX" } } }, false },
  130. { "Liechtenstein", "LI", "", { CallingCodeInfo{ "423", {}, { "XXX XXXX" } } }, false },
  131. { "Sri Lanka", "LK", "", { CallingCodeInfo{ "94", {}, { "XX XXX XXXX" } } }, false },
  132. { "Liberia", "LR", "", { CallingCodeInfo{ "231", {}, { "XX XXX XXXX" } } }, false },
  133. { "Lesotho", "LS", "", { CallingCodeInfo{ "266", {}, { "XX XXX XXX" } } }, false },
  134. { "Lithuania", "LT", "", { CallingCodeInfo{ "370", {}, { "XXX XXXXX" } } }, false },
  135. { "Luxembourg", "LU", "", { CallingCodeInfo{ "352", {}, { "XXX XXX XXX" } } }, false },
  136. { "Latvia", "LV", "", { CallingCodeInfo{ "371", {}, { "XXX XXXXX" } } }, false },
  137. { "Libya", "LY", "", { CallingCodeInfo{ "218", {}, { "XX XXX XXXX" } } }, false },
  138. { "Morocco", "MA", "", { CallingCodeInfo{ "212", {}, { "XX XXX XXXX" } } }, false },
  139. { "Monaco", "MC", "", { CallingCodeInfo{ "377", {}, { "XXXX XXXX" } } }, false },
  140. { "Moldova", "MD", "", { CallingCodeInfo{ "373", {}, { "XX XXX XXX" } } }, false },
  141. { "Montenegro", "ME", "", { CallingCodeInfo{ "382", {}, {} } }, false },
  142. { "Madagascar", "MG", "", { CallingCodeInfo{ "261", {}, { "XX XX XXX XX" } } }, false },
  143. { "Marshall Islands", "MH", "", { CallingCodeInfo{ "692", {}, {} } }, false },
  144. { "North Macedonia", "MK", "", { CallingCodeInfo{ "389", {}, { "XX XXX XXX" } } }, false },
  145. { "Mali", "ML", "", { CallingCodeInfo{ "223", {}, { "XXXX XXXX" } } }, false },
  146. { "Myanmar", "MM", "", { CallingCodeInfo{ "95", {}, {} } }, false },
  147. { "Mongolia", "MN", "", { CallingCodeInfo{ "976", {}, { "XX XX XXXX" } } }, false },
  148. { "Macau", "MO", "", { CallingCodeInfo{ "853", {}, { "XXXX XXXX" } } }, false },
  149. { "Northern Mariana Islands", "MP", "", { CallingCodeInfo{ "1670", {}, { "XXX XXXX" } } }, false },
  150. { "Martinique", "MQ", "", { CallingCodeInfo{ "596", {}, {} } }, false },
  151. { "Mauritania", "MR", "", { CallingCodeInfo{ "222", {}, { "XXXX XXXX" } } }, false },
  152. { "Montserrat", "MS", "", { CallingCodeInfo{ "1664", {}, { "XXX XXXX" } } }, false },
  153. { "Malta", "MT", "", { CallingCodeInfo{ "356", {}, { "XX XX XX XX" } } }, false },
  154. { "Mauritius", "MU", "", { CallingCodeInfo{ "230", {}, { "XXXX XXXX" } } }, false },
  155. { "Maldives", "MV", "", { CallingCodeInfo{ "960", {}, { "XXX XXXX" } } }, false },
  156. { "Malawi", "MW", "", { CallingCodeInfo{ "265", {}, { "XX XXX XXXX" } } }, false },
  157. { "Mexico", "MX", "", { CallingCodeInfo{ "52", {}, {} } }, false },
  158. { "Malaysia", "MY", "", { CallingCodeInfo{ "60", {}, { "XX XXXX XXXX" } } }, false },
  159. { "Mozambique", "MZ", "", { CallingCodeInfo{ "258", {}, { "XX XXX XXXX" } } }, false },
  160. { "Namibia", "NA", "", { CallingCodeInfo{ "264", {}, { "XX XXX XXXX" } } }, false },
  161. { "New Caledonia", "NC", "", { CallingCodeInfo{ "687", {}, {} } }, false },
  162. { "Niger", "NE", "", { CallingCodeInfo{ "227", {}, { "XX XX XX XX" } } }, false },
  163. { "Norfolk Island", "NF", "", { CallingCodeInfo{ "672", {}, {} } }, false },
  164. { "Nigeria", "NG", "", { CallingCodeInfo{ "234", {}, { "XX XXXX XXXX" } } }, false },
  165. { "Nicaragua", "NI", "", { CallingCodeInfo{ "505", {}, { "XXXX XXXX" } } }, false },
  166. { "Netherlands", "NL", "", { CallingCodeInfo{ "31", {}, { "X XX XX XX XX" } } }, false },
  167. { "Norway", "NO", "", { CallingCodeInfo{ "47", {}, { "XXXX XXXX" } } }, false },
  168. { "Nepal", "NP", "", { CallingCodeInfo{ "977", {}, { "XX XXXX XXXX" } } }, false },
  169. { "Nauru", "NR", "", { CallingCodeInfo{ "674", {}, {} } }, false },
  170. { "Niue", "NU", "", { CallingCodeInfo{ "683", {}, {} } }, false },
  171. { "New Zealand", "NZ", "", { CallingCodeInfo{ "64", {}, { "XXXX XXXX" } } }, false },
  172. { "Oman", "OM", "", { CallingCodeInfo{ "968", {}, { "XXXX XXXX" } } }, false },
  173. { "Panama", "PA", "", { CallingCodeInfo{ "507", {}, { "XXXX XXXX" } } }, false },
  174. { "Peru", "PE", "", { CallingCodeInfo{ "51", {}, { "XXX XXX XXX" } } }, false },
  175. { "French Polynesia", "PF", "", { CallingCodeInfo{ "689", {}, {} } }, false },
  176. { "Papua New Guinea", "PG", "", { CallingCodeInfo{ "675", {}, {} } }, false },
  177. { "Philippines", "PH", "", { CallingCodeInfo{ "63", {}, { "XXX XXX XXXX" } } }, false },
  178. { "Pakistan", "PK", "", { CallingCodeInfo{ "92", {}, { "XXX XXX XXXX" } } }, false },
  179. { "Poland", "PL", "", { CallingCodeInfo{ "48", {}, { "XXX XXX XXX" } } }, false },
  180. { "Saint Pierre & Miquelon", "PM", "", { CallingCodeInfo{ "508", {}, {} } }, false },
  181. { "Puerto Rico", "PR", "", { CallingCodeInfo{ "1787", {}, { "XXX XXXX" } } }, false },
  182. { "Palestine", "PS", "", { CallingCodeInfo{ "970", {}, { "XXX XX XXXX" } } }, false },
  183. { "Portugal", "PT", "", { CallingCodeInfo{ "351", {}, { "XXX XXX XXX" } } }, false },
  184. { "Palau", "PW", "", { CallingCodeInfo{ "680", {}, {} } }, false },
  185. { "Paraguay", "PY", "", { CallingCodeInfo{ "595", {}, { "XXX XXX XXX" } } }, false },
  186. { "Qatar", "QA", "", { CallingCodeInfo{ "974", {}, { "XX XXX XXX" } } }, false },
  187. { "Réunion", "RE", "", { CallingCodeInfo{ "262", {}, { "XXX XXX XXX" } } }, false },
  188. { "Romania", "RO", "", { CallingCodeInfo{ "40", {}, { "XXX XXX XXX" } } }, false },
  189. { "Serbia", "RS", "", { CallingCodeInfo{ "381", {}, { "XX XXX XXXX" } } }, false },
  190. { "Russian Federation", "RU", "", { CallingCodeInfo{ "7", {}, { "XXX XXX XXXX" } } }, false },
  191. { "Rwanda", "RW", "", { CallingCodeInfo{ "250", {}, { "XXX XXX XXX" } } }, false },
  192. { "Saudi Arabia", "SA", "", { CallingCodeInfo{ "966", {}, { "XX XXX XXXX" } } }, false },
  193. { "Solomon Islands", "SB", "", { CallingCodeInfo{ "677", {}, {} } }, false },
  194. { "Seychelles", "SC", "", { CallingCodeInfo{ "248", {}, { "X XX XX XX" } } }, false },
  195. { "Sudan", "SD", "", { CallingCodeInfo{ "249", {}, { "XX XXX XXXX" } } }, false },
  196. { "Sweden", "SE", "", { CallingCodeInfo{ "46", {}, { "XX XXX XXXX" } } }, false },
  197. { "Singapore", "SG", "", { CallingCodeInfo{ "65", {}, { "XXXX XXXX" } } }, false },
  198. { "Saint Helena", "SH", "", { CallingCodeInfo{ "247", {}, {} } }, false },
  199. { "Slovenia", "SI", "", { CallingCodeInfo{ "386", {}, { "XX XXX XXX" } } }, false },
  200. { "Slovakia", "SK", "", { CallingCodeInfo{ "421", {}, { "XXX XXX XXX" } } }, false },
  201. { "Sierra Leone", "SL", "", { CallingCodeInfo{ "232", {}, { "XX XXX XXX" } } }, false },
  202. { "San Marino", "SM", "", { CallingCodeInfo{ "378", {}, { "XXX XXX XXXX" } } }, false },
  203. { "Senegal", "SN", "", { CallingCodeInfo{ "221", {}, { "XX XXX XXXX" } } }, false },
  204. { "Somalia", "SO", "", { CallingCodeInfo{ "252", {}, { "XX XXX XXX" } } }, false },
  205. { "Suriname", "SR", "", { CallingCodeInfo{ "597", {}, { "XXX XXXX" } } }, false },
  206. { "South Sudan", "SS", "", { CallingCodeInfo{ "211", {}, { "XX XXX XXXX" } } }, false },
  207. { "São Tomé & Príncipe", "ST", "", { CallingCodeInfo{ "239", {}, { "XX XXXXX" } } }, false },
  208. { "El Salvador", "SV", "", { CallingCodeInfo{ "503", {}, { "XXXX XXXX" } } }, false },
  209. { "Sint Maarten", "SX", "", { CallingCodeInfo{ "1721", {}, { "XXX XXXX" } } }, false },
  210. { "Syria", "SY", "", { CallingCodeInfo{ "963", {}, { "XXX XXX XXX" } } }, false },
  211. { "Eswatini", "SZ", "", { CallingCodeInfo{ "268", {}, { "XXXX XXXX" } } }, false },
  212. { "Turks & Caicos Islands", "TC", "", { CallingCodeInfo{ "1649", {}, { "XXX XXXX" } } }, false },
  213. { "Chad", "TD", "", { CallingCodeInfo{ "235", {}, { "XX XX XX XX" } } }, false },
  214. { "Togo", "TG", "", { CallingCodeInfo{ "228", {}, { "XX XXX XXX" } } }, false },
  215. { "Thailand", "TH", "", { CallingCodeInfo{ "66", {}, { "X XXXX XXXX" } } }, false },
  216. { "Tajikistan", "TJ", "", { CallingCodeInfo{ "992", {}, { "XX XXX XXXX" } } }, false },
  217. { "Tokelau", "TK", "", { CallingCodeInfo{ "690", {}, {} } }, false },
  218. { "Timor-Leste", "TL", "", { CallingCodeInfo{ "670", {}, {} } }, false },
  219. { "Turkmenistan", "TM", "", { CallingCodeInfo{ "993", {}, { "XX XXXXXX" } } }, false },
  220. { "Tunisia", "TN", "", { CallingCodeInfo{ "216", {}, { "XX XXX XXX" } } }, false },
  221. { "Tonga", "TO", "", { CallingCodeInfo{ "676", {}, {} } }, false },
  222. { "Turkey", "TR", "", { CallingCodeInfo{ "90", {}, { "XXX XXX XXXX" } } }, false },
  223. { "Trinidad & Tobago", "TT", "", { CallingCodeInfo{ "1868", {}, { "XXX XXXX" } } }, false },
  224. { "Tuvalu", "TV", "", { CallingCodeInfo{ "688", {}, {} } }, false },
  225. { "Taiwan", "TW", "", { CallingCodeInfo{ "886", {}, { "XXX XXX XXX" } } }, false },
  226. { "Tanzania", "TZ", "", { CallingCodeInfo{ "255", {}, { "XX XXX XXXX" } } }, false },
  227. { "Ukraine", "UA", "", { CallingCodeInfo{ "380", {}, { "XX XXX XX XX" } } }, false },
  228. { "Uganda", "UG", "", { CallingCodeInfo{ "256", {}, { "XX XXX XXXX" } } }, false },
  229. { "USA", "US", "United States of America", { CallingCodeInfo{ "1", {}, { "XXX XXX XXXX" } } }, false },
  230. { "Uruguay", "UY", "", { CallingCodeInfo{ "598", {}, { "X XXX XXXX" } } }, false },
  231. { "Uzbekistan", "UZ", "", { CallingCodeInfo{ "998", {}, { "XX XXX XX XX" } } }, false },
  232. { "Saint Vincent & the Grenadines", "VC", "", { CallingCodeInfo{ "1784", {}, { "XXX XXXX" } } }, false },
  233. { "Venezuela", "VE", "", { CallingCodeInfo{ "58", {}, { "XXX XXX XXXX" } } }, false },
  234. { "British Virgin Islands", "VG", "", { CallingCodeInfo{ "1284", {}, { "XXX XXXX" } } }, false },
  235. { "US Virgin Islands", "VI", "", { CallingCodeInfo{ "1340", {}, { "XXX XXXX" } } }, false },
  236. { "Vietnam", "VN", "", { CallingCodeInfo{ "84", {}, {} } }, false },
  237. { "Vanuatu", "VU", "", { CallingCodeInfo{ "678", {}, {} } }, false },
  238. { "Wallis & Futuna", "WF", "", { CallingCodeInfo{ "681", {}, {} } }, false },
  239. { "Samoa", "WS", "", { CallingCodeInfo{ "685", {}, {} } }, false },
  240. { "Kosovo", "XK", "", { CallingCodeInfo{ "383", {}, { "XXXX XXXX" } } }, false },
  241. { "Yemen", "YE", "", { CallingCodeInfo{ "967", {}, { "XXX XXX XXX" } } }, false },
  242. { "South Africa", "ZA", "", { CallingCodeInfo{ "27", {}, { "XX XXX XXXX" } } }, false },
  243. { "Zambia", "ZM", "", { CallingCodeInfo{ "260", {}, { "XX XXX XXXX" } } }, false },
  244. { "Zimbabwe", "ZW", "", { CallingCodeInfo{ "263", {}, { "XX XXX XXXX" } } }, false },
  245. } };
  246. } // namespace
  247. CountriesInstance::CountriesInstance() {
  248. }
  249. const std::vector<Info> &CountriesInstance::list() const {
  250. if (_list.empty()) {
  251. _list = (FallbackList | ranges::to_vector);
  252. }
  253. return _list;
  254. }
  255. void CountriesInstance::setList(std::vector<Info> &&infos) {
  256. _list = std::move(infos);
  257. _byCode.clear();
  258. _byISO2.clear();
  259. _updated.fire({});
  260. }
  261. const CountriesInstance::Map &CountriesInstance::byCode() const {
  262. if (_byCode.empty()) {
  263. _byCode.reserve(list().size());
  264. for (const auto &entry : list()) {
  265. for (const auto &code : entry.codes) {
  266. _byCode.insert(code.callingCode, &entry);
  267. }
  268. }
  269. }
  270. return _byCode;
  271. }
  272. const CountriesInstance::Map &CountriesInstance::byISO2() const {
  273. if (_byISO2.empty()) {
  274. _byISO2.reserve(list().size());
  275. for (const auto &entry : list()) {
  276. _byISO2.insert(entry.iso2, &entry);
  277. }
  278. }
  279. return _byISO2;
  280. }
  281. QString CountriesInstance::validPhoneCode(QString fullCode) const {
  282. const auto &listByCode = byCode();
  283. while (fullCode.length()) {
  284. const auto i = listByCode.constFind(fullCode);
  285. if (i != listByCode.cend()) {
  286. return fullCode;
  287. }
  288. fullCode.chop(1);
  289. }
  290. return QString();
  291. }
  292. QString CountriesInstance::countryNameByISO2(const QString &iso) const {
  293. const auto &listByISO2 = byISO2();
  294. const auto i = listByISO2.constFind(iso);
  295. return (i != listByISO2.cend()) ? (*i)->name : QString();
  296. }
  297. QString CountriesInstance::countryISO2ByPhone(const QString &phone) const {
  298. const auto &listByCode = byCode();
  299. const auto code = validPhoneCode(phone);
  300. const auto i = listByCode.find(code);
  301. return (i != listByCode.cend()) ? (*i)->iso2 : QString();
  302. }
  303. QString CountriesInstance::flagEmojiByISO2(const QString &iso) const {
  304. if (iso.size() != 2
  305. || iso.front() < 'A'
  306. || iso.front() > 'Z'
  307. || iso.back() < 'A'
  308. || iso.back() > 'Z') {
  309. return QString();
  310. } else if (iso == u"FT"_q) {
  311. return QString::fromUtf8(
  312. "\xF0\x9F\x8F\xB4\xE2\x80\x8D\xE2\x98\xA0\xEF\xB8\x8F");
  313. }
  314. auto result = QString(4, QChar(0xD83C));
  315. result[1] = QChar(iso.front().unicode() - 'A' + 0xDDE6);
  316. result[3] = QChar(iso.back().unicode() - 'A' + 0xDDE6);
  317. return result;
  318. }
  319. FormatResult CountriesInstance::format(FormatArgs args) const {
  320. // Ported from TDLib.
  321. if (args.phone.isEmpty()) {
  322. return FormatResult();
  323. }
  324. const auto &phoneNumber = args.phone;
  325. const Info *bestCountryPtr = nullptr;
  326. const CallingCodeInfo *bestCallingCodePtr = nullptr;
  327. auto bestLength = size_t(0);
  328. [[maybe_unused]] auto isPrefix = false;
  329. for (const auto &country : list()) {
  330. for (auto &callingCode : country.codes) {
  331. if (phoneNumber.startsWith(callingCode.callingCode)) {
  332. const auto codeSize = callingCode.callingCode.size();
  333. for (const auto &prefix : callingCode.prefixes) {
  334. if (prefix.startsWith(base::StringViewMid(phoneNumber, codeSize))) {
  335. isPrefix = true;
  336. }
  337. if ((codeSize + prefix.size()) > bestLength &&
  338. base::StringViewMid(phoneNumber, codeSize).startsWith(prefix)) {
  339. bestCountryPtr = &country;
  340. bestCallingCodePtr = &callingCode;
  341. bestLength = codeSize + prefix.size();
  342. }
  343. }
  344. }
  345. if (callingCode.callingCode.startsWith(phoneNumber)) {
  346. isPrefix = true;
  347. }
  348. }
  349. }
  350. if (bestCountryPtr == nullptr) {
  351. return FormatResult{ .formatted = phoneNumber };
  352. }
  353. if (args.onlyCode) {
  354. return FormatResult{ .code = bestCallingCodePtr->callingCode };
  355. }
  356. const auto codeSize = int(bestCallingCodePtr->callingCode.size());
  357. if (args.onlyGroups && args.incomplete) {
  358. auto initialGroups = args.skipCode
  359. ? QVector<int>()
  360. : QVector<int>{ codeSize };
  361. auto initialGroupsSize = 0;
  362. if (bestCallingCodePtr->patterns.empty()) {
  363. return FormatResult{ .groups = std::move(initialGroups) };
  364. }
  365. auto bestGroups = initialGroups;
  366. auto bestGroupsSize = initialGroupsSize;
  367. auto bestPatternMaxMatches = -1;
  368. for (const auto &pattern : bestCallingCodePtr->patterns) {
  369. auto groups = initialGroups;
  370. auto groupSize = initialGroupsSize;
  371. auto lastSpacesCount = 0;
  372. auto maxMatchedDigits = 0;
  373. auto isNotBestPattern = false;
  374. for (auto i = 0; i < pattern.size(); i++) {
  375. const auto c = pattern.at(i);
  376. if (c.isDigit()) {
  377. const auto n = (i - lastSpacesCount) + codeSize;
  378. if (n < phoneNumber.size()) {
  379. if (phoneNumber.at(n) == c) {
  380. maxMatchedDigits++;
  381. } else {
  382. isNotBestPattern = true;
  383. }
  384. } else {
  385. isNotBestPattern = true;
  386. }
  387. }
  388. if (c.isSpace()) {
  389. groups.push_back(base::take(groupSize));
  390. lastSpacesCount++;
  391. } else {
  392. groupSize++;
  393. }
  394. }
  395. if (maxMatchedDigits > bestPatternMaxMatches) {
  396. bestPatternMaxMatches = isNotBestPattern
  397. ? -1
  398. : maxMatchedDigits;
  399. bestGroups = std::move(groups);
  400. bestGroupsSize = groupSize;
  401. }
  402. }
  403. if (bestGroupsSize) {
  404. bestGroups.push_back(base::take(bestGroupsSize));
  405. }
  406. return FormatResult{ .groups = std::move(bestGroups) };
  407. }
  408. const auto formattedPart = phoneNumber.mid(codeSize);
  409. auto formattedResult = formattedPart;
  410. auto groups = QVector<int>();
  411. auto maxMatchedDigits = size_t(0);
  412. for (auto &pattern : bestCallingCodePtr->patterns) {
  413. auto resultGroups = QVector<int>();
  414. auto result = QString();
  415. auto currentPatternPos = int(0);
  416. auto isFailedMatch = false;
  417. auto matchedDigits = size_t(0);
  418. auto groupSize = 0;
  419. for (const auto &c : formattedPart) {
  420. while ((currentPatternPos < pattern.size())
  421. && (pattern[currentPatternPos] != 'X')
  422. && !pattern[currentPatternPos].isDigit()) {
  423. if (args.onlyGroups) {
  424. resultGroups.push_back(groupSize);
  425. groupSize = 0;
  426. } else {
  427. result += pattern[currentPatternPos];
  428. }
  429. currentPatternPos++;
  430. }
  431. // Don't add an extra space to the end.
  432. // if (!args.onlyGroups && (currentPatternPos == pattern.size())) {
  433. // result += ' ';
  434. // }
  435. if ((currentPatternPos >= pattern.size())
  436. || (pattern[currentPatternPos] == 'X')) {
  437. currentPatternPos++;
  438. if (args.onlyGroups) {
  439. groupSize++;
  440. } else {
  441. result += c;
  442. }
  443. } else {
  444. if (c == pattern[currentPatternPos]) {
  445. matchedDigits++;
  446. currentPatternPos++;
  447. if (args.onlyGroups) {
  448. groupSize++;
  449. } else {
  450. result += c;
  451. }
  452. } else {
  453. isFailedMatch = true;
  454. break;
  455. }
  456. }
  457. }
  458. if (groupSize) {
  459. resultGroups.push_back(groupSize);
  460. }
  461. if (!isFailedMatch && matchedDigits >= maxMatchedDigits) {
  462. maxMatchedDigits = matchedDigits;
  463. if (args.onlyGroups) {
  464. groups = std::move(resultGroups);
  465. } else {
  466. formattedResult = std::move(result);
  467. }
  468. }
  469. }
  470. if (!args.skipCode) {
  471. if (args.onlyGroups) {
  472. groups.push_front(codeSize);
  473. } else {
  474. formattedResult = '+'
  475. + bestCallingCodePtr->callingCode
  476. + ' '
  477. + std::move(formattedResult);
  478. }
  479. }
  480. return FormatResult{
  481. .formatted = (args.onlyGroups
  482. ? QString()
  483. : std::move(formattedResult)),
  484. .groups = std::move(groups),
  485. };
  486. }
  487. rpl::producer<> CountriesInstance::updated() const {
  488. return _updated.events();
  489. }
  490. CountriesInstance &Instance() {
  491. return SingleInstance;
  492. }
  493. QString ExtractPhoneCode(const QString &phone) {
  494. return Instance().format({ .phone = phone, .onlyCode = true }).code;
  495. }
  496. QVector<int> Groups(const QString &phone) {
  497. return Instance().format({
  498. .phone = phone,
  499. .onlyGroups = true,
  500. .incomplete = true,
  501. }).groups;
  502. }
  503. } // namespace Countries