60 const int NUM_PIECES = 9;
61 const int WORK_SIZE = 1024;
62 char pieces[NUM_PIECES][WORK_SIZE];
63 int current_piece = 0;
70 int compass_dir_piece = -1;
74 int deg_has_decpoint = 0;
75 int deg_dec_digits = 0;
80 int min_has_decpoint = 0;
81 int min_dec_digits = 0;
86 int sec_has_decpoint = 0;
87 int sec_dec_digits = 0;
90 int format_length = ((NULL == format) ? 0 : strlen(format));
94 int index, following_byte_index;
95 int multibyte_char_width = 1;
100 for (index = 0; index < NUM_PIECES; index++)
102 pieces[index][0] =
'\0';
106 if (0 == format_length)
109 format =
"D\xC2\xB0""M'S.SSS\"C";
110 format_length = strlen(format);
112 else if (format_length > WORK_SIZE)
116 lwerror(
"Bad format, exceeds maximum length (%d).", WORK_SIZE);
119 for (index = 0; index < format_length; index++)
121 char next_char = format[index];
128 deg_has_decpoint ? deg_dec_digits++ : deg_digits++;
134 deg_piece = current_piece;
137 lwerror(
"Bad format, cannot include degrees (DD.DDD) more than once.");
149 min_has_decpoint ? min_dec_digits++ : min_digits++;
155 min_piece = current_piece;
158 lwerror(
"Bad format, cannot include minutes (MM.MMM) more than once.");
170 sec_has_decpoint ? sec_dec_digits++ : sec_digits++;
176 sec_piece = current_piece;
179 lwerror(
"Bad format, cannot include seconds (SS.SSS) more than once.");
189 if (reading_deg || reading_min || reading_sec)
198 if (compass_dir_piece >= 0)
200 lwerror(
"Bad format, cannot include compass dir (C) more than once.");
203 compass_dir_piece = current_piece;
210 deg_has_decpoint = 1;
212 else if (reading_min)
214 min_has_decpoint = 1;
216 else if (reading_sec)
218 sec_has_decpoint = 1;
223 strncat(pieces[current_piece], &next_char, 1);
228 if (reading_deg || reading_min || reading_sec)
238 multibyte_char_width = 1;
239 if (next_char & 0x80)
241 if ((next_char & 0xF8) == 0xF0)
243 multibyte_char_width += 3;
245 else if ((next_char & 0xF0) == 0xE0)
247 multibyte_char_width += 2;
249 else if ((next_char & 0xE0) == 0xC0)
251 multibyte_char_width += 1;
255 lwerror(
"Bad format, invalid high-order byte found first, format string may not be UTF-8.");
258 if (multibyte_char_width > 1)
260 if (index + multibyte_char_width >= format_length)
262 lwerror(
"Bad format, UTF-8 character first byte found with insufficient following bytes, format string may not be UTF-8.");
264 for (following_byte_index = (index + 1); following_byte_index < (index + multibyte_char_width); following_byte_index++)
266 if ((format[following_byte_index] & 0xC0) != 0x80)
268 lwerror(
"Bad format, invalid byte found following leading byte of multibyte character, format string may not be UTF-8.");
273 strncat(pieces[current_piece], &(format[index]), multibyte_char_width);
275 index += multibyte_char_width - 1;
278 if (current_piece >= NUM_PIECES)
280 lwerror(
"Internal error, somehow needed more pieces than it should.");
285 lwerror(
"Bad format, degrees (DD.DDD) must be included.");
297 degrees = (long)degrees;
298 minutes = (val - degrees) * 60;
304 lwerror(
"Bad format, cannot include seconds (SS.SSS) without including minutes (MM.MMM).");
306 minutes = (long)minutes;
307 seconds = (val - (degrees + (minutes / 60))) * 3600;
311 if (compass_dir_piece >= 0)
313 strcpy(pieces[compass_dir_piece], is_negative ? neg_dir_symbol : pos_dir_symbol);
315 else if (is_negative)
321 if (deg_digits + deg_dec_digits + 2 > WORK_SIZE)
323 lwerror(
"Bad format, degrees (DD.DDD) number of digits was greater than our working limit.");
325 sprintf(pieces[deg_piece],
"%*.*f", deg_digits, deg_dec_digits, degrees);
330 if (min_digits + min_dec_digits + 2 > WORK_SIZE)
332 lwerror(
"Bad format, minutes (MM.MMM) number of digits was greater than our working limit.");
334 sprintf(pieces[min_piece],
"%*.*f", min_digits, min_dec_digits, minutes);
339 if (sec_digits + sec_dec_digits + 2 > WORK_SIZE)
341 lwerror(
"Bad format, seconds (SS.SSS) number of digits was greater than our working limit.");
343 sprintf(pieces[sec_piece],
"%*.*f", sec_digits, sec_dec_digits, seconds);
347 result = (
char*)
lwalloc(format_length + WORK_SIZE);
349 strcpy(result, pieces[0]);
350 for (index = 1; index < NUM_PIECES; index++)
352 strcat(result, pieces[index]);
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
void * lwalloc(size_t size)