Jumbo patch: Incorporate extraArgs in memcached key YAZ-747
[yaz-moved-to-github.git] / src / marc_read_json.c
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) Index Data
3  * See the file LICENSE for details.
4  */
5
6 /**
7  * \file marc_read_json.c
8  * \brief Implements reading of MARC in JSON format
9  */
10
11 #if HAVE_CONFIG_H
12 #include <config.h>
13 #endif
14
15 #include <assert.h>
16 #include <stdio.h>
17 #include <string.h>
18
19 #include <yaz/marcdisp.h>
20 #include <yaz/json.h>
21 #include <yaz/yaz-util.h>
22
23 static void parse_subfields(yaz_marc_t mt, struct json_node *sf, WRBUF wtmp)
24 {
25     assert(sf->type == json_node_list);
26     for (; sf; sf = sf->u.link[1])
27     {
28         if (sf->u.link[0]->type == json_node_object &&
29             sf->u.link[0]->u.link[0]->type == json_node_list)
30         {
31             struct json_node *se = sf->u.link[0]->u.link[0];
32             for (; se; se = se->u.link[1])
33             {
34                 if (se->u.link[0]->type == json_node_pair
35                     && se->u.link[0]->u.link[0]->type == json_node_string
36                     && se->u.link[0]->u.link[1]->type == json_node_string)
37                 {
38                     wrbuf_rewind(wtmp);
39                     wrbuf_puts(wtmp, se->u.link[0]->u.link[0]->u.string);
40                     wrbuf_puts(wtmp, se->u.link[0]->u.link[1]->u.string);
41                     yaz_marc_add_subfield(mt, wrbuf_buf(wtmp), wrbuf_len(wtmp));
42                 }
43             }
44         }
45     }
46 }
47
48 static void parse_field(yaz_marc_t mt, struct json_node *p,
49                         int indicator_length, WRBUF wtmp)
50 {
51     if (p->type == json_node_pair && p->u.link[0]->type == json_node_string)
52     {
53         struct json_node *l = p->u.link[1];
54         if (l->type == json_node_string)
55         {
56             yaz_marc_add_controlfield(mt, p->u.link[0]->u.string,
57                                       l->u.string, strlen(l->u.string));
58         }
59         else if (l->type == json_node_object &&
60                  l->u.link[0]->type == json_node_list)
61         {
62             struct json_node *m;
63             char indicator[10];
64
65             memset(indicator, ' ', sizeof(indicator));
66             for (m = l->u.link[0]; m; m = m->u.link[1])
67             {
68                 struct json_node *s = m->u.link[0];
69                 if (s->type == json_node_pair)
70                 {
71                     if (s->u.link[0]->type == json_node_string
72                         && !strncmp(s->u.link[0]->u.string, "ind", 3)
73                         && s->u.link[1]->type == json_node_string)
74                     {
75                         int ch = s->u.link[0]->u.string[3];
76                         if (ch >= '1' && ch < '9')
77                             indicator[ch - '1'] = s->u.link[1]->u.string[0];
78                     }
79                 }
80             }
81             yaz_marc_add_datafield(mt, p->u.link[0]->u.string,
82                                    indicator, indicator_length);
83             for (m = l->u.link[0]; m; m = m->u.link[1])
84             {
85                 struct json_node *s = m->u.link[0];
86                 if (s->type == json_node_pair)
87                 {
88                     if (s->u.link[0]->type == json_node_string
89                         && !strcmp(s->u.link[0]->u.string, "subfields")
90                         && s->u.link[1]->type == json_node_array)
91                     {
92                         parse_subfields(mt, s->u.link[1]->u.link[0], wtmp);
93                     }
94                 }
95             }
96         }
97     }
98 }
99
100 int yaz_marc_read_json_node(yaz_marc_t mt, struct json_node *n)
101 {
102     if (n && n->type == json_node_object)
103     {
104         int indicator_length;
105         int identifier_length;
106         int base_address;
107         int length_data_entry;
108         int length_starting;
109         int length_implementation;
110         struct json_node *l;
111         WRBUF wtmp = wrbuf_alloc();
112         for (l = n->u.link[0]; l; l = l->u.link[1])
113         {
114             if (l->u.link[0]->type == json_node_pair &&
115                 l->u.link[0]->u.link[0]->type == json_node_string)
116             {
117                 struct json_node *p = l->u.link[0];
118                 if (!strcmp(p->u.link[0]->u.string, "leader") &&
119                     p->u.link[1]->type == json_node_string &&
120                     strlen(p->u.link[1]->u.string) == 24)
121                 {
122                     yaz_marc_set_leader(mt, p->u.link[1]->u.string,
123                                         &indicator_length,
124                                         &identifier_length,
125                                         &base_address,
126                                         &length_data_entry,
127                                         &length_starting,
128                                         &length_implementation);
129                 }
130                 if (!strcmp(p->u.link[0]->u.string, "fields") &&
131                     p->u.link[1]->type == json_node_array &&
132                     p->u.link[1]->u.link[0] &&
133                     p->u.link[1]->u.link[0]->type == json_node_list)
134                 {
135                     struct json_node *l;
136                     for (l = p->u.link[1]->u.link[0]; l; l = l->u.link[1])
137                     {
138                         if (l->u.link[0]->type == json_node_object)
139                         {
140                             if (l->u.link[0]->u.link[0] &&
141                                 l->u.link[0]->u.link[0]->type == json_node_list)
142                             {
143                                 struct json_node *m = l->u.link[0]->u.link[0];
144                                 for (; m; m = m->u.link[1])
145                                     parse_field(mt, m->u.link[0],
146                                                 indicator_length, wtmp);
147                             }
148                         }
149                     }
150                 }
151             }
152         }
153         wrbuf_destroy(wtmp);
154         return 0;
155     }
156     return -1;
157 }
158
159 /*
160  * Local variables:
161  * c-basic-offset: 4
162  * c-file-style: "Stroustrup"
163  * indent-tabs-mode: nil
164  * End:
165  * vim: shiftwidth=4 tabstop=8 expandtab
166  */
167