fromucs.c 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. /*
  2. * fromucs.c - convert Unicode to other character sets.
  3. */
  4. #include "charset.h"
  5. #include "internal.h"
  6. struct charset_emit_param {
  7. char *output;
  8. int outlen;
  9. const char *errstr;
  10. int errlen;
  11. int stopped;
  12. };
  13. static void charset_emit(void *ctx, long int output)
  14. {
  15. struct charset_emit_param *param = (struct charset_emit_param *)ctx;
  16. char outval;
  17. char const *p;
  18. int outlen;
  19. if (output == ERROR) {
  20. p = param->errstr;
  21. outlen = param->errlen;
  22. } else {
  23. outval = output;
  24. p = &outval;
  25. outlen = 1;
  26. }
  27. if (param->outlen >= outlen) {
  28. while (outlen > 0) {
  29. *param->output++ = *p++;
  30. param->outlen--;
  31. outlen--;
  32. }
  33. } else {
  34. param->stopped = 1;
  35. }
  36. }
  37. int charset_from_unicode(const wchar_t **input, int *inlen,
  38. char *output, int outlen,
  39. int charset, charset_state *state,
  40. const char *errstr, int errlen)
  41. {
  42. charset_spec const *spec = charset_find_spec(charset);
  43. charset_state localstate;
  44. struct charset_emit_param param;
  45. param.output = output;
  46. param.outlen = outlen;
  47. param.stopped = 0;
  48. /*
  49. * charset_emit will expect a valid errstr.
  50. */
  51. if (!errstr) {
  52. /* *shrug* this is good enough, and consistent across all SBCS... */
  53. param.errstr = ".";
  54. param.errlen = 1;
  55. }
  56. param.errstr = errstr;
  57. param.errlen = errlen;
  58. if (!state) {
  59. localstate.s0 = 0;
  60. } else {
  61. localstate = *state; /* structure copy */
  62. }
  63. state = &localstate;
  64. while (*inlen > 0) {
  65. int lenbefore = param.output - output;
  66. spec->write(spec, **input, &localstate, charset_emit, &param);
  67. if (param.stopped) {
  68. /*
  69. * The emit function has _tried_ to output some
  70. * characters, but ran up against the end of the
  71. * buffer. Leave immediately, and return what happened
  72. * _before_ attempting to process this character.
  73. */
  74. return lenbefore;
  75. }
  76. if (state)
  77. *state = localstate; /* structure copy */
  78. (*input)++;
  79. (*inlen)--;
  80. }
  81. return param.output - output;
  82. }