@@ -41,6 +41,102 @@ cstring fossil_io_cstring_copy(ccstring str) {
4141 return fossil_io_cstring_create (str );
4242}
4343
44+ static const char * units [] = {
45+ "zero" , "one" , "two" , "three" , "four" , "five" ,
46+ "six" , "seven" , "eight" , "nine" , "ten" , "eleven" ,
47+ "twelve" , "thirteen" , "fourteen" , "fifteen" ,
48+ "sixteen" , "seventeen" , "eighteen" , "nineteen"
49+ };
50+
51+ static const char * tens [] = {
52+ "" , "" , "twenty" , "thirty" , "forty" , "fifty" ,
53+ "sixty" , "seventy" , "eighty" , "ninety"
54+ };
55+
56+ // ---------------- Number -> Words ----------------
57+ int fossil_io_cstring_number_to_words (int num , char * buffer , size_t size ) {
58+ if (!buffer || size == 0 ) return -1 ;
59+ buffer [0 ] = '\0' ;
60+
61+ if (num < 0 || num > 9999 ) return -1 ; // Limit to 0..9999
62+
63+ if (num >= 1000 ) {
64+ int thousands = num / 1000 ;
65+ if (strlen (buffer ) + strlen (units [thousands ]) + 10 >= size ) return -1 ;
66+ strcat (buffer , units [thousands ]);
67+ strcat (buffer , " thousand" );
68+ num %= 1000 ;
69+ if (num > 0 ) strcat (buffer , " " );
70+ }
71+
72+ if (num >= 100 ) {
73+ int hundreds = num / 100 ;
74+ if (strlen (buffer ) + strlen (units [hundreds ]) + 10 >= size ) return -1 ;
75+ strcat (buffer , units [hundreds ]);
76+ strcat (buffer , " hundred" );
77+ num %= 100 ;
78+ if (num > 0 ) strcat (buffer , " and " );
79+ }
80+
81+ if (num >= 20 ) {
82+ int t = num / 10 ;
83+ if (strlen (buffer ) + strlen (tens [t ]) + 2 >= size ) return -1 ;
84+ strcat (buffer , tens [t ]);
85+ num %= 10 ;
86+ if (num > 0 ) {
87+ strcat (buffer , "-" );
88+ strcat (buffer , units [num ]);
89+ }
90+ } else if (num > 0 || strlen (buffer ) == 0 ) {
91+ if (strlen (buffer ) + strlen (units [num ]) + 1 >= size ) return -1 ;
92+ strcat (buffer , units [num ]);
93+ }
94+
95+ return 0 ;
96+ }
97+
98+ // ---------------- Words -> Number ----------------
99+ static int fossil_io_word_to_value (const char * word ) {
100+ for (int i = 0 ; i < 20 ; i ++ ) if (strcmp (word , units [i ]) == 0 ) return i ;
101+ for (int i = 2 ; i < 10 ; i ++ ) if (strcmp (word , tens [i ]) == 0 ) return i * 10 ;
102+ if (strcmp (word , "hundred" ) == 0 ) return -100 ; // multiplier
103+ if (strcmp (word , "thousand" ) == 0 ) return -1000 ; // multiplier
104+ return -1 ; // not found
105+ }
106+
107+ int fossil_io_cstring_number_from_words (const char * str , int * out ) {
108+ if (!str || !out ) return -1 ;
109+
110+ int total = 0 ;
111+ int current = 0 ;
112+
113+ char buffer [256 ];
114+ strncpy (buffer , str , sizeof (buffer )- 1 );
115+ buffer [sizeof (buffer )- 1 ] = '\0' ;
116+
117+ // lowercase and remove extra characters
118+ for (char * p = buffer ; * p ; ++ p ) * p = (char )tolower (* p );
119+
120+ char * token = strtok (buffer , " -" );
121+ while (token ) {
122+ int val = fossil_io_word_to_value (token );
123+ if (val >= 0 ) {
124+ current += val ;
125+ } else if (val == -100 ) { // hundred
126+ current *= 100 ;
127+ } else if (val == -1000 ) { // thousand
128+ total += current * 1000 ;
129+ current = 0 ;
130+ } else {
131+ return -1 ; // unknown word
132+ }
133+ token = strtok (NULL , " -" );
134+ }
135+
136+ * out = total + current ;
137+ return 0 ;
138+ }
139+
44140cstring fossil_io_cstring_dup (ccstring str ) {
45141 if (!str ) return NULL ;
46142 size_t length = strlen (str );
0 commit comments