File: CursesWide.c

package info (click to toggle)
libcurses-perl 1.45-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 896 kB
  • sloc: ansic: 9,185; perl: 1,485; makefile: 10
file content (292 lines) | stat: -rw-r--r-- 7,623 bytes parent folder | download
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
/* This is an inclusion for Curses.c */


/* Combined Normal/Wide-Character helper functions */

/* April 2014, Edgar Fu, Mathematisches Institut der Universitt Bonn,
  <ef@math.uni-bonn.de>
*/

#include <wchar.h>

#if HAVE_PERL_UVCHR_TO_UTF8
  #define UVCHR_TO_UTF8 uvchr_to_utf8
#elif HAVE_PERL_UV_TO_UTF8
  #define UVCHR_TO_UTF8 uv_to_utf8
#else
  #error CursesWide.c cannot be compiled on this system; no uv[chr]_to_utf8
#endif



static UV
utf8_to_uvchr_buf_x(U8 *     s,
                    U8 *     end,
                    STRLEN * lenP) {

#if HAVE_PERL_UTF8_TO_UVCHR_BUF
    return utf8_to_uvchr_buf(s, end, lenP);
#elif HAVE_PERL_UTF8_TO_UVCHR
    return utf8_to_uvchr(s, lenP);
#elif HAVE_PERL_UTF8_TO_UV
    return utf8_to_uv(s, end - s, lenP, 0);
#else
    #error CursesWide.c cannot compile because \
           there is no utf8_to_uvchr_buf, etc.
#endif
}



static void
c_wchar2sv(SV *    const sv,
           wchar_t const wc) {
/*----------------------------------------------------------------------------
  Set SV to a one-character (not -byte!) Perl string holding a given wide
  character
-----------------------------------------------------------------------------*/
    if (wc <= 0xff) {
        char s[] = { wc, 0 };
        sv_setpv(sv, s);
        SvPOK_on(sv);
        SvUTF8_off(sv);
    } else {
        char s[UTF8_MAXBYTES + 1] = { 0 };
        char *s_end = (char *)UVCHR_TO_UTF8((U8 *)s, wc);
        *s_end = 0;
        sv_setpv(sv, s);
        SvPOK_on(sv);
        SvUTF8_on(sv);
    }
}

static void
c_bstr2sv(SV *            const sv,
          unsigned char * const bs) {
/*----------------------------------------------------------------------------
  Set SV to a Perl string holding a given byte string
-----------------------------------------------------------------------------*/
    SvPOK_on(sv);
    sv_setpv(sv, (char *)bs);
    SvUTF8_off(sv);
}



static void
c_wstr2sv(SV *      const sv,
          wchar_t * const ws) {
/*----------------------------------------------------------------------------
  Set SV to a Perl string holding a given wide string
-----------------------------------------------------------------------------*/
    size_t const wsLen = wcslen(ws);

    bool needUtf8;
    unsigned int i;

    for (i = 0, needUtf8 = false; ws[i]; ++i) {
        if (ws[i] > 0xff)
            needUtf8 = true;
    }

    SvPOK_on(sv);

    if (needUtf8) {
        U8 * u8;
        U8 * u8Cursor;
        unsigned int i;

        u8 = (U8 *)sv_grow(sv, (wsLen + 1) * UTF8_MAXBYTES);
        for (i = 0, u8Cursor = &u8[0]; ws[i]; ++i)
            u8Cursor = UVCHR_TO_UTF8(u8Cursor, ws[i]);
        *u8Cursor = 0;
        SvCUR_set(sv, u8Cursor - &u8[0]);
        SvUTF8_on(sv);
    } else {
        U8 * u8;
        unsigned int i;

        u8 = (U8 *)sv_grow(sv, wsLen + 1);
        for (i = 0; ws[i]; ++i)
            u8[i] = ws[i];
        u8[i] = 0;
        SvCUR_set(sv, wsLen);
        SvUTF8_off(sv);
    }
}

