YAZ 5.35.1
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 */
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 "iconv-p.h"
21
22#define MAX_COMP 4
23
25{
26 unsigned long comp[MAX_COMP];
27 size_t sz;
28 unsigned long base_char;
29 int dia;
30};
31
32static size_t write1(yaz_iconv_t cd, unsigned long x,
33 char **outbuf, size_t *outbytesleft)
34{
35 unsigned char *outp = (unsigned char *) *outbuf;
36 if (x == '@' || x == '*')
37 {
38 if (*outbytesleft < 2)
39 {
41 return (size_t)(-1);
42 }
43 *outp++ = '@';
44 (*outbytesleft)--;
45 *outp++ = (unsigned char) x;
46 (*outbytesleft)--;
47 }
48 else if (x <= 0xff)
49 { /* latin-1 range */
50 if (*outbytesleft < 1)
51 {
53 return (size_t)(-1);
54 }
55 *outp++ = (unsigned char) x;
56 (*outbytesleft)--;
57 }
58 else if (x <= 0xffff)
59 {
60 if (*outbytesleft < 6)
61 {
63 return (size_t)(-1);
64 }
65 switch (x)
66 {
67 case 0xa733:
68 *outp++ = '@';
69 *outp++ = 0xe5;
70 (*outbytesleft) -= 2;
71 break;
72 case 0xa732:
73 *outp++ = '@';
74 *outp++ = 0xc5;
75 (*outbytesleft) -= 2;
76 break;
77 default:
78 /* full unicode, emit @XXXX */
79 sprintf(*outbuf, "@%04lX", x);
80 outp += 5;
81 (*outbytesleft) -= 5;
82 break;
83 }
84 }
85 else
86 { /* can not be encoded in Danmarc2 */
88 return (size_t)(-1);
89 }
90 *outbuf = (char *) outp;
91 return 0;
92}
93
95 char **outbuf, size_t *outbytesleft)
96{
97 struct encoder_data *w = (struct encoder_data *) e->data;
98 /* see if this is a combining thing that can be mapped to Latin-1 */
99 if (w->base_char && w->sz == 1)
100 {
101 unsigned long y;
102 if (yaz_iso_8859_1_lookup_x12(w->base_char, w->comp[0], &y))
103 {
104 w->base_char = y;
105 w->sz = 0;
106 }
107 }
108 /* combining characters in reverse */
109 while (w->sz > 0)
110 {
111 unsigned long x = w->comp[w->sz - 1];
112 if (w->dia)
114 size_t r = write1(cd, x, outbuf, outbytesleft);
115 if (r)
116 return r;
117 w->sz--;
118 }
119 /* then base char */
120 if (w->base_char)
121 {
122 size_t r = write1(cd, w->base_char, outbuf, outbytesleft);
123 if (r)
124 return r; /* if we fail base_char is still there.. */
125 w->base_char = 0;
126 }
127 return 0;
128}
129
131 unsigned long x,
132 char **outbuf, size_t *outbytesleft)
133{
134 struct encoder_data *w = (struct encoder_data *) e->data;
135
136 /* check for combining characters */
138 {
139 w->comp[w->sz++] = x;
140 if (w->sz < MAX_COMP)
141 return 0;
142 }
143 /* x is NOT a combining character. Flush previous sequence */
144 size_t r = flush_danmarc(cd, e, outbuf, outbytesleft);
145 if (r)
146 return r;
147 w->base_char = x;
148 return 0;
149}
150
152{
153 struct encoder_data *w = (struct encoder_data *) e->data;
154 w->base_char = 0;
155 w->sz = 0;
156}
157
159{
160 xfree(e->data);
161}
162
165
166{
167 if (!yaz_matchstr(tocode, "danmarc"))
168 {
169 struct encoder_data *data = (struct encoder_data *)
170 xmalloc(sizeof(*data));
171 data->dia = 0;
172 e->data = data;
177 return e;
178 }
179 if (!yaz_matchstr(tocode, "danmarc2"))
180 {
181 struct encoder_data *data = (struct encoder_data *)
182 xmalloc(sizeof(*data));
183 data->dia = 1;
184 e->data = data;
189 return e;
190 }
191 return 0;
192}
193
194/*
195 * Local variables:
196 * c-basic-offset: 4
197 * c-file-style: "Stroustrup"
198 * indent-tabs-mode: nil
199 * End:
200 * vim: shiftwidth=4 tabstop=8 expandtab
201 */
202
Header for errno utilities.
Internal header for iconv.
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
#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)
#define MAX_COMP
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
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