ae47de9516ba0a3af5362cc16a30b3e8c1eee179
[yaz-moved-to-github.git] / src / srwutil.c
1 /*
2  * Copyright (C) 1995-2005, Index Data ApS
3  * See the file LICENSE for details.
4  *
5  * $Id: srwutil.c,v 1.26 2005-01-17 12:53:04 adam Exp $
6  */
7 /**
8  * \file srwutil.c
9  * \brief Implements SRW/SRU utilities.
10  */
11
12 #include <stdlib.h>
13 #include <yaz/srw.h>
14 #include <yaz/yaz-iconv.h>
15
16 static int hex_digit (int ch)
17 {
18     if (ch >= '0' && ch <= '9')
19         return ch - '0';
20     else if (ch >= 'a' && ch <= 'f')
21         return ch - 'a'+10;
22     else if (ch >= 'A' && ch <= 'F')
23         return ch - 'A'+10;
24     return 0;
25 }
26
27 int yaz_uri_array(const char *path, ODR o, char ***name, char ***val)
28 {
29     int no = 2;
30     const char *cp;
31     *name = 0;
32     if (*path != '?')
33         return no;
34     path++;
35     cp = path;
36     while ((cp = strchr(cp, '&')))
37     {
38         cp++;
39         no++;
40     }
41     *name = odr_malloc(o, no * sizeof(char**));
42     *val = odr_malloc(o, no * sizeof(char**));
43
44     for (no = 0; *path; no++)
45     {
46         const char *p1 = strchr(path, '=');
47         size_t i = 0;
48         char *ret;
49         if (!p1)
50             break;
51
52         (*name)[no] = odr_malloc(o, (p1-path)+1);
53         memcpy((*name)[no], path, p1-path);
54         (*name)[no][p1-path] = '\0';
55
56         path = p1 + 1;
57         p1 = strchr(path, '&');
58         if (!p1)
59             p1 = strlen(path) + path;
60         (*val)[no] = ret = odr_malloc(o, p1 - path + 1);
61         while (*path && *path != '&')
62         {
63             if (*path == '+')
64             {
65                 ret[i++] = ' ';
66                 path++;
67             }
68             else if (*path == '%' && path[1] && path[2])
69             {
70                 ret[i++] = hex_digit (path[1])*16 + hex_digit (path[2]);
71                 path = path + 3;
72             }
73             else
74                 ret[i++] = *path++;
75         }
76         ret[i] = '\0';
77
78         if (*path)
79             path++;
80     }
81     (*name)[no] = 0;
82     (*val)[no] = 0;
83     return no;
84 }
85
86 char *yaz_uri_val(const char *path, const char *name, ODR o)
87 {
88     size_t nlen = strlen(name);
89     if (*path != '?')
90         return 0;
91     path++;
92     while (path && *path)
93     {
94         const char *p1 = strchr(path, '=');
95         if (!p1)
96             break;
97         if ((size_t)(p1 - path) == nlen && !memcmp(path, name, nlen))
98         {
99             size_t i = 0;
100             char *ret;
101             
102             path = p1 + 1;
103             p1 = strchr(path, '&');
104             if (!p1)
105                 p1 = strlen(path) + path;
106             ret = (char *) odr_malloc(o, p1 - path + 1);
107             while (*path && *path != '&')
108             {
109                 if (*path == '+')
110                 {
111                     ret[i++] = ' ';
112                     path++;
113                 }
114                 else if (*path == '%' && path[1] && path[2])
115                 {
116                     ret[i++] = hex_digit (path[1])*16 + hex_digit (path[2]);
117                     path = path + 3;
118                 }
119                 else
120                     ret[i++] = *path++;
121             }
122             ret[i] = '\0';
123             return ret;
124         }
125         path = strchr(p1, '&');
126         if (path)
127             path++;
128     }
129     return 0;
130 }
131
132 void yaz_uri_val_int(const char *path, const char *name, ODR o, int **intp)
133 {
134     const char *v = yaz_uri_val(path, name, o);
135     if (v)
136         *intp = odr_intdup(o, atoi(v));
137 }
138
139 void yaz_mk_std_diagnostic(ODR o, Z_SRW_diagnostic *d, 
140                            int code, const char *details)
141 {
142     d->uri = (char *) odr_malloc(o, 50);
143     sprintf(d->uri, "info:srw/diagnostic/1/%d", code);
144     d->message = 0;
145     if (details)
146         d->details = odr_strdup(o, details);
147     else
148         d->details = 0;
149 }
150
151 void yaz_add_srw_diagnostic(ODR o, Z_SRW_diagnostic **d,
152                             int *num, int code, const char *addinfo)
153 {
154     Z_SRW_diagnostic *d_new;
155     d_new = (Z_SRW_diagnostic *) odr_malloc (o, (*num + 1)* sizeof(**d));
156     if (*num)
157         memcpy (d_new, *d, *num *sizeof(**d));
158     *d = d_new;
159
160     yaz_mk_std_diagnostic(o, *d + *num, code, addinfo);
161     (*num)++;
162 }
163
164 int yaz_srw_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
165                    Z_SOAP **soap_package, ODR decode, char **charset)
166 {
167     if (!strcmp(hreq->method, "POST"))
168     {
169         const char *content_type = z_HTTP_header_lookup(hreq->headers,
170                                                         "Content-Type");
171         if (content_type && !yaz_strcmp_del("text/xml", content_type, "; "))
172         {
173             char *db = "Default";
174             const char *p0 = hreq->path, *p1;
175             int ret = -1;
176             const char *charset_p = 0;
177             
178             static Z_SOAP_Handler soap_handlers[3] = {
179 #if HAVE_XML2
180                 {"http://www.loc.gov/zing/srw/", 0,
181                  (Z_SOAP_fun) yaz_srw_codec},
182                 {"http://www.loc.gov/zing/srw/v1.0/", 0,
183                  (Z_SOAP_fun) yaz_srw_codec},
184 #endif
185                 {0, 0, 0}
186             };
187             
188             if (*p0 == '/')
189                 p0++;
190             p1 = strchr(p0, '?');
191             if (!p1)
192                 p1 = p0 + strlen(p0);
193             if (p1 != p0)
194             {
195                 db = (char*) odr_malloc(decode, p1 - p0 + 1);
196                 memcpy (db, p0, p1 - p0);
197                 db[p1 - p0] = '\0';
198             }
199
200             if (charset && (charset_p = strstr(content_type, "; charset=")))
201             {
202                 int i = 0;
203                 charset_p += 10;
204                 while (i < 20 && charset_p[i] &&
205                        !strchr("; \n\r", charset_p[i]))
206                     i++;
207                 *charset = (char*) odr_malloc(decode, i+1);
208                 memcpy(*charset, charset_p, i);
209                 (*charset)[i] = '\0';
210             }
211             ret = z_soap_codec(decode, soap_package, 
212                                &hreq->content_buf, &hreq->content_len,
213                                soap_handlers);
214             if (ret == 0 && (*soap_package)->which == Z_SOAP_generic)
215             {
216                 *srw_pdu = (Z_SRW_PDU*) (*soap_package)->u.generic->p;
217                 
218                 if ((*srw_pdu)->which == Z_SRW_searchRetrieve_request &&
219                     (*srw_pdu)->u.request->database == 0)
220                     (*srw_pdu)->u.request->database = db;
221
222                 if ((*srw_pdu)->which == Z_SRW_explain_request &&
223                     (*srw_pdu)->u.explain_request->database == 0)
224                     (*srw_pdu)->u.explain_request->database = db;
225
226                 if ((*srw_pdu)->which == Z_SRW_scan_request &&
227                     (*srw_pdu)->u.scan_request->database == 0)
228                     (*srw_pdu)->u.scan_request->database = db;
229
230                 return 0;
231             }
232             return 1;
233         }
234     }
235     return 2;
236 }
237
238 /**
239   http://www.loc.gov/z3950/agency/zing/srw/service.html
240 */ 
241 int yaz_sru_decode(Z_HTTP_Request *hreq, Z_SRW_PDU **srw_pdu,
242                    Z_SOAP **soap_package, ODR decode, char **charset,
243                    Z_SRW_diagnostic **diag, int *num_diag)
244 {
245 #if HAVE_XML2
246     static Z_SOAP_Handler soap_handlers[2] = {
247         {"http://www.loc.gov/zing/srw/", 0,
248          (Z_SOAP_fun) yaz_srw_codec},
249         {0, 0, 0}
250     };
251 #endif
252     if (!strcmp(hreq->method, "GET"))
253     {
254         char *db = "Default";
255         const char *p0 = hreq->path, *p1;
256 #if HAVE_XML2
257         const char *operation = 0;
258         char *version = 0;
259         char *query = 0;
260         char *pQuery = 0;
261         char *sortKeys = 0;
262         char *stylesheet = 0;
263         char *scanClause = 0;
264         char *pScanClause = 0;
265         char *recordXPath = 0;
266         char *recordSchema = 0;
267         char *recordPacking = "xml";  /* xml packing is default for SRU */
268         char *maximumRecords = 0;
269         char *startRecord = 0;
270         char *maximumTerms = 0;
271         char *responsePosition = 0;
272         char *extraRequestData = 0;
273 #endif
274         char **uri_name;
275         char **uri_val;
276
277         if (charset)
278             *charset = 0;
279         if (*p0 == '/')
280             p0++;
281         p1 = strchr(p0, '?');
282         if (!p1)
283             p1 = p0 + strlen(p0);
284         if (p1 != p0)
285         {
286             db = (char*) odr_malloc(decode, p1 - p0 + 1);
287             memcpy (db, p0, p1 - p0);
288             db[p1 - p0] = '\0';
289         }
290         yaz_uri_array(p1, decode, &uri_name, &uri_val);
291 #if HAVE_XML2
292         if (uri_name)
293         {
294             int i;
295             for (i = 0; uri_name[i]; i++)
296             {
297                 char *n = uri_name[i];
298                 char *v = uri_val[i];
299                 if (!strcmp(n, "query"))
300                     query = v;
301                 else if (!strcmp(n, "x-pquery"))
302                     pQuery = v;
303                 else if (!strcmp(n, "operation"))
304                     operation = v;
305                 else if (!strcmp(n, "stylesheet"))
306                     stylesheet = v;
307                 else if (!strcmp(n, "sortKeys"))
308                     sortKeys = v;
309                 else if (!strcmp(n, "recordXPath"))
310                     recordXPath = v;
311                 else if (!strcmp(n, "recordSchema"))
312                     recordSchema = v;
313                 else if (!strcmp(n, "recordPacking"))
314                     recordPacking = v;
315                 else if (!strcmp(n, "version"))
316                     version = v;
317                 else if (!strcmp(n, "scanClause"))
318                     scanClause = v;
319                 else if (!strcmp(n, "x-pScanClause"))
320                     pScanClause = v;
321                 else if (!strcmp(n, "maximumRecords"))
322                     maximumRecords = v;
323                 else if (!strcmp(n, "startRecord"))
324                     startRecord = v;
325                 else if (!strcmp(n, "maximumTerms"))
326                     maximumTerms = v;
327                 else if (!strcmp(n, "responsePosition"))
328                     responsePosition = v;
329                 else if (!strcmp(n, "extraRequestData"))
330                     extraRequestData = v;
331                 else
332                     yaz_add_srw_diagnostic(decode, diag, num_diag, 8, n);
333             }
334         }
335         if (!version)
336         {
337             if (uri_name)
338                 yaz_add_srw_diagnostic(decode, diag, num_diag, 7, "version");
339             version = "1.1";
340         }
341         if (strcmp(version, "1.1"))
342             yaz_add_srw_diagnostic(decode, diag, num_diag, 5, "1.1");
343         if (!operation)
344         {
345             if (uri_name)
346                 yaz_add_srw_diagnostic(decode, diag, num_diag, 7, "operation");
347             operation = "explain";
348         }
349         if (!strcmp(operation, "searchRetrieve"))
350         {
351             Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_searchRetrieve_request);
352
353             sr->srw_version = version;
354             *srw_pdu = sr;
355             if (query)
356             {
357                 sr->u.request->query_type = Z_SRW_query_type_cql;
358                 sr->u.request->query.cql = query;
359             }
360             else if (pQuery)
361             {
362                 sr->u.request->query_type = Z_SRW_query_type_pqf;
363                 sr->u.request->query.pqf = pQuery;
364             }
365             else
366                 yaz_add_srw_diagnostic(decode, diag, num_diag, 7, "query");
367
368             if (sortKeys)
369             {
370                 sr->u.request->sort_type = Z_SRW_sort_type_sort;
371                 sr->u.request->sort.sortKeys = sortKeys;
372             }
373             sr->u.request->recordXPath = recordXPath;
374             sr->u.request->recordSchema = recordSchema;
375             sr->u.request->recordPacking = recordPacking;
376             sr->u.request->stylesheet = stylesheet;
377
378             if (maximumRecords)
379                 sr->u.request->maximumRecords =
380                     odr_intdup(decode, atoi(maximumRecords));
381             if (startRecord)
382                 sr->u.request->startRecord =
383                     odr_intdup(decode, atoi(startRecord));
384
385             sr->u.request->database = db;
386
387             (*soap_package) = odr_malloc(decode, sizeof(**soap_package));
388             (*soap_package)->which = Z_SOAP_generic;
389             
390             (*soap_package)->u.generic =
391                 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
392             
393             (*soap_package)->u.generic->p = sr;
394             (*soap_package)->u.generic->ns = soap_handlers[0].ns;
395             (*soap_package)->u.generic->no = 0;
396             
397             (*soap_package)->ns = "SRU";
398
399             return 0;
400         }
401         else if (!strcmp(operation, "explain"))
402         {
403             /* Transfer SRU explain parameters to common struct */
404             /* http://www.loc.gov/z3950/agency/zing/srw/explain.html */
405             Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_explain_request);
406
407             sr->srw_version = version;
408             *srw_pdu = sr;
409             sr->u.explain_request->recordPacking = recordPacking;
410             sr->u.explain_request->database = db;
411
412             sr->u.explain_request->stylesheet = stylesheet;
413
414             (*soap_package) = odr_malloc(decode, sizeof(**soap_package));
415             (*soap_package)->which = Z_SOAP_generic;
416             
417             (*soap_package)->u.generic =
418                 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
419             
420             (*soap_package)->u.generic->p = sr;
421             (*soap_package)->u.generic->ns = soap_handlers[0].ns;
422             (*soap_package)->u.generic->no = 0;
423             
424             (*soap_package)->ns = "SRU";
425
426             return 0;
427         }
428         else if (!strcmp(operation, "scan"))
429         {
430             /* Transfer SRU scan parameters to common struct */
431             /* http://www.loc.gov/z3950/agency/zing/srw/scan.html */
432             Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_scan_request);
433
434             sr->srw_version = version;
435             *srw_pdu = sr;
436
437             if (scanClause)
438             {
439                 sr->u.scan_request->query_type = Z_SRW_query_type_cql;
440                 sr->u.scan_request->scanClause.cql = scanClause;
441             }
442             else if (pScanClause)
443             {
444                 sr->u.scan_request->query_type = Z_SRW_query_type_pqf;
445                 sr->u.scan_request->scanClause.pqf = pScanClause;
446             }
447             else
448                 yaz_add_srw_diagnostic(decode, diag, num_diag, 7,
449                                        "scanClause");
450             sr->u.scan_request->database = db;
451
452             if (maximumTerms)
453                 sr->u.scan_request->maximumTerms =
454                     odr_intdup(decode, atoi(maximumTerms));
455             if (responsePosition)
456                 sr->u.scan_request->responsePosition =
457                     odr_intdup(decode, atoi(responsePosition));
458
459             sr->u.scan_request->stylesheet = stylesheet;
460
461             (*soap_package) = odr_malloc(decode, sizeof(**soap_package));
462             (*soap_package)->which = Z_SOAP_generic;
463             
464             (*soap_package)->u.generic =
465                 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
466             
467             (*soap_package)->u.generic->p = sr;
468             (*soap_package)->u.generic->ns = soap_handlers[0].ns;
469             (*soap_package)->u.generic->no = 0;
470             
471             (*soap_package)->ns = "SRU";
472
473             return 0;
474         }
475         else
476         {
477             /* unsupported operation ... */
478             /* Act as if we received a explain request and throw diagnostic. */
479
480             Z_SRW_PDU *sr = yaz_srw_get(decode, Z_SRW_explain_request);
481
482             sr->srw_version = version;
483             *srw_pdu = sr;
484             sr->u.explain_request->recordPacking = recordPacking;
485             sr->u.explain_request->database = db;
486
487             sr->u.explain_request->stylesheet = stylesheet;
488
489             (*soap_package) = odr_malloc(decode, sizeof(**soap_package));
490             (*soap_package)->which = Z_SOAP_generic;
491             
492             (*soap_package)->u.generic =
493                 odr_malloc(decode, sizeof(*(*soap_package)->u.generic));
494             
495             (*soap_package)->u.generic->p = sr;
496             (*soap_package)->u.generic->ns = soap_handlers[0].ns;
497             (*soap_package)->u.generic->no = 0;
498             
499             (*soap_package)->ns = "SRU";
500
501             yaz_add_srw_diagnostic(decode, diag, num_diag, 4, operation);
502             return 0;
503         }
504 #endif
505         return 1;
506     }
507     return 2;
508 }
509
510 Z_SRW_PDU *yaz_srw_get(ODR o, int which)
511 {
512     Z_SRW_PDU *sr = (Z_SRW_PDU *) odr_malloc(o, sizeof(*o));
513
514     sr->srw_version = odr_strdup(o, "1.1");
515     sr->which = which;
516     switch(which)
517     {
518     case Z_SRW_searchRetrieve_request:
519         sr->u.request = (Z_SRW_searchRetrieveRequest *)
520             odr_malloc(o, sizeof(*sr->u.request));
521         sr->u.request->query_type = Z_SRW_query_type_cql;
522         sr->u.request->query.cql = 0;
523         sr->u.request->sort_type = Z_SRW_sort_type_none;
524         sr->u.request->sort.none = 0;
525         sr->u.request->startRecord = 0;
526         sr->u.request->maximumRecords = 0;
527         sr->u.request->recordSchema = 0;
528         sr->u.request->recordPacking = 0;
529         sr->u.request->recordXPath = 0;
530         sr->u.request->database = 0;
531         sr->u.request->resultSetTTL = 0;
532         sr->u.request->stylesheet = 0;
533         break;
534     case Z_SRW_searchRetrieve_response:
535         sr->u.response = (Z_SRW_searchRetrieveResponse *)
536             odr_malloc(o, sizeof(*sr->u.response));
537         sr->u.response->numberOfRecords = 0;
538         sr->u.response->resultSetId = 0;
539         sr->u.response->resultSetIdleTime = 0;
540         sr->u.response->records = 0;
541         sr->u.response->num_records = 0;
542         sr->u.response->diagnostics = 0;
543         sr->u.response->num_diagnostics = 0;
544         sr->u.response->nextRecordPosition = 0;
545         break;
546     case Z_SRW_explain_request:
547         sr->u.explain_request = (Z_SRW_explainRequest *)
548             odr_malloc(o, sizeof(*sr->u.explain_request));
549         sr->u.explain_request->recordPacking = 0;
550         sr->u.explain_request->database = 0;
551         sr->u.explain_request->stylesheet = 0;
552         break;
553     case Z_SRW_explain_response:
554         sr->u.explain_response = (Z_SRW_explainResponse *)
555             odr_malloc(o, sizeof(*sr->u.explain_response));
556         sr->u.explain_response->record.recordData_buf = 0;
557         sr->u.explain_response->record.recordData_len = 0;
558         sr->u.explain_response->record.recordSchema = 0;
559         sr->u.explain_response->record.recordPosition = 0;
560         sr->u.explain_response->record.recordPacking =
561             Z_SRW_recordPacking_string;
562         sr->u.explain_response->diagnostics = 0;
563         sr->u.explain_response->num_diagnostics = 0;
564         break;
565     case Z_SRW_scan_request:
566         sr->u.scan_request = (Z_SRW_scanRequest *)
567             odr_malloc(o, sizeof(*sr->u.scan_request));
568         sr->u.scan_request->database = 0;
569         sr->u.scan_request->stylesheet = 0;
570         sr->u.scan_request->maximumTerms = 0;
571         sr->u.scan_request->responsePosition = 0;
572         sr->u.scan_request->query_type = Z_SRW_query_type_cql;
573         sr->u.scan_request->scanClause.cql = 0;
574         break;
575     case Z_SRW_scan_response:
576         sr->u.scan_response = (Z_SRW_scanResponse *)
577             odr_malloc(o, sizeof(*sr->u.scan_response));
578         sr->u.scan_response->terms = 0;
579         sr->u.scan_response->num_terms = 0;
580         sr->u.scan_response->diagnostics = 0;
581         sr->u.scan_response->num_diagnostics = 0;
582     }
583     return sr;
584 }
585
586
587
588 /* bib1:srw */
589 static int srw_bib1_map[] = {
590     1, 1,
591     2, 2,
592     3, 11,
593     4, 35,
594     5, 12,
595     6, 38,
596     7, 30,
597     8, 32,
598     9, 29,
599     108, 10,  /* Malformed query : Syntax error */
600     10, 10,
601     11, 12,
602     11, 23,
603     12, 60,
604     13, 61,
605     13, 62,
606     14, 63,
607     14, 64,
608     14, 65,
609     15, 68,
610     15, 69,
611     16, 70,
612     17, 70,
613     18, 50,
614     19, 55,
615     20, 56, 
616     21, 52,
617     22, 50,
618     23, 3,
619     24, 66,
620     25, 66,
621     26, 66,
622     27, 51,
623     28, 52,
624     29, 52,
625     30, 51,
626     31, 57,
627     32, 58,
628     33, 59,
629     100, 1, /* bad map */
630     101, 3,
631     102, 3,
632     103, 3,
633     104, 3,
634     105, 3, 
635     106, 66,
636     107, 11,
637     108, 13,
638     108, 14,
639     108, 25,
640     108, 26,
641     108, 27,
642     108, 45,
643         
644     109, 2,
645     110, 37,
646     111, 1,
647     112, 58,
648     113, 10,
649     114, 16,
650     115, 16,
651     116, 16,
652     117, 19,
653     117, 20,
654     118, 22,
655     119, 32,
656     119, 31,
657     120, 28,
658     121, 15,
659     122, 32,
660     123, 22,
661     123, 17,
662     123, 18,
663     124, 24,
664     125, 36,
665     126, 36, 
666     127, 36,
667     128, 51,
668     129, 39,
669     130, 43,
670     131, 40,
671     132, 42,
672     201, 44,
673     201, 33,
674     201, 34,
675     202, 41,
676     203, 43,
677     205, 1,  /* bad map */
678     206, 1,  /* bad map */
679     207, 89,
680     208, 1,  /* bad map */
681     209, 80,
682     210, 80,
683     210, 81,
684     211, 84,
685     212, 85,
686     213, 92,
687     214, 90,
688     215, 91,
689     216, 92,
690     217, 63,
691     218, 1,  /* bad map */
692     219, 1,  /* bad map */
693     220, 1,  /* bad map */
694     221, 1,  /* bad map */
695     222, 1,  /* bad map */
696     223, 1,  /* bad map */
697     224, 1,  /* bad map */
698     225, 1,  /* bad map */
699     226, 1,  /* bad map */
700     227, 66,
701     228, 1,  /* bad map */
702     229, 36,
703     230, 83,
704     231, 89,
705     232, 1,
706     233, 1, /* bad map */
707     234, 1, /* bad map */
708     235, 2,
709     236, 3, 
710     237, 82,
711     238, 67,
712     239, 66,
713     240, 1, /* bad map */
714     241, 1, /* bad map */
715     242, 70,
716     243, 1, /* bad map */
717     244, 66,
718     245, 10,
719     246, 10,
720     247, 10,
721     1001, 1, /* bad map */
722     1002, 1, /* bad map */
723     1003, 1, /* bad map */
724     1004, 1, /* bad map */
725     1005, 1, /* bad map */
726     1006, 1, /* bad map */
727     1007, 100,
728     1008, 1, 
729     1009, 1,
730     1010, 3,
731     1011, 3,
732     1012, 3,
733     1013, 3,
734     1014, 3,
735     1015, 3,
736     1015, 3,
737     1016, 3,
738     1017, 3,
739     1018, 2,
740     1019, 2,
741     1020, 2,
742     1021, 3,
743     1022, 3,
744     1023, 3,
745     1024, 16,
746     1025, 3,
747     1026, 64,
748     1027, 1,
749     1028, 65,
750     1029, 1,
751     1040, 1,
752     /* 1041-1065 */
753     1066, 66,
754     1066, 67,
755     0
756 };
757
758 int yaz_diag_bib1_to_srw (int code)
759 {
760     const int *p = srw_bib1_map;
761     while (*p)
762     {
763         if (code == p[0])
764             return p[1];
765         p += 2;
766     }
767     return 1;
768 }
769
770 int yaz_diag_srw_to_bib1(int code)
771 {
772     const int *p = srw_bib1_map;
773     while (*p)
774     {
775         if (code == p[1])
776             return p[0];
777         p += 2;
778     }
779     return 1;
780 }
781