static void
c_sv2GetWchar(SV *      const sv,
              wchar_t * const wcP,
              bool *    const succeededP) {
/*----------------------------------------------------------------------------
   Extract a wide character from a SV holding a one-character Perl string

   Fails (returning *succeededP false) iff SV doesn't hold a string or the
   string is not one character long.
-----------------------------------------------------------------------------*/
    if (!SvPOK(sv))
        *succeededP = false;
    else {
        U8 * s;
        STRLEN sLen;

        s = (U8 *)SvPV(sv, sLen);

        if (sLen == 0)
            *succeededP = false;
        else {
            if (SvUTF8(sv)) {
                STRLEN len;
                UV uv;

                uv = utf8_to_uvchr_buf_x(s, s + sLen, &len);

                if (len != sLen)
                    *succeededP = false;
                else {
                    *succeededP = true;
                    *wcP = (wchar_t)uv;
                }
            } else {
                if (sLen != 1)
                    *succeededP = false;
                else {
                    *succeededP = true;
                    *wcP = s[0];
                }
            }
        }
    }
}



static unsigned char *
c_sv2bstr(SV *     const sv,
          size_t * const b_len,
          int *    const need_free) {
/*----------------------------------------------------------------------------
  Extract a char (byte) string from a SV holding a Perl string

  Fails (returning NULL) if SV doesn't hold a string or the string has
  characters not fitting into a byte or doesn't UTF-8 decode

  Set b_len to length of result.

   Caller must free() result if we set need_free.
-----------------------------------------------------------------------------*/
    U8 *s, *s_p, *s_end;
    STRLEN s_len;
    unsigned char *bs, *bs_p;

    if (!SvPOK(sv)) {
        *need_free = 0;
        return NULL;
    }
    s = (U8 *)SvPV(sv, s_len);
    s_p = s;
    s_end = s + s_len;
    if (SvUTF8(sv)) {
        bs = malloc(s_len + 1);
            /* number of bytes is an upper bound on the number of characters */
        if (bs == NULL) croak("c_sv2bstr: malloc");
        bs_p = bs;
        while (s_p < s_end) {
            if (UTF8_IS_INVARIANT(*s_p)) {
                *bs_p++ = *s_p++;
            } else {
                STRLEN len;
                UV uv = utf8_to_uvchr_buf_x(s_p, s_end, &len);
                if (uv > 0xff) {
                    *need_free = 0;
                    *b_len = 0;
                    return NULL;
                }
                *bs_p++ = uv;
                s_p += len;
            }
        }
        if (s_p != s_end) {
            *need_free = 0;
            *b_len = 0;
            return NULL;
        }
        *bs_p = 0;
        *b_len = s_len;
        *need_free = 1;
        return bs;
    } else {
        *need_free = 0;
        *b_len = s_len;
        return (unsigned char *)s;
    }

}

static wchar_t *
c_sv2wstr(SV *     const sv,
          size_t * const wLenP) {
/*----------------------------------------------------------------------------
   Extract a wide char string from a SV holding a Perl string.

   Fails (returning NULL) if SV doesn't hold a string or doesn't UTF-8
   decode.

   set *wLenP to length of result.

   Caller must free result
-----------------------------------------------------------------------------*/
    wchar_t * ws;

    if (!SvPOK(sv))
        ws = NULL;
    else {
        STRLEN sLen;
        U8 * s;

        s = (U8 *)SvPV(sv, sLen);
        ws = malloc((sLen + 1) * sizeof(ws[0]));
        /* number of bytes is an upper bound on the number of characters */
        if (!ws)
            croak("c_sv2wstr: malloc");
        if (SvUTF8(sv)) {
            U8 * sP;
            U8 * sEnd;
            unsigned int i;

            sP = &s[0];
            sEnd = &s[sLen];
            i = 0;

            while (sP < sEnd) {
                if (UTF8_IS_INVARIANT(*sP)) {
                    ws[i++] = *sP++;
                } else {
                    STRLEN len;
                    ws[i++] = utf8_to_uvchr_buf_x(sP, sEnd, &len);
                    sP += len;
                }
            }
            if (sP != sEnd) {
                free(ws);
                *wLenP = 0;
                ws = NULL;
            } else {
                ws[i] = 0;
                *wLenP = sLen;
            }
        } else {
            unsigned int i;

            for (i = 0; i < sLen; ++i)
                ws[i] = s[i];

            ws[i] = 0;
            *wLenP = sLen;
        }
    }
    return ws;
}