YAZ 5.37.0
iconv_encode_danmarc.c
Go to the documentation of this file.
1/* This file is part of the YAZ toolkit.
2 * Copyright (C) Index Data
3 * See the file LICENSE for details.
4 */
9
10#if HAVE_CONFIG_H
11#include <config.h>
12#endif
13
14#include <assert.h>
15#include <stdio.h>
16#include <errno.h>
17#include <string.h>
18
19#include <yaz/xmalloc.h>
20#include <yaz/snprintf.h>
21#include "iconv-p.h"
22
23#define MAX_COMP 4
24
26{
27 unsigned long comp[MAX_COMP];
28 size_t sz;
29 unsigned long base_char;
30 int dia;
31};
32
33static size_t write1(yaz_iconv_t cd, unsigned long x,
34 char **outbuf, size_t *outbytesleft)
35{
36 unsigned char *outp = (unsigned char *) *outbuf;
37 if (x == '@' || x == '*')
38 {
39 if (*outbytesleft < 2)
40 {
42 return (size_t)(-1);
43 }
44 *outp++ = '@';
45 (*outbytesleft)--;
46 *outp++ = (unsigned char) x;
47 (*outbytesleft)--;
48 }
49 else if (x <= 0xff)
50 { /* latin-1 range */
51 if (*outbytesleft < 1)
52 {
54 return (size_t)(-1);
55 }
56 *outp++ = (unsigned char) x;
57 (*outbytesleft)--;
58 }
59 else if (x <= 0xffff)
60 {
61 if (*outbytesleft < 6)
62 {
64 return (size_t)(-1);
65 }
66 switch (x)
67 {
68 case 0xa733:
69 *outp++ = '@';
70 *outp++ = 0xe5;
71 (*outbytesleft) -= 2;
72 break;
73 case 0xa732:
74 *outp++ = '@';
75 *outp++ = 0xc5;
76 (*outbytesleft) -= 2;
77 break;
78 default:
79 /* full unicode, emit @XXXX */
80 yaz_snprintf(*outbuf, 6, "@%04lX", x);
81 outp += 5;
82 (*outbytesleft) -= 5;
83 break;
84 }
85 }
86 else
87 { /* can not be encoded in Danmarc2 */
89 return (size_t)(-1);
90 }
91 *outbuf = (char *) outp;
92 return 0;
93}
94
96 char **outbuf, size_t *outbytesleft)
97{
98 struct encoder_data *w = (struct encoder_data *) e->data;
99 /* see if this is a combining thing that can be mapped to Latin-1 */
100 if (w->base_char && w->sz == 1)
101 {
102 unsigned long y;
103 if (yaz_iso_8859_1_lookup_x12(w->base_char, w->comp[0], &y))
104 {
105 w->base_char = y;
106 w->sz = 0;
107 }
108 }
109 /* combining characters in reverse */
110 while (w->sz > 0)
111 {
112 unsigned long x = w->comp[w->sz - 1];
113 if (w->dia)
115 size_t r = write1(cd, x, outbuf, outbytesleft);
116 if (r)
117 return r;
118 w->sz--;
119 }
120 /* then base char */
121 if (w->base_char)
122 {
123 size_t r = write1(cd, w->base_char, outbuf, outbytesleft);
124 if (r)
125 return r; /* if we fail base_char is still there.. */
126 w->base_char = 0;
127 }
128 return 0;
129}
130
132 unsigned long x,
133 char **outbuf, size_t *outbytesleft)
134{
135 struct encoder_data *w = (struct encoder_data *) e->data;
136
137 /* check for combining characters */
139 {
140 w->comp[w->sz++] = x;
141 if (w->sz < MAX_COMP)
142 return 0;
143 }
144 /* x is NOT a combining character. Flush previous sequence */
145 size_t r = flush_danmarc(cd, e, outbuf, outbytesleft);
146 if (r)
147 return r;
148 w->base_char = x;
149 return 0;
150}
151
153{
154 struct encoder_data *w = (struct encoder_data *) e->data;
155 w->base_char = 0;
156 w->sz = 0;
157}
158
160{
161 xfree(e->data);
162}
163
166
167{
168 if (!yaz_matchstr(tocode, "danmarc"))
169 {
170 struct encoder_data *data = (struct encoder_data *)
171 xmalloc(sizeof(*data));
172 data->dia = 0;
173 e->data = data;
178 return e;
179 }
180 if (!yaz_matchstr(tocode, "danmarc2"))
181 {
182 struct encoder_data *data = (struct encoder_data *)
183 xmalloc(sizeof(*data));
184 data->dia = 1;
185 e->data = data;
190 return e;
191 }
192 return 0;
193}
194
195/*
196 * Local variables:
197 * c-basic-offset: 4
198 * c-file-style: "Stroustrup"
199 * indent-tabs-mode: nil
200 * End:
201 * vim: shiftwidth=4 tabstop=8 expandtab
202 */
203
Header for errno utilities.
Internal header for iconv.
struct yaz_iconv_encoder_s * yaz_iconv_encoder_t
Definition iconv-p.h:42
int yaz_iso_8859_1_lookup_x12(unsigned long x1, unsigned long x2, unsigned long *y)
int yaz_danmarc_is_combining(unsigned long ch)
unsigned long yaz_danmarc_swap_to_danmarc(unsigned long ch)
void yaz_iconv_set_errno(yaz_iconv_t cd, int no)
Definition siconv.c:298
static size_t init_danmarc(yaz_iconv_t cd, yaz_iconv_decoder_t d, unsigned char *inp, size_t inbytesleft, size_t *no_read)
void destroy_danmarc(yaz_iconv_decoder_t d)
#define MAX_COMP
static size_t write_danmarc(yaz_iconv_t cd, yaz_iconv_encoder_t e, unsigned long x, char **outbuf, size_t *outbytesleft)
static void init_danmarc(yaz_iconv_encoder_t e)
yaz_iconv_encoder_t yaz_danmarc_encoder(const char *tocode, yaz_iconv_encoder_t e)
static size_t flush_danmarc(yaz_iconv_t cd, yaz_iconv_encoder_t e, char **outbuf, size_t *outbytesleft)
static size_t write1(yaz_iconv_t cd, unsigned long x, char **outbuf, size_t *outbytesleft)
static void destroy_danmarc(yaz_iconv_encoder_t e)
unsigned y
int yaz_matchstr(const char *s1, const char *s2)
match strings - independent of case and '-'
Definition matchstr.c:42
void yaz_snprintf(char *buf, size_t size, const char *fmt,...)
Definition snprintf.c:31
Header for config file reading utilities.
unsigned long comp[MAX_COMP]
unsigned long base_char
void(* init_handle)(yaz_iconv_encoder_t e)
Definition iconv-p.h:50
size_t(* write_handle)(yaz_iconv_t cd, yaz_iconv_encoder_t e, unsigned long x, char **outbuf, size_t *outbytesleft)
Definition iconv-p.h:45
void(* destroy_handle)(yaz_iconv_encoder_t e)
Definition iconv-p.h:51
size_t(* flush_handle)(yaz_iconv_t cd, yaz_iconv_encoder_t e, char **outbuf, size_t *outbytesleft)
Definition iconv-p.h:48
Header for memory handling functions.
#define xfree(x)
utility macro which calls xfree_f
Definition xmalloc.h:53
#define xmalloc(x)
utility macro which calls malloc_f
Definition xmalloc.h:49
#define YAZ_ICONV_EILSEQ
error code: Invalid sequence
Definition yaz-iconv.h:49
#define YAZ_ICONV_E2BIG
error code: Not sufficient room for output buffer
Definition yaz-iconv.h:47
struct yaz_iconv_struct * yaz_iconv_t
yaz_iconv handle (similar to iconv_t)
Definition yaz-iconv.h:42