Improve display of MARC records with multi-byte subfield IDs YAZ-695
[yaz-moved-to-github.git] / src / ucs4.c
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) 1995-2013 Index Data
3  * See the file LICENSE for details.
4  */
5 /**
6  * \file
7  * \brief UCS4 decoding and encoding
8  */
9
10 #if HAVE_CONFIG_H
11 #include <config.h>
12 #endif
13
14 #include <assert.h>
15 #include <errno.h>
16 #include <string.h>
17
18 #include "iconv-p.h"
19
20 static unsigned long read_UCS4(yaz_iconv_t cd, yaz_iconv_decoder_t d,
21                                unsigned char *inp,
22                                size_t inbytesleft, size_t *no_read)
23 {
24     unsigned long x = 0;
25
26     if (inbytesleft < 4)
27     {
28         yaz_iconv_set_errno(cd, YAZ_ICONV_EINVAL); /* incomplete input */
29         *no_read = 0;
30     }
31     else
32     {
33         x = (inp[0]<<24) | (inp[1]<<16) | (inp[2]<<8) | inp[3];
34         *no_read = 4;
35     }
36     return x;
37 }
38
39 static unsigned long read_UCS4LE(yaz_iconv_t cd, yaz_iconv_decoder_t d,
40                                  unsigned char *inp,
41                                  size_t inbytesleft, size_t *no_read)
42 {
43     unsigned long x = 0;
44
45     if (inbytesleft < 4)
46     {
47         yaz_iconv_set_errno(cd, YAZ_ICONV_EINVAL); /* incomplete input */
48         *no_read = 0;
49     }
50     else
51     {
52         x = (inp[3]<<24) | (inp[2]<<16) | (inp[1]<<8) | inp[0];
53         *no_read = 4;
54     }
55     return x;
56 }
57
58 static size_t write_UCS4(yaz_iconv_t cd, yaz_iconv_encoder_t en,
59                          unsigned long x,
60                          char **outbuf, size_t *outbytesleft)
61 {
62     unsigned char *outp = (unsigned char *) *outbuf;
63     if (*outbytesleft >= 4)
64     {
65         *outp++ = (unsigned char) (x>>24);
66         *outp++ = (unsigned char) (x>>16);
67         *outp++ = (unsigned char) (x>>8);
68         *outp++ = (unsigned char) x;
69         (*outbytesleft) -= 4;
70     }
71     else
72     {
73         yaz_iconv_set_errno(cd, YAZ_ICONV_E2BIG);
74         return (size_t)(-1);
75     }
76     *outbuf = (char *) outp;
77     return 0;
78 }
79
80 static size_t write_UCS4LE(yaz_iconv_t cd, yaz_iconv_encoder_t en,
81                            unsigned long x,
82                            char **outbuf, size_t *outbytesleft)
83 {
84     unsigned char *outp = (unsigned char *) *outbuf;
85     if (*outbytesleft >= 4)
86     {
87         *outp++ = (unsigned char) x;
88         *outp++ = (unsigned char) (x>>8);
89         *outp++ = (unsigned char) (x>>16);
90         *outp++ = (unsigned char) (x>>24);
91         (*outbytesleft) -= 4;
92     }
93     else
94     {
95         yaz_iconv_set_errno(cd, YAZ_ICONV_E2BIG);
96         return (size_t)(-1);
97     }
98     *outbuf = (char *) outp;
99     return 0;
100 }
101
102
103 yaz_iconv_encoder_t yaz_ucs4_encoder(const char *tocode,
104                                      yaz_iconv_encoder_t e)
105
106 {
107     if (!yaz_matchstr(tocode, "UCS4"))
108         e->write_handle = write_UCS4;
109     else if (!yaz_matchstr(tocode, "UCS4LE"))
110         e->write_handle = write_UCS4LE;
111     else
112         return 0;
113     return e;
114 }
115
116 yaz_iconv_decoder_t yaz_ucs4_decoder(const char *tocode,
117                                      yaz_iconv_decoder_t d)
118
119 {
120     if (!yaz_matchstr(tocode, "UCS4"))
121         d->read_handle = read_UCS4;
122     else if (!yaz_matchstr(tocode, "UCS4LE"))
123         d->read_handle = read_UCS4LE;
124     else
125         return 0;
126     return d;
127 }
128
129
130
131 /*
132  * Local variables:
133  * c-basic-offset: 4
134  * c-file-style: "Stroustrup"
135  * indent-tabs-mode: nil
136  * End:
137  * vim: shiftwidth=4 tabstop=8 expandtab
138  */
139