@@ -24,10 +24,11 @@ #include #include #import "OFString.h" +#import "OFSystemInfo.h" #define MAX_SUBFORMAT_LEN 64 #ifndef HAVE_ASPRINTF /* @@ -64,10 +65,11 @@ LENGTH_MODIFIER_J, LENGTH_MODIFIER_Z, LENGTH_MODIFIER_T, LENGTH_MODIFIER_CAPITAL_L } lengthModifier; + bool useLocale; }; #ifndef HAVE_ASPRINTF static int vasprintf(char **string, const char *format, va_list arguments) @@ -163,10 +165,14 @@ case '0': if (!appendSubformat(ctx, ctx->format + ctx->i, 1)) return false; break; + case ',': + /* ObjFW extension: Use decimal point from locale */ + ctx->useLocale = true; + break; default: ctx->state = STATE_FORMAT_FIELD_WIDTH; ctx->i--; break; @@ -499,10 +505,39 @@ va_arg(ctx->arguments, long double)); break; default: return false; } + + /* + * Ugly hack to undo locale, as there is nothing such as + * asprintf_l in POSIX. + */ + if (!ctx->useLocale) { + void *pool = objc_autoreleasePoolPush(); + char *tmp2; + + @try { + OFMutableString *tmpStr = [OFMutableString + stringWithUTF8String: tmp + length: tmpLen]; + OFString *decimalPoint = + [OFSystemInfo decimalPoint]; + [tmpStr replaceOccurrencesOfString: decimalPoint + withString: @"."]; + if ([tmpStr UTF8StringLength] > INT_MAX) + return false; + tmpLen = (int)[tmpStr UTF8StringLength]; + tmp2 = malloc(tmpLen); + memcpy(tmp2, [tmpStr UTF8String], tmpLen); + } @finally { + free(tmp); + objc_autoreleasePoolPop(pool); + } + + tmp = tmp2; + } break; case 'c': switch (ctx->lengthModifier) { case LENGTH_MODIFIER_NONE: @@ -610,10 +645,11 @@ } memset(ctx->subformat, 0, MAX_SUBFORMAT_LEN); ctx->subformatLen = 0; ctx->lengthModifier = LENGTH_MODIFIER_NONE; + ctx->useLocale = false; ctx->last = ctx->i + 1; ctx->state = STATE_STRING; return true; @@ -639,10 +675,11 @@ va_copy(ctx.arguments, arguments); ctx.bufferLen = 0; ctx.last = 0; ctx.state = STATE_STRING; ctx.lengthModifier = LENGTH_MODIFIER_NONE; + ctx.useLocale = false; if ((ctx.buffer = malloc(1)) == NULL) return -1; for (ctx.i = 0; ctx.i < ctx.formatLen; ctx.i++) {