Added several type casts for C++ compilation. ZOOM fixes.
[yaz-moved-to-github.git] / zutil / charneg.c
1 /* 
2  $ $Id: charneg.c,v 1.5 2002-09-24 08:05:42 adam Exp $
3  * Helper functions for Character Set and Language Negotiation - 3
4  */
5
6 #include <stdio.h>
7 #include <yaz/otherinfo.h>
8 #include <yaz/z-charneg.h>
9 #include <yaz/charneg.h>
10
11 static Z_External* z_ext_record2(ODR o, int oid_class, int oid_value,
12                                  const char *buf, int len)
13 {
14     Z_External *p;
15     oident oid;
16     
17     if (!(p = (Z_External *)odr_malloc(o, sizeof(*p)))) return 0;
18     
19     p->descriptor = 0;
20     p->indirect_reference = 0;
21     
22     oid.proto = PROTO_Z3950;
23     oid.oclass = (enum oid_class) oid_class;
24     oid.value = (enum oid_value) oid_value;
25     p->direct_reference = odr_oiddup(o, oid_getoidbyent(&oid));
26     
27     p->which = Z_External_octet;
28     if (!(p->u.octet_aligned = (Odr_oct *)odr_malloc(o, sizeof(Odr_oct)))) {
29         return 0;
30     }
31     if (!(p->u.octet_aligned->buf = (unsigned char *)odr_malloc(o, len))) {
32         return 0;
33     }
34     p->u.octet_aligned->len = p->u.octet_aligned->size = len;
35     memcpy(p->u.octet_aligned->buf, buf, len);
36         
37     return p;
38 }
39
40 static int get_form(const char *charset)
41 {
42     int form = -1;
43
44
45     if (!strcmp (charset, "UCS-2"))
46         form = 2;
47     if (!strcmp (charset, "UCS-4"))
48         form = 4;
49     if (!strcmp (charset, "UTF-16"))
50         form = 5;
51     if (!strcmp (charset, "UTF-8"))
52         form = 8;
53
54     return form;
55 }
56
57 static char *set_form (Odr_oid *encoding)
58 {
59     static char *charset = 0;
60     if ( oid_oidlen(encoding) != 6)
61         return 0;
62     if (encoding[5] == 2)
63         charset = "UCS-2";
64     if (encoding[5] == 4)
65         charset = "UCS-4";
66     if (encoding[5] == 5)
67         charset = "UTF-16";
68     if (encoding[5] == 8)
69         charset = "UTF-8";
70     return charset;
71 }
72
73 static Z_OriginProposal_0 *z_get_OriginProposal_0(ODR o, const char *charset)
74 {
75     int form = get_form (charset);
76     Z_OriginProposal_0 *p0 =
77         (Z_OriginProposal_0*)odr_malloc(o, sizeof(*p0));
78
79     memset(p0, 0, sizeof(*p0));
80
81     if (form > 0)
82     {   /* ISO 10646 (UNICODE) */
83         char oidname[20];
84
85         Z_Iso10646 *is = (Z_Iso10646 *) odr_malloc (o, sizeof(*is));
86         p0->which = Z_OriginProposal_0_iso10646;
87         p0->u.iso10646 = is;
88         is->collections = 0;
89         sprintf (oidname, "1.0.10646.1.0.%d", form);
90         is->encodingLevel = odr_getoidbystr (o, oidname);
91     }
92     else
93     {   /* private ones */
94         Z_PrivateCharacterSet *pc =
95             (Z_PrivateCharacterSet *)odr_malloc(o, sizeof(*pc));
96
97         
98         memset(pc, 0, sizeof(*pc));
99         
100         p0->which = Z_OriginProposal_0_private;
101         p0->u.zprivate = pc;
102         
103         pc->which = Z_PrivateCharacterSet_externallySpecified;
104         pc->u.externallySpecified =
105             z_ext_record2(o, CLASS_RECSYN, VAL_NOP, charset, strlen(charset));
106     }
107     return p0;
108 }
109
110 static Z_OriginProposal *z_get_OriginProposal(
111     ODR o, const char **charsets, int num_charsets,
112     const char **langs, int num_langs, int selected)
113 {       
114     int i;
115     Z_OriginProposal *p = (Z_OriginProposal *) odr_malloc(o, sizeof(*p));
116                 
117     memset(p, 0, sizeof(*p));
118
119     p->recordsInSelectedCharSets = (bool_t *)odr_malloc(o, sizeof(bool_t));
120     *p->recordsInSelectedCharSets = (selected) ? 1:0;
121
122     if (charsets && num_charsets) {             
123         
124         p->num_proposedCharSets = num_charsets;
125         p->proposedCharSets = 
126             (Z_OriginProposal_0**)
127             odr_malloc(o, num_charsets*sizeof(Z_OriginProposal_0*));
128
129         for (i = 0; i<num_charsets; i++)
130             p->proposedCharSets[i] =
131                 z_get_OriginProposal_0(o, charsets[i]);
132     }
133     if (langs && num_langs) {
134         
135         p->num_proposedlanguages = num_langs;
136
137         p->proposedlanguages = 
138             (char **) odr_malloc(o, num_langs*sizeof(char *));
139
140         for (i = 0; i<num_langs; i++) {
141
142             p->proposedlanguages[i] = (char *)langs[i];
143                         
144         }
145     }
146     return p;
147 }
148
149 static Z_CharSetandLanguageNegotiation *z_get_CharSetandLanguageNegotiation(
150     ODR o)
151 {
152     Z_CharSetandLanguageNegotiation *p =
153         (Z_CharSetandLanguageNegotiation *) odr_malloc(o, sizeof(*p));
154     
155     memset(p, 0, sizeof(*p));
156         
157     return p;
158 }
159
160 Z_External *yaz_set_proposal_charneg(ODR o,
161                                      const char **charsets, int num_charsets,
162                                      const char **langs, int num_langs,
163                                      int selected)
164 {
165     Z_External *p = (Z_External *)odr_malloc(o, sizeof(*p));
166     oident oid;
167         
168     p->descriptor = 0;
169     p->indirect_reference = 0;  
170
171     oid.proto = PROTO_Z3950;
172     oid.oclass = CLASS_NEGOT;
173     oid.value = VAL_CHARNEG3;
174     p->direct_reference = odr_oiddup(o, oid_getoidbyent(&oid));
175
176     p->which = Z_External_charSetandLanguageNegotiation;
177     p->u.charNeg3 = z_get_CharSetandLanguageNegotiation(o);
178     p->u.charNeg3->which = Z_CharSetandLanguageNegotiation_proposal;
179     p->u.charNeg3->u.proposal =
180         z_get_OriginProposal(o, charsets, num_charsets,
181                              langs, num_langs, selected);
182
183     return p;
184 }
185
186 static Z_TargetResponse *z_get_TargetResponse(ODR o, const char *charset,
187                                               const char *lang, int selected)
188 {       
189     Z_TargetResponse *p = (Z_TargetResponse *) odr_malloc(o, sizeof(*p));
190     int form = get_form(charset);
191
192     memset(p, 0, sizeof(*p));
193
194     if (form > 0)
195     {
196         char oidname[20];
197
198         Z_Iso10646 *is = (Z_Iso10646 *) odr_malloc (o, sizeof(*is));
199         p->which = Z_TargetResponse_iso10646;
200         p->u.iso10646 = is;
201         is->collections = 0;
202         sprintf (oidname, "1.0.10646.1.0.%d", form);
203         is->encodingLevel = odr_getoidbystr (o, oidname);
204     }
205     else
206     {
207         Z_PrivateCharacterSet *pc =
208             (Z_PrivateCharacterSet *)odr_malloc(o, sizeof(*pc));
209         
210         memset(pc, 0, sizeof(*pc));
211         
212         p->which = Z_TargetResponse_private;
213         p->u.zprivate = pc;
214         
215         pc->which = Z_PrivateCharacterSet_externallySpecified;
216         pc->u.externallySpecified =
217         z_ext_record2(o, CLASS_RECSYN, VAL_NOP, charset, strlen(charset));
218     }
219     p->recordsInSelectedCharSets = (bool_t *)odr_malloc(o, sizeof(bool_t));
220     *p->recordsInSelectedCharSets = (selected) ? 1:0;
221     
222     p->selectedLanguage = lang ? (char *)odr_strdup(o, lang) : 0;
223     return p;
224 }
225
226 Z_External *yaz_set_response_charneg(ODR o, const char *charset,
227                                      const char *lang, int selected)
228 {
229     Z_External *p = (Z_External *)odr_malloc(o, sizeof(*p));
230     oident oid;
231         
232     p->descriptor = 0;
233     p->indirect_reference = 0;  
234
235     oid.proto = PROTO_Z3950;
236     oid.oclass = CLASS_NEGOT;
237     oid.value = VAL_CHARNEG3;
238     p->direct_reference = odr_oiddup(o, oid_getoidbyent(&oid));
239
240     p->which = Z_External_charSetandLanguageNegotiation;
241     p->u.charNeg3 = z_get_CharSetandLanguageNegotiation(o);
242     p->u.charNeg3->which = Z_CharSetandLanguageNegotiation_response;
243     p->u.charNeg3->u.response = z_get_TargetResponse(o, charset, lang, selected);
244
245     return p;
246 }
247
248 Z_CharSetandLanguageNegotiation *yaz_get_charneg_record(Z_OtherInformation *p)
249 {
250     Z_External *pext;
251     int i;
252         
253     if(!p)
254         return 0;
255         
256     for (i=0; i<p->num_elements; i++) {
257         
258         if ((p->list[i]->which == Z_OtherInfo_externallyDefinedInfo) &&
259             (pext = p->list[i]->information.externallyDefinedInfo)) {
260                                         
261             oident *ent = oid_getentbyoid(pext->direct_reference);
262                         
263             if (ent && ent->value == VAL_CHARNEG3 && ent->oclass == CLASS_NEGOT &&
264                 pext->which == Z_External_charSetandLanguageNegotiation) {
265                                 
266                 return pext->u.charNeg3;
267             }
268         }
269     }
270         
271     return 0;
272 }
273
274 void yaz_get_proposal_charneg(NMEM mem, Z_CharSetandLanguageNegotiation *p,
275                               char ***charsets, int *num_charsets,
276                               char ***langs, int *num_langs, int *selected)
277 {
278     int i;
279     Z_OriginProposal *pro = p->u.proposal;
280     
281     if (num_charsets && charsets)
282     {
283         if (pro->num_proposedCharSets)
284         {
285             *num_charsets = pro->num_proposedCharSets;
286             
287             (*charsets) = (char **)
288                 nmem_malloc(mem, pro->num_proposedCharSets * sizeof(char *));
289             
290             for (i=0; i<pro->num_proposedCharSets; i++) 
291             {
292                 (*charsets)[i] = 0;
293                 
294                 if (pro->proposedCharSets[i]->which ==
295                     Z_OriginProposal_0_private &&
296                     pro->proposedCharSets[i]->u.zprivate->which ==
297                     Z_PrivateCharacterSet_externallySpecified) {
298                     
299                     Z_External *pext =
300                         pro->proposedCharSets[i]->u.zprivate->u.externallySpecified;
301                     
302                     if (pext->which == Z_External_octet) {
303                         
304                         (*charsets)[i] = (char *)
305                             nmem_malloc(mem, (1+pext->u.octet_aligned->len) *
306                                         sizeof(char));
307                         
308                         memcpy ((*charsets)[i], pext->u.octet_aligned->buf,
309                                 pext->u.octet_aligned->len);
310                         (*charsets)[i][pext->u.octet_aligned->len] = 0;
311                         
312                     }
313                 }
314                 else if (pro->proposedCharSets[i]->which ==
315                          Z_OriginProposal_0_iso10646)
316                     (*charsets)[i] = set_form (
317                         pro->proposedCharSets[i]->u.iso10646->encodingLevel);
318             }
319         }
320         else
321             *num_charsets = 0;
322     }
323     
324     if (langs && num_langs)
325     {
326         if (pro->num_proposedlanguages)
327         {
328             *num_langs = pro->num_proposedlanguages;
329             
330             (*langs) = (char **)
331                 nmem_malloc(mem, pro->num_proposedlanguages * sizeof(char *));
332             
333             for (i=0; i<pro->num_proposedlanguages; i++)
334                 (*langs)[i] = nmem_strdup(mem, pro->proposedlanguages[i]);
335         }
336         else
337             *num_langs = 0;
338     }
339     
340     if(pro->recordsInSelectedCharSets && selected)
341         *selected = *pro->recordsInSelectedCharSets;
342 }
343
344 void yaz_get_response_charneg(NMEM mem, Z_CharSetandLanguageNegotiation *p,
345                               char **charset, char **lang, int *selected)
346 {
347     Z_TargetResponse *res = p->u.response;
348         
349     if (charset && res->which == Z_TargetResponse_private &&
350         res->u.zprivate->which == Z_PrivateCharacterSet_externallySpecified) {
351
352         Z_External *pext = res->u.zprivate->u.externallySpecified;
353         
354         if (pext->which == Z_External_octet) {
355             
356             *charset = (char *)
357                 nmem_malloc(mem, (1+pext->u.octet_aligned->len)*sizeof(char));
358             memcpy (*charset, pext->u.octet_aligned->buf,
359                     pext->u.octet_aligned->len);
360             (*charset)[pext->u.octet_aligned->len] = 0;
361         }       
362     }
363     if (charset && res->which == Z_TargetResponse_iso10646)
364         *charset = set_form (res->u.iso10646->encodingLevel);
365     if (lang && res->selectedLanguage)
366         *lang = nmem_strdup (mem, res->selectedLanguage);
367
368     if(selected && res->recordsInSelectedCharSets)
369         *selected = *res->recordsInSelectedCharSets;
370 }