aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/charset/iconv.h
blob: 58188bb33d463364c406e2aa2d4fa33d1e60216f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#pragma once

#include "codepage.h"

#include <util/generic/noncopyable.h>

// WARNING: Do not use this functions - use functions from wide.h or recyr.hh instead.

namespace NICONVPrivate {
    inline const char* CharsetName(ECharset code) {
        return NameByCharset(code);
    }
 
    inline const char* CharsetName(const char* code) {
        return code;
    }

    template <int size> 
    inline const char* UnicodeNameBySize();

    template <> 
    inline const char* UnicodeNameBySize<1>() {
        return "UTF-8";
    }
 
    template <> 
    inline const char* UnicodeNameBySize<2>() {
        return "UTF-16LE";
    }
 
    template <> 
    inline const char* UnicodeNameBySize<4>() {
        return "UCS-4LE";
    }

    template <class C> 
    inline const char* UnicodeName() {
        return UnicodeNameBySize<sizeof(C)>();
    }

    class TDescriptor : NNonCopyable::TNonCopyable {
    private:
        void* Descriptor_; 
        const char* From_; 
        const char* To_; 

    public:
        template <class TFrom, class TTo>
        inline TDescriptor(TFrom from, TTo to)
            : TDescriptor(CharsetName(from), CharsetName(to)) 
        {
        }

        TDescriptor(const char* from, const char* to); 
 
        ~TDescriptor(); 
 
        inline void* Get() const { 
            return Descriptor_; 
        }

        inline bool Invalid() const { 
            return Descriptor_ == (void*)(-1); 
        }

        inline const char* From() const noexcept { 
            return From_; 
        }
 
        inline const char* To() const noexcept { 
            return To_; 
        } 
    };

    template <class TFrom, class TTo>
    inline bool CanConvert(TFrom from, TTo to) {
        TDescriptor descriptor(from, to);

        return !descriptor.Invalid();
    }

    size_t RecodeImpl(const TDescriptor& descriptor, const char* in, char* out, size_t inSize, size_t outSize, size_t& read, size_t& written); 
    void DoRecode(const TDescriptor& descriptor, const char* in, char* out, size_t inSize, size_t outSize, size_t& read, size_t& written); 

    template <class TFrom, class TTo>
    inline void Recode(TFrom from, TTo to, const char* in, char* out, size_t inSize, size_t outSize, size_t& read, size_t& written) {
        TDescriptor descriptor(from, to);

        DoRecode(descriptor, in, out, inSize, outSize, read, written); 
    }

    template <class TCharType> 
    inline void RecodeToUnicode(ECharset from, const char* in, TCharType* out, size_t inSize, size_t outSize, size_t& read, size_t& written) { 
        const size_t charSize = sizeof(TCharType);

        Recode(from, UnicodeName<TCharType>(), in, reinterpret_cast<char*>(out), inSize, outSize * charSize, read, written);
        written /= charSize;
    }

    template <class TCharType> 
    inline void RecodeFromUnicode(ECharset to, const TCharType* in, char* out, size_t inSize, size_t outSize, size_t& read, size_t& written) { 
        const size_t charSize = sizeof(TCharType);

        Recode(UnicodeName<TCharType>(), to, reinterpret_cast<const char*>(in), out, inSize * charSize, outSize, read, written);
        read /= charSize;
    }

    RECODE_RESULT DoRecodeNoThrow(const TDescriptor& d, const char* in, char* out, size_t inSize, size_t outSize, size_t& read, size_t& written); 
 
    template <class TFrom, class TTo>
    inline RECODE_RESULT RecodeNoThrow(TFrom from, TTo to, const char* in, char* out, size_t inSize, size_t outSize, size_t& read, size_t& written) {
        TDescriptor descriptor(from, to);

        return DoRecodeNoThrow(descriptor, in, out, inSize, outSize, read, written); 
    }

    template <class TCharType> 
    inline RECODE_RESULT RecodeToUnicodeNoThrow(ECharset from, const char* in, TCharType* out, size_t inSize, size_t outSize, size_t& read, size_t& written) { 
        const size_t charSize = sizeof(TCharType);

        RECODE_RESULT res = RecodeNoThrow(from, UnicodeName<TCharType>(), in, reinterpret_cast<char*>(out), inSize, outSize * charSize, read, written);
        written /= charSize;

        return res;
    }

    template <class TCharType> 
    inline RECODE_RESULT RecodeFromUnicodeNoThrow(ECharset to, const TCharType* in, char* out, size_t inSize, size_t outSize, size_t& read, size_t& written) { 
        const size_t charSize = sizeof(TCharType);

        RECODE_RESULT res = RecodeNoThrow(UnicodeName<TCharType>(), to, reinterpret_cast<const char*>(in), out, inSize * charSize, outSize, read, written);
        read /= charSize;

        return res;
    }
}