Line data Source code
1 : // Copyright (c) 2011-2022 Made to Order Software Corp. All Rights Reserved
2 : //
3 : // https://snapwebsites.org/project/snaplogger
4 : // contact@m2osw.com
5 : //
6 : // This program is free software; you can redistribute it and/or modify
7 : // it under the terms of the GNU General Public License as published by
8 : // the Free Software Foundation; either version 2 of the License, or
9 : // (at your option) any later version.
10 : //
11 : // This program is distributed in the hope that it will be useful,
12 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : // GNU General Public License for more details.
15 : //
16 : // You should have received a copy of the GNU General Public License along
17 : // with this program; if not, write to the Free Software Foundation, Inc.,
18 : // 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 : //
20 :
21 : /** \file
22 : * \brief Functions to return a string representing the ordinal indicator.
23 : *
24 : * A few languages make use of ordinal indicators such as "st" for first
25 : * in English. These indicators may further have a feminin variant as
26 : * in French (1er and 1ere--accent missing here, to avoid UTF-8 in our
27 : * source code).
28 : *
29 : * The language is very important although we offer functions that return
30 : * the ordinal indicator in each language, you probably want to use the
31 : * main function that will return the indicator depending on the language.
32 : *
33 : * \note
34 : * The ordinal indicator changes even within one language. The default can
35 : * be used by more languages (those that do not otherwise offer an ordinal
36 : * indicator).
37 : *
38 : * \sa https://en.wikipedia.org/wiki/Ordinal_indicator
39 : * \sa https://fr.wikipedia.org/wiki/Indicateur_ordinal
40 : */
41 :
42 : // self
43 : //
44 : #include "snaplogger/ordinal_indicator.h"
45 :
46 :
47 : // snapdev lib
48 : //
49 : #include <snapdev/not_used.h>
50 :
51 :
52 : // C++ lib
53 : //
54 : #include <string>
55 :
56 :
57 :
58 : namespace snaplogger
59 : {
60 :
61 :
62 : namespace
63 : {
64 :
65 :
66 :
67 : // WARNING: to simplify the usage in the find_values() functions, the flags
68 : // are bit numbers, not masks
69 : //
70 : typedef std::uint16_t flag_t;
71 :
72 : flag_t FLAG_TENTH = 0; // use (n % 10) instead of n to do the search unless `(n % 100) E { 11, 12, 13 }` is true
73 :
74 :
75 :
76 : struct indicator_t
77 : {
78 : std::uint16_t f_count = 0;
79 : std::uint16_t f_flags = 0;
80 : std::uint32_t f_languages = 0;
81 : std::uint32_t f_genders = 0;
82 : std::uint32_t f_numbers = 0;
83 : std::uint32_t f_secondary_forms = 0;
84 : char const * f_ordinal_indicator = nullptr;
85 : };
86 :
87 :
88 :
89 :
90 : template<typename T>
91 : class indicator_value
92 : {
93 : public:
94 : typedef T value_t;
95 :
96 120 : constexpr indicator_value<T>(T const v)
97 120 : : f_value(v)
98 : {
99 120 : }
100 :
101 110 : constexpr value_t get() const
102 : {
103 110 : return f_value;
104 : }
105 :
106 : private:
107 : value_t f_value;
108 : };
109 :
110 :
111 :
112 :
113 : class specific_count
114 : : public indicator_value<std::uint16_t>
115 : {
116 : public:
117 10 : constexpr specific_count()
118 10 : : indicator_value<std::uint16_t>(0)
119 : {
120 10 : }
121 :
122 10 : constexpr specific_count(std::uint16_t c)
123 10 : : indicator_value<std::uint16_t>(c)
124 : {
125 10 : }
126 : };
127 :
128 :
129 : class indicator_flag
130 : : public indicator_value<flag_t>
131 : {
132 : public:
133 10 : constexpr indicator_flag()
134 10 : : indicator_value<flag_t>(static_cast<flag_t>(-1))
135 : {
136 10 : }
137 :
138 10 : constexpr indicator_flag(flag_t f)
139 10 : : indicator_value<flag_t>(f)
140 : {
141 10 : }
142 : };
143 :
144 :
145 : class indicator_language
146 : : public indicator_value<language_t>
147 : {
148 : public:
149 : constexpr indicator_language()
150 : : indicator_value<language_t>(language_t::LANGUAGE_DEFAULT)
151 : {
152 : }
153 :
154 10 : constexpr indicator_language(language_t l)
155 10 : : indicator_value<language_t>(l)
156 : {
157 10 : }
158 : };
159 :
160 :
161 : class indicator_gender
162 : : public indicator_value<gender_t>
163 : {
164 : public:
165 : constexpr indicator_gender()
166 : : indicator_value<gender_t>(gender_t::GENDER_MASCULINE)
167 : {
168 : }
169 :
170 30 : constexpr indicator_gender(gender_t g)
171 30 : : indicator_value<gender_t>(g)
172 : {
173 30 : }
174 : };
175 :
176 :
177 : class indicator_number
178 : : public indicator_value<number_t>
179 : {
180 : public:
181 : constexpr indicator_number()
182 : : indicator_value<number_t>(number_t::NUMBER_SINGULAR)
183 : {
184 : }
185 :
186 20 : constexpr indicator_number(number_t g)
187 20 : : indicator_value<number_t>(g)
188 : {
189 20 : }
190 : };
191 :
192 :
193 : class indicator_secondary_form
194 : : public indicator_value<secondary_form_t>
195 : {
196 : public:
197 : constexpr indicator_secondary_form()
198 : : indicator_value<secondary_form_t>(secondary_form_t::SECONDARY_FORM_FORMAL)
199 : {
200 : }
201 :
202 10 : constexpr indicator_secondary_form(secondary_form_t sf)
203 10 : : indicator_value<secondary_form_t>(sf)
204 : {
205 10 : }
206 : };
207 :
208 :
209 : class ordinal_indicator_string
210 : : public indicator_value<char const *>
211 : {
212 : public:
213 : constexpr ordinal_indicator_string()
214 : : indicator_value<char const *>(nullptr)
215 : {
216 : }
217 :
218 10 : constexpr ordinal_indicator_string(char const * indicator)
219 10 : : indicator_value<char const *>(indicator)
220 : {
221 10 : }
222 : };
223 :
224 :
225 :
226 :
227 :
228 :
229 :
230 : //template<typename T, typename F, class ...ARGS>
231 : template<typename T, typename F>
232 10 : constexpr typename std::enable_if<std::is_same<T, F>::value, std::uint32_t>::type find_values(F first)
233 : {
234 10 : std::uint32_t const value(static_cast<std::uint32_t>(first.get()));
235 10 : if(value >= 32)
236 : {
237 10 : return 0;
238 : }
239 : return 1 << value; // LCOV_EXCL_LINE
240 : }
241 :
242 :
243 : template<typename T, typename F>
244 40 : constexpr typename std::enable_if<!std::is_same<T, F>::value, std::uint32_t>::type find_values(F first)
245 : {
246 40 : snapdev::NOT_USED(first);
247 40 : return 0;
248 : }
249 :
250 :
251 : template<typename T, typename F, class ...ARGS>
252 80 : constexpr typename std::enable_if<std::is_same<T, F>::value, std::uint32_t>::type find_values(F first, ARGS ...args)
253 : {
254 80 : std::uint32_t const value(static_cast<std::uint32_t>(first.get()));
255 80 : if(value == static_cast<std::uint32_t>(-1))
256 : {
257 : return find_values<T>(args...); // LCOV_EXCL_LINE
258 : }
259 80 : return (1 << value) | find_values<T>(args...);
260 : }
261 :
262 :
263 : template<typename T, typename F, class ...ARGS>
264 380 : constexpr typename std::enable_if<!std::is_same<T, F>::value, std::uint32_t>::type find_values(F first, ARGS ...args)
265 : {
266 380 : snapdev::NOT_USED(first);
267 380 : return find_values<T>(args...);
268 : }
269 :
270 :
271 :
272 :
273 : template<typename T, typename F, class ...ARGS>
274 20 : constexpr typename std::enable_if<std::is_same<T, F>::value, typename T::value_t>::type find_option(F first, ARGS ...args)
275 : {
276 20 : snapdev::NOT_USED(args...);
277 20 : return first.get();
278 : }
279 :
280 :
281 : template<typename T, typename F, class ...ARGS>
282 90 : constexpr typename std::enable_if<!std::is_same<T, F>::value, typename T::value_t>::type find_option(F first, ARGS ...args)
283 : {
284 90 : snapdev::NOT_USED(first);
285 90 : return find_option<T>(args...);
286 : }
287 :
288 :
289 :
290 : template<class ...ARGS>
291 10 : constexpr indicator_t define_indicator(ARGS ...args)
292 : {
293 : #pragma GCC diagnostic push
294 : #pragma GCC diagnostic ignored "-Wpedantic"
295 90 : indicator_t indicator =
296 : {
297 20 : .f_count = find_option<specific_count>(args..., specific_count()), // 0 = any
298 20 : .f_flags = static_cast<flag_t>(find_values<indicator_flag>(args..., indicator_flag())),
299 10 : .f_languages = find_values<indicator_language>(args...),
300 10 : .f_genders = find_values<indicator_gender>(args...),
301 10 : .f_numbers = find_values<indicator_number>(args...),
302 10 : .f_secondary_forms = find_values<indicator_secondary_form>(args...),
303 10 : .f_ordinal_indicator = find_option<ordinal_indicator_string>(args...),
304 : };
305 : #pragma GCC diagnostic pop
306 :
307 10 : return indicator;
308 : }
309 :
310 :
311 :
312 2 : struct indicator_t g_indicators[]
313 : {
314 : // Breton
315 : //
316 : define_indicator(
317 : specific_count(1)
318 : , indicator_language(language_t::LANGUAGE_BRETON)
319 : , indicator_gender(gender_t::GENDER_MASCULINE)
320 : , indicator_gender(gender_t::GENDER_FEMININE)
321 : , indicator_gender(gender_t::GENDER_NEUTRAL)
322 : , indicator_number(number_t::NUMBER_SINGULAR)
323 : , indicator_number(number_t::NUMBER_PLURAL)
324 : , indicator_secondary_form(secondary_form_t::SECONDARY_FORM_FORMAL)
325 : , ordinal_indicator_string("a\xC3\xB1")
326 : ),
327 : define_indicator(
328 : specific_count(2)
329 : , indicator_language(language_t::LANGUAGE_BRETON)
330 : , indicator_gender(gender_t::GENDER_MASCULINE)
331 : , indicator_gender(gender_t::GENDER_FEMININE)
332 : , indicator_gender(gender_t::GENDER_NEUTRAL)
333 : , indicator_number(number_t::NUMBER_SINGULAR)
334 : , indicator_number(number_t::NUMBER_PLURAL)
335 : , indicator_secondary_form(secondary_form_t::SECONDARY_FORM_FORMAL)
336 : , ordinal_indicator_string("l")
337 : ),
338 : define_indicator(
339 : specific_count(3)
340 : , indicator_language(language_t::LANGUAGE_BRETON)
341 : , indicator_gender(gender_t::GENDER_MASCULINE)
342 : , indicator_gender(gender_t::GENDER_FEMININE)
343 : , indicator_gender(gender_t::GENDER_NEUTRAL)
344 : , indicator_number(number_t::NUMBER_SINGULAR)
345 : , indicator_number(number_t::NUMBER_PLURAL)
346 : , indicator_secondary_form(secondary_form_t::SECONDARY_FORM_FORMAL)
347 : , ordinal_indicator_string("de")
348 : ),
349 : define_indicator(
350 : specific_count(4)
351 : , indicator_language(language_t::LANGUAGE_BRETON)
352 : , indicator_gender(gender_t::GENDER_MASCULINE)
353 : , indicator_gender(gender_t::GENDER_FEMININE)
354 : , indicator_gender(gender_t::GENDER_NEUTRAL)
355 : , indicator_number(number_t::NUMBER_SINGULAR)
356 : , indicator_number(number_t::NUMBER_PLURAL)
357 : , indicator_secondary_form(secondary_form_t::SECONDARY_FORM_FORMAL)
358 : , ordinal_indicator_string("re")
359 : ),
360 : define_indicator(
361 : indicator_language(language_t::LANGUAGE_BRETON)
362 : , indicator_gender(gender_t::GENDER_MASCULINE)
363 : , indicator_gender(gender_t::GENDER_FEMININE)
364 : , indicator_gender(gender_t::GENDER_NEUTRAL)
365 : , indicator_number(number_t::NUMBER_SINGULAR)
366 : , indicator_number(number_t::NUMBER_PLURAL)
367 : , indicator_secondary_form(secondary_form_t::SECONDARY_FORM_FORMAL)
368 : , ordinal_indicator_string("vet")
369 : ),
370 :
371 : // English
372 : //
373 : define_indicator(
374 : specific_count(1)
375 : , indicator_flag(FLAG_TENTH)
376 : , indicator_language(language_t::LANGUAGE_ENGLISH)
377 : , indicator_gender(gender_t::GENDER_MASCULINE)
378 : , indicator_gender(gender_t::GENDER_FEMININE)
379 : , indicator_gender(gender_t::GENDER_NEUTRAL)
380 : , indicator_number(number_t::NUMBER_SINGULAR)
381 : , indicator_number(number_t::NUMBER_PLURAL)
382 : , indicator_secondary_form(secondary_form_t::SECONDARY_FORM_FORMAL)
383 : , ordinal_indicator_string("st")
384 22 : ),
385 : define_indicator(
386 : specific_count(2)
387 : , indicator_flag(FLAG_TENTH)
388 : , indicator_language(language_t::LANGUAGE_ENGLISH)
389 : , indicator_gender(gender_t::GENDER_MASCULINE)
390 : , indicator_gender(gender_t::GENDER_FEMININE)
391 : , indicator_gender(gender_t::GENDER_NEUTRAL)
392 : , indicator_number(number_t::NUMBER_SINGULAR)
393 : , indicator_number(number_t::NUMBER_PLURAL)
394 : , indicator_secondary_form(secondary_form_t::SECONDARY_FORM_FORMAL)
395 : , ordinal_indicator_string("nd")
396 22 : ),
397 : define_indicator(
398 : specific_count(2)
399 : , indicator_flag(FLAG_TENTH)
400 : , indicator_language(language_t::LANGUAGE_ENGLISH)
401 : , indicator_gender(gender_t::GENDER_MASCULINE)
402 : , indicator_gender(gender_t::GENDER_FEMININE)
403 : , indicator_gender(gender_t::GENDER_NEUTRAL)
404 : , indicator_number(number_t::NUMBER_SINGULAR)
405 : , indicator_number(number_t::NUMBER_PLURAL)
406 : , indicator_secondary_form(secondary_form_t::SECONDARY_FORM_ONE)
407 : , ordinal_indicator_string("d")
408 22 : ),
409 : define_indicator(
410 : specific_count(3)
411 : , indicator_flag(FLAG_TENTH)
412 : , indicator_language(language_t::LANGUAGE_ENGLISH)
413 : , indicator_gender(gender_t::GENDER_MASCULINE)
414 : , indicator_gender(gender_t::GENDER_FEMININE)
415 : , indicator_gender(gender_t::GENDER_NEUTRAL)
416 : , indicator_number(number_t::NUMBER_SINGULAR)
417 : , indicator_number(number_t::NUMBER_PLURAL)
418 : , indicator_secondary_form(secondary_form_t::SECONDARY_FORM_FORMAL)
419 : , ordinal_indicator_string("rd")
420 22 : ),
421 : define_indicator(
422 : specific_count(3)
423 : , indicator_flag(FLAG_TENTH)
424 : , indicator_language(language_t::LANGUAGE_ENGLISH)
425 : , indicator_gender(gender_t::GENDER_MASCULINE)
426 : , indicator_gender(gender_t::GENDER_FEMININE)
427 : , indicator_gender(gender_t::GENDER_NEUTRAL)
428 : , indicator_number(number_t::NUMBER_SINGULAR)
429 : , indicator_number(number_t::NUMBER_PLURAL)
430 : , indicator_secondary_form(secondary_form_t::SECONDARY_FORM_ONE)
431 : , ordinal_indicator_string("d")
432 22 : ),
433 : define_indicator(
434 : indicator_language(language_t::LANGUAGE_ENGLISH)
435 : , indicator_gender(gender_t::GENDER_MASCULINE)
436 : , indicator_gender(gender_t::GENDER_FEMININE)
437 : , indicator_gender(gender_t::GENDER_NEUTRAL)
438 : , indicator_number(number_t::NUMBER_SINGULAR)
439 : , indicator_number(number_t::NUMBER_PLURAL)
440 : , indicator_secondary_form(secondary_form_t::SECONDARY_FORM_FORMAL)
441 : , ordinal_indicator_string("th")
442 : ),
443 :
444 : // French
445 : //
446 : define_indicator(
447 : specific_count(1)
448 : , indicator_language(language_t::LANGUAGE_FRENCH)
449 : , indicator_gender(gender_t::GENDER_MASCULINE)
450 : , indicator_number(number_t::NUMBER_SINGULAR)
451 : , indicator_secondary_form(secondary_form_t::SECONDARY_FORM_FORMAL)
452 : , ordinal_indicator_string("er")
453 : ),
454 : define_indicator(
455 : specific_count(1)
456 : , indicator_language(language_t::LANGUAGE_FRENCH)
457 : , indicator_gender(gender_t::GENDER_FEMININE)
458 : , indicator_number(number_t::NUMBER_SINGULAR)
459 : , indicator_secondary_form(secondary_form_t::SECONDARY_FORM_FORMAL)
460 : , ordinal_indicator_string("re")
461 : ),
462 : define_indicator(
463 : specific_count(1)
464 : , indicator_language(language_t::LANGUAGE_FRENCH)
465 : , indicator_gender(gender_t::GENDER_MASCULINE)
466 : , indicator_number(number_t::NUMBER_PLURAL)
467 : , indicator_secondary_form(secondary_form_t::SECONDARY_FORM_FORMAL)
468 : , ordinal_indicator_string("ers")
469 : ),
470 : define_indicator(
471 : specific_count(1)
472 : , indicator_language(language_t::LANGUAGE_FRENCH)
473 : , indicator_gender(gender_t::GENDER_FEMININE)
474 : , indicator_number(number_t::NUMBER_PLURAL)
475 : , indicator_secondary_form(secondary_form_t::SECONDARY_FORM_FORMAL)
476 : , ordinal_indicator_string("res")
477 : ),
478 : define_indicator(
479 : specific_count(2)
480 : , indicator_language(language_t::LANGUAGE_FRENCH)
481 : , indicator_gender(gender_t::GENDER_MASCULINE)
482 : , indicator_number(number_t::NUMBER_SINGULAR)
483 : , indicator_secondary_form(secondary_form_t::SECONDARY_FORM_THREE)
484 : , ordinal_indicator_string("d")
485 : ),
486 : define_indicator(
487 : specific_count(2)
488 : , indicator_language(language_t::LANGUAGE_FRENCH)
489 : , indicator_gender(gender_t::GENDER_FEMININE)
490 : , indicator_number(number_t::NUMBER_SINGULAR)
491 : , indicator_secondary_form(secondary_form_t::SECONDARY_FORM_THREE)
492 : , ordinal_indicator_string("de")
493 : ),
494 : define_indicator(
495 : specific_count(2)
496 : , indicator_language(language_t::LANGUAGE_FRENCH)
497 : , indicator_gender(gender_t::GENDER_MASCULINE)
498 : , indicator_number(number_t::NUMBER_PLURAL)
499 : , indicator_secondary_form(secondary_form_t::SECONDARY_FORM_THREE)
500 : , ordinal_indicator_string("ds")
501 : ),
502 : define_indicator(
503 : specific_count(2)
504 : , indicator_language(language_t::LANGUAGE_FRENCH)
505 : , indicator_gender(gender_t::GENDER_FEMININE)
506 : , indicator_number(number_t::NUMBER_PLURAL)
507 : , indicator_secondary_form(secondary_form_t::SECONDARY_FORM_THREE)
508 : , ordinal_indicator_string("des")
509 : ),
510 : define_indicator(
511 : specific_count(2)
512 : , indicator_language(language_t::LANGUAGE_FRENCH)
513 : , indicator_gender(gender_t::GENDER_MASCULINE)
514 : , indicator_number(number_t::NUMBER_SINGULAR)
515 : , indicator_secondary_form(secondary_form_t::SECONDARY_FORM_FOUR)
516 : , ordinal_indicator_string("nd")
517 : ),
518 : define_indicator(
519 : specific_count(2)
520 : , indicator_language(language_t::LANGUAGE_FRENCH)
521 : , indicator_gender(gender_t::GENDER_FEMININE)
522 : , indicator_number(number_t::NUMBER_SINGULAR)
523 : , indicator_secondary_form(secondary_form_t::SECONDARY_FORM_FOUR)
524 : , ordinal_indicator_string("nde")
525 : ),
526 : define_indicator(
527 : specific_count(2)
528 : , indicator_language(language_t::LANGUAGE_FRENCH)
529 : , indicator_gender(gender_t::GENDER_MASCULINE)
530 : , indicator_number(number_t::NUMBER_PLURAL)
531 : , indicator_secondary_form(secondary_form_t::SECONDARY_FORM_FOUR)
532 : , ordinal_indicator_string("nds")
533 : ),
534 : define_indicator(
535 : specific_count(2)
536 : , indicator_language(language_t::LANGUAGE_FRENCH)
537 : , indicator_gender(gender_t::GENDER_FEMININE)
538 : , indicator_number(number_t::NUMBER_PLURAL)
539 : , indicator_secondary_form(secondary_form_t::SECONDARY_FORM_FOUR)
540 : , ordinal_indicator_string("ndes")
541 : ),
542 : define_indicator(
543 : indicator_language(language_t::LANGUAGE_FRENCH)
544 : , indicator_gender(gender_t::GENDER_MASCULINE)
545 : , indicator_gender(gender_t::GENDER_FEMININE)
546 : , indicator_number(number_t::NUMBER_SINGULAR)
547 : , indicator_secondary_form(secondary_form_t::SECONDARY_FORM_FORMAL)
548 : , ordinal_indicator_string("e")
549 : ),
550 : define_indicator(
551 : indicator_language(language_t::LANGUAGE_FRENCH)
552 : , indicator_gender(gender_t::GENDER_MASCULINE)
553 : , indicator_gender(gender_t::GENDER_FEMININE)
554 : , indicator_number(number_t::NUMBER_PLURAL)
555 : , indicator_secondary_form(secondary_form_t::SECONDARY_FORM_FORMAL)
556 : , ordinal_indicator_string("es")
557 : ),
558 : define_indicator(
559 : indicator_language(language_t::LANGUAGE_FRENCH)
560 : , indicator_gender(gender_t::GENDER_MASCULINE)
561 : , indicator_gender(gender_t::GENDER_FEMININE)
562 : , indicator_number(number_t::NUMBER_SINGULAR)
563 : , indicator_secondary_form(secondary_form_t::SECONDARY_FORM_ONE)
564 : , ordinal_indicator_string("\xC3\xA8me")
565 : ),
566 : define_indicator(
567 : indicator_language(language_t::LANGUAGE_FRENCH)
568 : , indicator_gender(gender_t::GENDER_MASCULINE)
569 : , indicator_gender(gender_t::GENDER_FEMININE)
570 : , indicator_number(number_t::NUMBER_PLURAL)
571 : , indicator_secondary_form(secondary_form_t::SECONDARY_FORM_ONE)
572 : , ordinal_indicator_string("\xC3\xA8mes")
573 : ),
574 : define_indicator(
575 : indicator_language(language_t::LANGUAGE_FRENCH)
576 : , indicator_gender(gender_t::GENDER_MASCULINE)
577 : , indicator_gender(gender_t::GENDER_FEMININE)
578 : , indicator_number(number_t::NUMBER_SINGULAR)
579 : , indicator_secondary_form(secondary_form_t::SECONDARY_FORM_TWO)
580 : , ordinal_indicator_string("i\xC3\xA8me")
581 : ),
582 : define_indicator(
583 : indicator_language(language_t::LANGUAGE_FRENCH)
584 : , indicator_gender(gender_t::GENDER_MASCULINE)
585 : , indicator_gender(gender_t::GENDER_FEMININE)
586 : , indicator_number(number_t::NUMBER_PLURAL)
587 : , indicator_secondary_form(secondary_form_t::SECONDARY_FORM_TWO)
588 : , ordinal_indicator_string("i\xC3\xA8mes")
589 : ),
590 :
591 : // Francoprovincal
592 : //
593 : define_indicator(
594 : specific_count(1)
595 : , indicator_language(language_t::LANGUAGE_FRANCOPROVENCAL)
596 : , indicator_gender(gender_t::GENDER_MASCULINE)
597 : , indicator_number(number_t::NUMBER_SINGULAR)
598 : , indicator_number(number_t::NUMBER_PLURAL)
599 : , indicator_secondary_form(secondary_form_t::SECONDARY_FORM_FORMAL)
600 : , ordinal_indicator_string("\xC3\xA9r")
601 : ),
602 : define_indicator(
603 : specific_count(1)
604 : , indicator_language(language_t::LANGUAGE_FRANCOPROVENCAL)
605 : , indicator_gender(gender_t::GENDER_FEMININE)
606 : , indicator_number(number_t::NUMBER_SINGULAR)
607 : , indicator_number(number_t::NUMBER_PLURAL)
608 : , indicator_secondary_form(secondary_form_t::SECONDARY_FORM_FORMAL)
609 : , ordinal_indicator_string("\xC3\xA9re")
610 : ),
611 : define_indicator(
612 : specific_count(2)
613 : , indicator_language(language_t::LANGUAGE_FRANCOPROVENCAL)
614 : , indicator_gender(gender_t::GENDER_MASCULINE)
615 : , indicator_number(number_t::NUMBER_SINGULAR)
616 : , indicator_number(number_t::NUMBER_PLURAL)
617 : , indicator_secondary_form(secondary_form_t::SECONDARY_FORM_ONE)
618 : , ordinal_indicator_string("nd")
619 : ),
620 : define_indicator(
621 : specific_count(2)
622 : , indicator_language(language_t::LANGUAGE_FRANCOPROVENCAL)
623 : , indicator_gender(gender_t::GENDER_FEMININE)
624 : , indicator_number(number_t::NUMBER_SINGULAR)
625 : , indicator_number(number_t::NUMBER_PLURAL)
626 : , indicator_secondary_form(secondary_form_t::SECONDARY_FORM_ONE)
627 : , ordinal_indicator_string("nda")
628 : ),
629 : define_indicator(
630 : indicator_language(language_t::LANGUAGE_FRANCOPROVENCAL)
631 : , indicator_gender(gender_t::GENDER_MASCULINE)
632 : , indicator_number(number_t::NUMBER_SINGULAR)
633 : , indicator_number(number_t::NUMBER_PLURAL)
634 : , indicator_secondary_form(secondary_form_t::SECONDARY_FORM_FORMAL)
635 : , ordinal_indicator_string("\xC3\xA9mo")
636 : ),
637 : define_indicator(
638 : indicator_language(language_t::LANGUAGE_FRANCOPROVENCAL)
639 : , indicator_gender(gender_t::GENDER_FEMININE)
640 : , indicator_number(number_t::NUMBER_SINGULAR)
641 : , indicator_number(number_t::NUMBER_PLURAL)
642 : , indicator_secondary_form(secondary_form_t::SECONDARY_FORM_FORMAL)
643 : , ordinal_indicator_string("\xC3\xA9ma")
644 : ),
645 :
646 : // Occitan
647 : //
648 : define_indicator(
649 : specific_count(1)
650 : , indicator_language(language_t::LANGUAGE_OCCITAN)
651 : , indicator_gender(gender_t::GENDER_MASCULINE)
652 : , indicator_number(number_t::NUMBER_SINGULAR)
653 : , indicator_number(number_t::NUMBER_PLURAL)
654 : , indicator_secondary_form(secondary_form_t::SECONDARY_FORM_FORMAL)
655 : , ordinal_indicator_string("\xC3\xA8r")
656 : ),
657 : define_indicator(
658 : specific_count(1)
659 : , indicator_language(language_t::LANGUAGE_OCCITAN)
660 : , indicator_gender(gender_t::GENDER_FEMININE)
661 : , indicator_number(number_t::NUMBER_SINGULAR)
662 : , indicator_number(number_t::NUMBER_PLURAL)
663 : , indicator_secondary_form(secondary_form_t::SECONDARY_FORM_FORMAL)
664 : , ordinal_indicator_string("\xC3\xA8ra")
665 : ),
666 : define_indicator(
667 : specific_count(2)
668 : , indicator_language(language_t::LANGUAGE_OCCITAN)
669 : , indicator_gender(gender_t::GENDER_MASCULINE)
670 : , indicator_number(number_t::NUMBER_SINGULAR)
671 : , indicator_number(number_t::NUMBER_PLURAL)
672 : , indicator_secondary_form(secondary_form_t::SECONDARY_FORM_FORMAL)
673 : , ordinal_indicator_string("nd")
674 : ),
675 : define_indicator(
676 : specific_count(2)
677 : , indicator_language(language_t::LANGUAGE_OCCITAN)
678 : , indicator_gender(gender_t::GENDER_FEMININE)
679 : , indicator_number(number_t::NUMBER_SINGULAR)
680 : , indicator_number(number_t::NUMBER_PLURAL)
681 : , indicator_secondary_form(secondary_form_t::SECONDARY_FORM_FORMAL)
682 : , ordinal_indicator_string("nda")
683 : ),
684 : define_indicator(
685 : indicator_language(language_t::LANGUAGE_OCCITAN)
686 : , indicator_gender(gender_t::GENDER_MASCULINE)
687 : , indicator_number(number_t::NUMBER_SINGULAR)
688 : , indicator_number(number_t::NUMBER_PLURAL)
689 : , indicator_secondary_form(secondary_form_t::SECONDARY_FORM_FORMAL)
690 : , ordinal_indicator_string("en")
691 : ),
692 : define_indicator(
693 : indicator_language(language_t::LANGUAGE_OCCITAN)
694 : , indicator_gender(gender_t::GENDER_FEMININE)
695 : , indicator_number(number_t::NUMBER_SINGULAR)
696 : , indicator_number(number_t::NUMBER_PLURAL)
697 : , indicator_secondary_form(secondary_form_t::SECONDARY_FORM_FORMAL)
698 : , ordinal_indicator_string("ena")
699 : ),
700 :
701 : // Russian
702 : //
703 : define_indicator(
704 : indicator_language(language_t::LANGUAGE_RUSSIAN)
705 : , indicator_gender(gender_t::GENDER_MASCULINE)
706 : , indicator_number(number_t::NUMBER_SINGULAR)
707 : , indicator_number(number_t::NUMBER_PLURAL)
708 : , indicator_secondary_form(secondary_form_t::SECONDARY_FORM_FORMAL)
709 : , ordinal_indicator_string("-\xD0\xB9")
710 : ),
711 : define_indicator(
712 : indicator_language(language_t::LANGUAGE_RUSSIAN)
713 : , indicator_gender(gender_t::GENDER_FEMININE)
714 : , indicator_number(number_t::NUMBER_SINGULAR)
715 : , indicator_number(number_t::NUMBER_PLURAL)
716 : , indicator_secondary_form(secondary_form_t::SECONDARY_FORM_FORMAL)
717 : , ordinal_indicator_string("-\xD1\x8F")
718 : ),
719 : define_indicator(
720 : indicator_language(language_t::LANGUAGE_RUSSIAN)
721 : , indicator_gender(gender_t::GENDER_NEUTRAL)
722 : , indicator_number(number_t::NUMBER_SINGULAR)
723 : , indicator_number(number_t::NUMBER_PLURAL)
724 : , indicator_secondary_form(secondary_form_t::SECONDARY_FORM_FORMAL)
725 : , ordinal_indicator_string("-\xD0\xB5")
726 : ),
727 :
728 : // Other Latin languages use pretty much the same notation
729 : //
730 : define_indicator(
731 : indicator_language(language_t::LANGUAGE_SPANISH)
732 : , indicator_language(language_t::LANGUAGE_PORTUGUESE)
733 : , indicator_language(language_t::LANGUAGE_ITALIAN)
734 : , indicator_language(language_t::LANGUAGE_GALICIAN)
735 : , indicator_gender(gender_t::GENDER_MASCULINE)
736 : , indicator_number(number_t::NUMBER_SINGULAR)
737 : , indicator_number(number_t::NUMBER_PLURAL)
738 : , indicator_secondary_form(secondary_form_t::SECONDARY_FORM_FORMAL)
739 : , ordinal_indicator_string("\xC2\xBA")
740 : ),
741 : define_indicator(
742 : indicator_language(language_t::LANGUAGE_SPANISH)
743 : , indicator_language(language_t::LANGUAGE_PORTUGUESE)
744 : , indicator_language(language_t::LANGUAGE_ITALIAN)
745 : , indicator_language(language_t::LANGUAGE_GALICIAN)
746 : , indicator_gender(gender_t::GENDER_FEMININE)
747 : , indicator_number(number_t::NUMBER_SINGULAR)
748 : , indicator_number(number_t::NUMBER_PLURAL)
749 : , indicator_secondary_form(secondary_form_t::SECONDARY_FORM_FORMAL)
750 : , ordinal_indicator_string("\xC2\xAA")
751 : ),
752 : define_indicator(
753 : indicator_language(language_t::LANGUAGE_SPANISH)
754 : , indicator_language(language_t::LANGUAGE_PORTUGUESE)
755 : , indicator_gender(gender_t::GENDER_MASCULINE)
756 : , indicator_number(number_t::NUMBER_SINGULAR)
757 : , indicator_number(number_t::NUMBER_PLURAL)
758 : , indicator_secondary_form(secondary_form_t::SECONDARY_FORM_ONE)
759 : , ordinal_indicator_string(".\xC2\xBA")
760 : ),
761 : define_indicator(
762 : indicator_language(language_t::LANGUAGE_SPANISH)
763 : , indicator_language(language_t::LANGUAGE_PORTUGUESE)
764 : , indicator_gender(gender_t::GENDER_FEMININE)
765 : , indicator_number(number_t::NUMBER_SINGULAR)
766 : , indicator_number(number_t::NUMBER_PLURAL)
767 : , indicator_secondary_form(secondary_form_t::SECONDARY_FORM_ONE)
768 : , ordinal_indicator_string(".\xC2\xAA")
769 : ),
770 :
771 : // Period Indicator
772 : //
773 : define_indicator(
774 : indicator_language(language_t::LANGUAGE_BASQUE)
775 : , indicator_language(language_t::LANGUAGE_BOSNIAN)
776 : , indicator_language(language_t::LANGUAGE_CROATIAN)
777 : , indicator_language(language_t::LANGUAGE_CZECH)
778 : , indicator_language(language_t::LANGUAGE_DANISH)
779 : , indicator_language(language_t::LANGUAGE_FAROESE)
780 : , indicator_language(language_t::LANGUAGE_FINNISH)
781 : , indicator_language(language_t::LANGUAGE_GERMAN)
782 : , indicator_language(language_t::LANGUAGE_ICELANDIC)
783 : , indicator_language(language_t::LANGUAGE_LATVIAN)
784 : , indicator_language(language_t::LANGUAGE_MONTENEGRIN)
785 : , indicator_language(language_t::LANGUAGE_NORWEGIAN)
786 : , indicator_language(language_t::LANGUAGE_SERBIAN) // <- TODO: this is only for Arabic numbers
787 : , indicator_language(language_t::LANGUAGE_SLOVAK)
788 : , indicator_language(language_t::LANGUAGE_SLOVENE)
789 : , indicator_language(language_t::LANGUAGE_TURKISH)
790 : , indicator_gender(gender_t::GENDER_MASCULINE)
791 : , indicator_gender(gender_t::GENDER_FEMININE)
792 : , indicator_gender(gender_t::GENDER_NEUTRAL)
793 : , indicator_number(number_t::NUMBER_SINGULAR)
794 : , indicator_number(number_t::NUMBER_PLURAL)
795 : , indicator_secondary_form(secondary_form_t::SECONDARY_FORM_FORMAL)
796 : , ordinal_indicator_string(".")
797 : ),
798 112 : };
799 :
800 : }
801 :
802 :
803 :
804 : /** \brief Define the language.
805 : *
806 : * The language to use to generate the indicated.
807 : *
808 : * By default is LANGUAGE_DEFAULT is used. This means nothing happens
809 : * (i.e. the indicator() function will always return an empty string).
810 : *
811 : * \param[in] l The language to use to generate the indicator.
812 : *
813 : * \sa language()
814 : */
815 563 : void ordinal_indicator::language(language_t l)
816 : {
817 563 : f_language = l;
818 563 : }
819 :
820 :
821 : /** \brief Retrieve the current language of the ordinal indicator.
822 : *
823 : * This function returns the language definition of the ordinal indicator
824 : * object.
825 : *
826 : * \return The current language of the ordinal indicator.
827 : *
828 : * \sa language(language_t l)
829 : */
830 523 : language_t ordinal_indicator::language() const
831 : {
832 523 : return f_language;
833 : }
834 :
835 :
836 : /** \brief Change the grammatical gender.
837 : *
838 : * The ordinal indicator often depends on the grammatical gender in the
839 : * sentence including the number.
840 : *
841 : * \param[in] g The new gender.
842 : *
843 : * \sa gender()
844 : */
845 20668 : void ordinal_indicator::gender(gender_t g)
846 : {
847 20668 : f_gender = g;
848 20668 : }
849 :
850 :
851 : /** \brief Retrieve the grammatical gender.
852 : *
853 : * This function retrieves the current grammatical gender.
854 : *
855 : * \return The current grammatical gender.
856 : *
857 : * \sa gender(gender_t g)
858 : */
859 523 : gender_t ordinal_indicator::gender() const
860 : {
861 523 : return f_gender;
862 : }
863 :
864 :
865 : /** \brief The number of the indicator.
866 : *
867 : * The number defines whether the singular or the plural version is to be
868 : * retrieved. For some languages (English) this makes no difference. For
869 : * others (French) it will force the plural version (i.e. append an 's'
870 : * to the French ordinal).
871 : *
872 : * By default, the number is set to singular.
873 : *
874 : * \param[in] n The new number of the indicator.
875 : *
876 : * \sa number()
877 : */
878 20640 : void ordinal_indicator::number(number_t n)
879 : {
880 20640 : f_number = n;
881 20640 : }
882 :
883 :
884 : /** \brief Retrieve the current indicator number.
885 : *
886 : * This function returns whether the singular or plural version of the
887 : * ordinal indicator is to be returned.
888 : *
889 : * \return The current number of the indicator.
890 : *
891 : * \sa number(number_t n)
892 : */
893 523 : number_t ordinal_indicator::number() const
894 : {
895 523 : return f_number;
896 : }
897 :
898 :
899 : /** \brief Select a secondary form.
900 : *
901 : * By default, the formal form is returned by the indicator() function.
902 : * Some languages offer multiple ordinals for various numbers.
903 : *
904 : * For example, the Spanish form just uses an ordinal mark (a small 'o'
905 : * with an underscore) by default, but it is possible to add a period
906 : * just before that character. In French, the number 2 can be folloed
907 : * by an 'e' (deuxieme) or 'nd' (second). Etc.
908 : *
909 : * \param[in] sf The new secondary form to use with indicator().
910 : *
911 : * \sa secondary_form()
912 : */
913 20525 : void ordinal_indicator::secondary_form(secondary_form_t sf)
914 : {
915 20525 : f_secondary_form = sf;
916 20525 : }
917 :
918 :
919 : /** \brief Retrieve the secondary form.
920 : *
921 : * This function returns the current secondary form.
922 : *
923 : * \return The current secondary form.
924 : *
925 : * \sa secondary_form(secondary_form_t sf)
926 : */
927 523 : secondary_form_t ordinal_indicator::secondary_form() const
928 : {
929 523 : return f_secondary_form;
930 : }
931 :
932 :
933 : /** \brief Determine the ordinal indicator for number \p n.
934 : *
935 : * This function returns the ordinal indicator for the input number \p n
936 : * as per all the specified parameters such as the language and
937 : * grammatical gender.
938 : *
939 : * This function can be called any number of times. Parameters can be changed
940 : * between calls and it will still work.
941 : *
942 : * \param[in] n The number to be given an ordinal indicator.
943 : *
944 : * \return The ordinal indicator string or "" if no indicator is available.
945 : */
946 117979 : char const * ordinal_indicator::indicator(long long n) const
947 : {
948 117979 : if(n < 1)
949 : {
950 1001 : return "";
951 : }
952 :
953 116978 : int const tenth(n % 10);
954 116978 : int const hundredth(n % 100);
955 :
956 116978 : constexpr std::size_t const max(sizeof(g_indicators) / sizeof(g_indicators[0]));
957 5098891 : for(std::size_t idx(0); idx < max; ++idx)
958 : {
959 : // language
960 : //
961 5098369 : if((g_indicators[idx].f_languages & (1 << static_cast<std::uint32_t>(f_language))) == 0)
962 : {
963 4744404 : continue;
964 : }
965 :
966 : // gender (masculine, feminine, neutral)
967 : //
968 353965 : if((g_indicators[idx].f_genders & (1 << static_cast<std::uint32_t>(f_gender))) == 0)
969 : {
970 92518 : continue;
971 : }
972 :
973 : // number (plurial, singular)
974 : //
975 261447 : if((g_indicators[idx].f_numbers & (1 << static_cast<std::uint32_t>(f_number))) == 0)
976 : {
977 53910 : continue;
978 : }
979 :
980 : // another form than the formal form
981 : //
982 207537 : if((g_indicators[idx].f_secondary_forms & (1 << static_cast<std::uint32_t>(f_secondary_form))) == 0)
983 : {
984 50487 : continue;
985 : }
986 :
987 157050 : if(g_indicators[idx].f_count != 0
988 81273 : && g_indicators[idx].f_count != n
989 40594 : && ((g_indicators[idx].f_flags & (1 << FLAG_TENTH)) == 0
990 714 : || g_indicators[idx].f_count != tenth
991 71 : || hundredth == 11
992 55 : || hundredth == 12
993 28 : || hundredth == 13))
994 : {
995 40594 : continue;
996 : }
997 :
998 116456 : return g_indicators[idx].f_ordinal_indicator;
999 : }
1000 :
1001 522 : return "";
1002 : }
1003 :
1004 :
1005 :
1006 :
1007 :
1008 :
1009 6 : } // snaplogger namespace
1010 : // vim: ts=4 sw=4 et
|