19 #include <ucommon/ucommon.h>
20 #include <ucommon/export.h>
25 using namespace UCOMMON_NAMESPACE;
27 static LinkedObject *primary = NULL;
28 static LinkedObject *secondary = NULL;
30 Phrasebook::Phrasebook(
bool pri) :
39 static class __LOCAL _default :
public Phrasebook
44 bool id(
const char *lang);
48 static class __LOCAL _en_US :
public Phrasebook
53 bool id(
const char *lang);
55 void time(
const char *text, rule_t *
state);
57 void date(
const char *text, rule_t *
state);
63 linked_pointer<Phrasebook> rp;
68 lang = getenv(
"LANG");
72 return &_default_rule;
91 _default::_default() :
101 bool _en_US::id(
const char *lang)
103 if(case_eq(lang,
"en_US"))
106 if(case_eq(lang,
"en_US.", 6))
112 void _en_US::time(
const char *text, rule_t *
state)
114 const char *ap =
"a";
116 Time now((
char *)text);
117 if(now[Time::hour] >= 12) {
119 unsigned hour = now[Time::hour];
121 _lownumber(now[Time::hour] % 12, state);
123 _lownumber(12, state);
125 else if(now[Time::hour])
126 _lownumber(now[Time::hour], state);
128 _lownumber(12, state);
130 if(now[Time::minute]) {
131 if(now[Time::minute] < 10)
133 _lownumber(now[Time::minute], state);
140 void _en_US::date(
const char *text, rule_t *state)
142 static const char *_month[] = {
"",
"january",
"febuary",
"march",
"april",
"may",
"june",
"july",
"august",
"september",
"october",
"november",
"december"};
144 Date now((
char *)text);
145 _add(_month[now[Date::month]], state);
148 snprintf(buf,
sizeof(buf),
"%d", now[Date::day]);
152 bool _default::id(
const char *lang)
154 if(case_eq(lang,
"en_", 3))
157 if(case_eq(lang,
"C"))
160 if(case_eq(lang,
"en"))
166 void Phrasebook::_dup(
const char *text, rule_t *state)
168 size_t len = strlen(text) + 1;
170 state->bp = ((
char *)(&state->list[state->max])) - 1;
173 if(state->bp && ((
char *)(&state->list[state->pos + 2]) >= state->bp)) {
174 state->list[0] = NULL;
175 state->pos = state->max;
178 String::set(state->bp, len, text);
179 state->list[state->pos++] = state->bp;
180 state->list[state->pos] = NULL;
184 void Phrasebook::_add(
const char *text, rule_t *state)
186 if(state->bp && ((
char *)(&state->list[state->pos + 2]) >= state->bp)) {
187 state->list[0] = NULL;
188 state->pos = state->max;
190 else if(state->pos >= state->max - 1)
191 state->list[0] = NULL;
193 state->list[state->pos++] = text;
194 state->list[state->pos] = NULL;
198 static const char *_0to19[] =
199 {
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
200 "10",
"11",
"12",
"13",
"14",
"15",
"16",
"17",
"18",
"19"};
202 static const char *_tens[] =
203 {
"",
"10",
"20",
"30",
"40",
"50",
"60",
"70",
"80",
"90"};
205 void Phrasebook::_lownumber(
int num, rule_t *state)
209 _add(_0to19[num / 100], state);
210 _add(
"hundred", state);
217 _add(_0to19[num], state);
220 _add(_tens[num / 10], state);
222 _add(_0to19[num % 10], state);
225 void Phrasebook::nonzero(
const char *text, rule_t *state)
227 char *bp = state->bp;
228 unsigned pos = state->pos;
231 if(state->zeroflag) {
234 state->list[pos] = NULL;
238 void Phrasebook::zero(
const char *text, rule_t *state)
241 literal(text, state);
244 void Phrasebook::single(
const char *text, rule_t *state)
247 literal(text, state);
250 void Phrasebook::plural(
const char *text, rule_t *state)
253 literal(text, state);
256 void Phrasebook::number(
const char *text, rule_t *state)
260 state->zeroflag =
true;
261 state->last = atol(text);
268 _add(
"negative", state);
274 state->zeroflag =
false;
275 _lownumber(num / 1000000000, state);
276 _add(
"billion", state);
281 state->zeroflag =
false;
282 _lownumber(num / 1000000, state);
283 _add(
"million", state);
288 state->zeroflag =
false;
289 _lownumber(num / 1000, state);
290 _add(
"thousand", state);
293 if(num || state->zeroflag)
294 _lownumber(num, state);
297 state->zeroflag =
false;
299 text = strchr(text,
'.');
302 _add(
"point", state);
304 if(*text >=
'0' && *text <=
'9')
305 _add(_0to19[(*text -
'0')], state);
307 state->zeroflag =
false;
310 void Phrasebook::order(
const char *text, rule_t *state)
312 static const char *low[] = {
"th",
313 "1st",
"2nd",
"3rd",
"4th",
"5th",
314 "6th",
"7th",
"8th",
"9th",
"10th",
315 "11th",
"12th",
"13th",
"14th",
"15th",
316 "16th",
"17th",
"18th",
"19th"};
318 static const char *hi[] = {
"",
"",
"20th",
"30th",
"40th",
"50th",
"60th",
"70th",
"80th",
"90th"};
320 unsigned num = atoi(text);
321 state->last = atol(text);
326 _add(_0to19[num / 100], state);
327 _add(
"hundred", state);
330 _add(_0to19[num / 100], state);
331 _add(
"hundred", state);
339 _add(_tens[num / 10], state);
341 _add(hi[num / 10], state);
345 _add(low[num], state);
348 void Phrasebook::spell(
const char *text, rule_t *state)
354 state->bp = (
char *)(&state->list[state->max]);
356 while(text && *text) {
358 buf[0] = tolower(*(text++));
362 code = utf8::codepoint(text);
363 if(!code || code == (ucs4_t)EOF)
365 text += utf8::size(text);
366 snprintf(buf,
sizeof(buf),
"cp%lu", (
long unsigned)code);
372 void Phrasebook::literal(
const char *text, rule_t *state)
374 const char *cp = text;
381 if(isdigit(text[0]) && isdigit(text[1]) && text[2] ==
':') {
386 if(isdigit(text[0]) && isdigit(text[1]) && isdigit(text[2]) && isdigit(text[3]) && text[4] ==
'-') {
387 fulldate(text, state);
395 if(*cp ==
'.' && !dot) {
411 void Phrasebook::weekday(
const char *text, rule_t *state)
413 static const char *_dow[] = {
"sunday",
"monday",
"tuesday",
"wednasday",
"thursday",
"friday",
"saturday"};
415 Date now((
char *)text);
416 _add(_dow[now[Date::dow]], state);
419 void Phrasebook::fulldate(
const char *text, rule_t *state)
425 void Phrasebook::date(
const char *text, rule_t *state)
427 static const char *_month[] = {
"",
"january",
"febuary",
"march",
"april",
"may",
"june",
"july",
"august",
"september",
"october",
"november",
"december"};
429 Date now((
char *)text);
431 snprintf(buf,
sizeof(buf),
"%d", now[Date::day]);
433 _add(_month[now[Date::month]], state);
436 void Phrasebook::year(
const char *text, rule_t *state)
438 Date now((
char *)text);
439 unsigned year = now[Date::year];
440 unsigned hi = year / 100;
441 unsigned lo = year % 100;
444 _lownumber(hi / 10, state);
445 _add(
"thousand", state);
448 _lownumber(lo, state);
453 _lownumber(hi, state);
454 _add(
"hundred", state);
458 _lownumber(hi, state);
461 _lownumber(lo, state);
464 void Phrasebook::time(
const char *text, rule_t *state)
466 Time now((
char *)text);
467 _lownumber(now[Time::hour], state);
468 if(now[Time::minute] < 1)
470 if(now[Time::minute] < 10)
472 if(now[Time::minute])
473 _lownumber(now[Time::minute], state);
476 void Phrasebook::init(rule_t *state,
size_t size)
478 memset(state, 0, size);
479 state->max = (size -
sizeof(rule_t)) /
sizeof(
char *);
483 void Phrasebook::reset(rule_t *state)
486 init(state, state->size);
489 const char *Phrasebook::path(
void)
#define BAYONNE_NAMESPACE
GNU Bayonne library namespace.