5

In iOS, if I use vswprintf with a non-western locale, it will fail and return -1.

However, if I set the locale correctly it will write properly.

Why is this? Any ideas?

phs
  • 10,687
  • 4
  • 58
  • 84
mskw
  • 10,063
  • 9
  • 42
  • 64
  • Could you provide the reference that says `vswprintf` will return `-1` when used with a non-western locale? – Jesse Good Jul 29 '12 at 23:13
  • 1
    http://stackoverflow.com/questions/3085751/swprintf-chokes-on-characters-outside-8-bit-range – mskw Jul 29 '12 at 23:14
  • 1
    I don't understand your question. `vswprintf` cares about the locale because depending on the users native language, country, etc. you don't always want to use the default locale. – Jesse Good Jul 29 '12 at 23:33
  • I thought vswprintf will print to stdout and does not care what the bytes carry. No? – mskw Jul 29 '12 at 23:56
  • @mskw: If that were true, the output would be unreadable nonsense in the most common cases. (Try using a `putchar` loop instead of `vswprintf` for a static string and watch the nonsense you get if you don't care what the bytes carry.) – David Schwartz Jul 30 '12 at 00:13
  • 6
    @mskw: `vswprintf` and family *formats* the output. It has to know how to interpret the bytes. For example, I can make it output `Monday 07/30/12 09:42:22` with the default locale or `月曜日 2012/07/30 9:42:59` if I set the locale to Japanese on my system with the same string. – Jesse Good Jul 30 '12 at 00:44
  • Thanks! I understand now! And the person below, also had the exact issue I was having. I hope I don't have to implement that on iOS. – mskw Jul 30 '12 at 03:13

1 Answers1

10

Strangely, the implementation of vswprintf on iOS converts the wide string arguments it's given to narrow strings and then converts the result back to a wide string (I had to debug this issue once). If your wide strings contain non-ASCII characters in them, then this is a lossy conversion, and only certain characters can be successfully converted.

The exact set of non-ASCII characters which can be converted depends on the current locale setting. If you try to pass in unsupported characters, then vswprintf will fail by returning -1 and setting errno to the error EILSEQ (illegal multibyte sequence).

On Mac OS X, at least, you can get around this by switching to a UTF-8 locale, e.g.:

setlocale(LC_CTYPE, "UTF-8")

However, this doesn't appear to work on iOS, so if you need to be able to vswprintf all characters without knowing the locale in advance, I'm afraid you're out of luck unless you reimplement vswprintf yourself.

Adam Rosenfield
  • 390,455
  • 97
  • 512
  • 589