iconv.cpp 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. #include "iconv.h"
  2. #include <iconv.h>
  3. using namespace NICONVPrivate;
  4. TDescriptor::TDescriptor(const char* from, const char* to)
  5. : Descriptor_(iconv_open(to, from))
  6. , From_(from)
  7. , To_(to)
  8. {
  9. #if defined(USE_ICONV_EXTENSIONS)
  10. if (!Invalid()) {
  11. int temp = 1;
  12. libiconvctl(Descriptor_, ICONV_SET_DISCARD_ILSEQ, &temp);
  13. }
  14. #endif
  15. }
  16. TDescriptor::~TDescriptor() {
  17. if (!Invalid()) {
  18. iconv_close(static_cast<iconv_t>(Descriptor_));
  19. }
  20. }
  21. size_t NICONVPrivate::RecodeImpl(const TDescriptor& descriptor, const char* in, char* out, size_t inSize, size_t outSize, size_t& read, size_t& written) {
  22. Y_ASSERT(!descriptor.Invalid());
  23. Y_ASSERT(in);
  24. Y_ASSERT(out);
  25. char* inPtr = const_cast<char*>(in);
  26. char* outPtr = out;
  27. size_t inSizeMod = inSize;
  28. size_t outSizeMod = outSize;
  29. size_t res = iconv(static_cast<iconv_t>(descriptor.Get()), &inPtr, &inSizeMod, &outPtr, &outSizeMod);
  30. read = inSize - inSizeMod;
  31. written = outSize - outSizeMod;
  32. return res;
  33. }
  34. void NICONVPrivate::DoRecode(const TDescriptor& descriptor, const char* in, char* out, size_t inSize, size_t outSize, size_t& read, size_t& written) {
  35. if (descriptor.Invalid()) {
  36. ythrow yexception() << "Can not convert from " << descriptor.From() << " to " << descriptor.To();
  37. }
  38. size_t res = RecodeImpl(descriptor, in, out, inSize, outSize, read, written);
  39. if (res == static_cast<size_t>(-1)) {
  40. switch (errno) {
  41. case EILSEQ:
  42. read = inSize;
  43. break;
  44. case EINVAL:
  45. read = inSize;
  46. break;
  47. case E2BIG:
  48. ythrow yexception() << "Iconv error: output buffer is too small";
  49. default:
  50. ythrow yexception() << "Unknown iconv error";
  51. }
  52. }
  53. }
  54. RECODE_RESULT NICONVPrivate::DoRecodeNoThrow(const TDescriptor& descriptor, const char* in, char* out, size_t inSize, size_t outSize, size_t& read, size_t& written) {
  55. if (descriptor.Invalid()) {
  56. return RECODE_ERROR;
  57. }
  58. size_t res = RecodeImpl(descriptor, in, out, inSize, outSize, read, written);
  59. if (res == static_cast<size_t>(-1)) {
  60. switch (errno) {
  61. case EILSEQ:
  62. read = inSize;
  63. break;
  64. case EINVAL:
  65. read = inSize;
  66. break;
  67. case E2BIG:
  68. return RECODE_EOOUTPUT;
  69. default:
  70. return RECODE_ERROR;
  71. }
  72. }
  73. return RECODE_OK;
  74. }