-ZOOM_API(void)
- ZOOM_record_destroy(ZOOM_record rec)
-{
- ZOOM_record_release(rec);
- yaz_log(log_details0, "ZOOM_record destroy");
- xfree(rec);
-}
-
-
-static yaz_iconv_t iconv_create_charset(const char *record_charset)
-{
- char to[40];
- char from[40];
- yaz_iconv_t cd = 0;
-
- *from = '\0';
- strcpy(to, "UTF-8");
- if (record_charset && *record_charset)
- {
- /* Use "from,to" or just "from" */
- const char *cp = strchr(record_charset, ',');
- size_t clen = strlen(record_charset);
- if (cp && cp[1])
- {
- strncpy( to, cp+1, sizeof(to)-1);
- to[sizeof(to)-1] = '\0';
- clen = cp - record_charset;
- }
- if (clen > sizeof(from)-1)
- clen = sizeof(from)-1;
-
- if (clen)
- strncpy(from, record_charset, clen);
- from[clen] = '\0';
- }
- if (*from && *to)
- cd = yaz_iconv_open(to, from);
- return cd;
-}
-
-static const char *return_marc_record(WRBUF wrbuf,
- int marc_type,
- int *len,
- const char *buf, int sz,
- const char *record_charset)
-{
- yaz_iconv_t cd = iconv_create_charset(record_charset);
- yaz_marc_t mt = yaz_marc_create();
- const char *ret_string = 0;
-
- if (cd)
- yaz_marc_iconv(mt, cd);
- yaz_marc_xml(mt, marc_type);
- if (yaz_marc_decode_wrbuf(mt, buf, sz, wrbuf) > 0)
- {
- if (len)
- *len = wrbuf_len(wrbuf);
- ret_string = wrbuf_cstr(wrbuf);
- }
- yaz_marc_destroy(mt);
- if (cd)
- yaz_iconv_close(cd);
- return ret_string;
-}
-
-static const char *return_opac_record(WRBUF wrbuf,
- int marc_type,
- int *len,
- Z_OPACRecord *opac_rec,
- const char *record_charset)
-{
- yaz_iconv_t cd = iconv_create_charset(record_charset);
- yaz_marc_t mt = yaz_marc_create();
-
- if (cd)
- yaz_marc_iconv(mt, cd);
- yaz_marc_xml(mt, marc_type);
-
- yaz_opac_decode_wrbuf(mt, opac_rec, wrbuf);
- yaz_marc_destroy(mt);
-
- if (cd)
- yaz_iconv_close(cd);
- if (len)
- *len = wrbuf_len(wrbuf);
- return wrbuf_cstr(wrbuf);
-}
-
-static const char *return_string_record(WRBUF wrbuf,
- int *len,
- const char *buf, int sz,
- const char *record_charset)
-{
- yaz_iconv_t cd = iconv_create_charset(record_charset);
-
- if (cd)
- {
- wrbuf_iconv_write(wrbuf, cd, buf, sz);
- wrbuf_iconv_reset(wrbuf, cd);
-
- buf = wrbuf_cstr(wrbuf);
- sz = wrbuf_len(wrbuf);
- yaz_iconv_close(cd);
- }
- if (len)
- *len = sz;
- return buf;
-}
-
-static const char *return_record_wrbuf(WRBUF wrbuf, int *len,
- Z_NamePlusRecord *npr,
- int marctype, const char *charset)
-{
- Z_External *r = (Z_External *) npr->u.databaseRecord;
- const Odr_oid *oid = r->direct_reference;
-
- wrbuf_rewind(wrbuf);
- /* render bibliographic record .. */
- if (r->which == Z_External_OPAC)
- {
- return return_opac_record(wrbuf, marctype, len,
- r->u.opac, charset);
- }
- if (r->which == Z_External_sutrs)
- return return_string_record(wrbuf, len,
- (char*) r->u.sutrs->buf,
- r->u.sutrs->len,
- charset);
- else if (r->which == Z_External_octet)
- {
- if (yaz_oid_is_iso2709(oid))
- {
- const char *ret_buf = return_marc_record(
- wrbuf, marctype, len,
- (const char *) r->u.octet_aligned->buf,
- r->u.octet_aligned->len,
- charset);
- if (ret_buf)
- return ret_buf;
- /* bad ISO2709. Return fail unless raw (ISO2709) is wanted */
- if (marctype != YAZ_MARC_ISO2709)
- return 0;
- }
- return return_string_record(wrbuf, len,
- (const char *) r->u.octet_aligned->buf,
- r->u.octet_aligned->len,
- charset);
- }
- else if (r->which == Z_External_grs1)
- {
- yaz_display_grs1(wrbuf, r->u.grs1, 0);
- return return_string_record(wrbuf, len,
- wrbuf_buf(wrbuf),
- wrbuf_len(wrbuf),
- charset);
- }
- return 0;
-}
-
-ZOOM_API(int)
- ZOOM_record_error(ZOOM_record rec, const char **cp,
- const char **addinfo, const char **diagset)
-{
- Z_NamePlusRecord *npr;
-
- if (!rec)
- return 0;
-
- npr = rec->npr;
- if (rec->diag_uri)
- {
- if (cp)
- *cp = rec->diag_message;
- if (addinfo)
- *addinfo = rec->diag_details;
- if (diagset)
- *diagset = rec->diag_set;
- return uri_to_code(rec->diag_uri);
- }
- if (npr && npr->which == Z_NamePlusRecord_surrogateDiagnostic)
- {
- Z_DiagRec *diag_rec = npr->u.surrogateDiagnostic;
- int error = YAZ_BIB1_UNSPECIFIED_ERROR;
- const char *add = 0;
-
- if (diag_rec->which == Z_DiagRec_defaultFormat)
- {
- Z_DefaultDiagFormat *ddf = diag_rec->u.defaultFormat;
- oid_class oclass;
-
- error = *ddf->condition;
- switch (ddf->which)
- {
- case Z_DefaultDiagFormat_v2Addinfo:
- add = ddf->u.v2Addinfo;
- break;
- case Z_DefaultDiagFormat_v3Addinfo:
- add = ddf->u.v3Addinfo;
- break;
- }
- if (diagset)
- *diagset =
- yaz_oid_to_string(yaz_oid_std(),
- ddf->diagnosticSetId, &oclass);
- }
- else
- {
- if (diagset)
- *diagset = "Bib-1";
- }
- if (addinfo)
- *addinfo = add ? add : "";
- if (cp)
- *cp = diagbib1_str(error);
- return error;
- }
- return 0;
-}
-
-static const char *get_record_format(WRBUF wrbuf, int *len,
- Z_NamePlusRecord *npr,
- int marctype, const char *charset,
- const char *format)
-{
- const char *res = return_record_wrbuf(wrbuf, len, npr, marctype, charset);
-#if YAZ_HAVE_XML2
- if (*format == '1' && len)
- {
- /* try to XML format res */
- xmlDocPtr doc;
- xmlKeepBlanksDefault(0); /* get get xmlDocFormatMemory to work! */
- doc = xmlParseMemory(res, *len);
- if (doc)
- {
- xmlChar *xml_mem;
- int xml_size;
- xmlDocDumpFormatMemory(doc, &xml_mem, &xml_size, 1);
- wrbuf_rewind(wrbuf);
- wrbuf_write(wrbuf, (const char *) xml_mem, xml_size);
- xmlFree(xml_mem);
- xmlFreeDoc(doc);
- res = wrbuf_cstr(wrbuf);
- *len = wrbuf_len(wrbuf);
- }
- }
-#endif
- return res;
-}
-
-
-static const char *npr_format(Z_NamePlusRecord *npr, const char *schema,
- WRBUF wrbuf,
- const char *type_spec, int *len)
-{
- size_t i;
- char type[40];
- char charset[40];
- char format[3];
- const char *cp = type_spec;
-
- for (i = 0; cp[i] && cp[i] != ';' && cp[i] != ' ' && i < sizeof(type)-1;
- i++)
- type[i] = cp[i];
- type[i] = '\0';
- charset[0] = '\0';
- format[0] = '\0';
- while (1)
- {
- while (cp[i] == ' ')
- i++;
- if (cp[i] != ';')
- break;
- i++;
- while (cp[i] == ' ')
- i++;
- if (!strncmp(cp + i, "charset=", 8))
- {
- size_t j = 0;
- i = i + 8; /* skip charset= */
- for (j = 0; cp[i] && cp[i] != ';' && cp[i] != ' '; i++)
- {
- if (j < sizeof(charset)-1)
- charset[j++] = cp[i];
- }
- charset[j] = '\0';
- }
- else if (!strncmp(cp + i, "format=", 7))
- {
- size_t j = 0;
- i = i + 7;
- for (j = 0; cp[i] && cp[i] != ';' && cp[i] != ' '; i++)
- {
- if (j < sizeof(format)-1)
- format[j++] = cp[i];
- }
- format[j] = '\0';
- }
- }
- if (!strcmp(type, "database"))
- {
- if (len)
- *len = (npr->databaseName ? strlen(npr->databaseName) : 0);
- return npr->databaseName;
- }
- else if (!strcmp(type, "schema"))
- {
- if (len)
- *len = schema ? strlen(schema) : 0;
- return schema;
- }
- else if (!strcmp(type, "syntax"))
- {
- const char *desc = 0;
- if (npr->which == Z_NamePlusRecord_databaseRecord)
- {
- Z_External *r = (Z_External *) npr->u.databaseRecord;
- desc = yaz_oid_to_string(yaz_oid_std(), r->direct_reference, 0);
- }
- if (!desc)
- desc = "none";
- if (len)
- *len = strlen(desc);
- return desc;
- }
- if (npr->which != Z_NamePlusRecord_databaseRecord)
- return 0;
-
- /* from now on - we have a database record .. */
- if (!strcmp(type, "render"))
- {
- return get_record_format(wrbuf, len, npr, YAZ_MARC_LINE, charset, format);
- }
- else if (!strcmp(type, "xml"))
- {
- return get_record_format(wrbuf, len, npr, YAZ_MARC_MARCXML, charset,
- format);
- }
- else if (!strcmp(type, "txml"))
- {
- return get_record_format(wrbuf, len, npr, YAZ_MARC_TURBOMARC, charset,
- format);
- }
- else if (!strcmp(type, "raw"))
- {
- return get_record_format(wrbuf, len, npr, YAZ_MARC_ISO2709, charset,
- format);
- }
- else if (!strcmp(type, "ext"))
- {
- if (len) *len = -1;
- return (const char *) npr->u.databaseRecord;
- }
- else if (!strcmp(type, "opac"))
- {
- if (npr->u.databaseRecord->which == Z_External_OPAC)
- return get_record_format(wrbuf, len, npr, YAZ_MARC_MARCXML, charset,
- format);
- }
- return 0;
-}
-
-ZOOM_API(const char *)
- ZOOM_record_get(ZOOM_record rec, const char *type_spec, int *len)
-{
- WRBUF wrbuf;
-
- if (len)
- *len = 0; /* default return */
-
- if (!rec || !rec->npr)
- return 0;
-
-#if SHPTR
- if (!rec->record_wrbuf)
- {
- WRBUF w = wrbuf_alloc();
- YAZ_SHPTR_INIT(rec->record_wrbuf, w);
- }
- wrbuf = rec->record_wrbuf->ptr;
-#else
- if (!rec->wrbuf)
- rec->wrbuf = wrbuf_alloc();
- wrbuf = rec->wrbuf;
-#endif
- return npr_format(rec->npr, rec->schema, wrbuf, type_spec, len);
-}
-
-static int strcmp_null(const char *v1, const char *v2)
-{
- if (!v1 && !v2)
- return 0;
- if (!v1 || !v2)
- return -1;
- return strcmp(v1, v2);
-}
-
-static size_t record_hash(int pos)
-{
- if (pos < 0)
- pos = 0;
- return pos % RECORD_HASH_SIZE;
-}
-
-void ZOOM_record_cache_add(ZOOM_resultset r, Z_NamePlusRecord *npr,
- int pos,
- const char *syntax, const char *elementSetName,
- const char *schema,
- Z_SRW_diagnostic *diag)
-{
- ZOOM_record_cache rc = 0;
-
- ZOOM_Event event = ZOOM_Event_create(ZOOM_EVENT_RECV_RECORD);
- ZOOM_connection_put_event(r->connection, event);
-
- for (rc = r->record_hash[record_hash(pos)]; rc; rc = rc->next)
- {
- if (pos == rc->pos
- && strcmp_null(r->schema, rc->schema) == 0
- && strcmp_null(elementSetName,rc->elementSetName) == 0
- && strcmp_null(syntax, rc->syntax) == 0)
- break;
- }
- if (!rc)
- {
- rc = (ZOOM_record_cache) odr_malloc(r->odr, sizeof(*rc));
- rc->rec.odr = 0;
-#if SHPTR
- YAZ_SHPTR_INC(r->record_wrbuf);
- rc->rec.record_wrbuf = r->record_wrbuf;
-#else
- rc->rec.wrbuf = 0;
-#endif
- rc->elementSetName = odr_strdup_null(r->odr, elementSetName);
-
- rc->syntax = odr_strdup_null(r->odr, syntax);
-
- rc->schema = odr_strdup_null(r->odr, r->schema);
-
- rc->pos = pos;
- rc->next = r->record_hash[record_hash(pos)];
- r->record_hash[record_hash(pos)] = rc;
- }
- rc->rec.npr = npr;
- rc->rec.schema = odr_strdup_null(r->odr, schema);
- rc->rec.diag_set = 0;
- rc->rec.diag_uri = 0;
- rc->rec.diag_message = 0;
- rc->rec.diag_details = 0;
- if (diag)
- {
- if (diag->uri)
- {
- char *cp;
- rc->rec.diag_set = odr_strdup(r->odr, diag->uri);
- if ((cp = strrchr(rc->rec.diag_set, '/')))
- *cp = '\0';
- rc->rec.diag_uri = odr_strdup(r->odr, diag->uri);
- }
- rc->rec.diag_message = odr_strdup_null(r->odr, diag->message);
- rc->rec.diag_details = odr_strdup_null(r->odr, diag->details);
- }
-}
-
-ZOOM_record ZOOM_record_cache_lookup(ZOOM_resultset r, int pos,
- const char *syntax,
- const char *elementSetName)
-{
- ZOOM_record_cache rc;
-
- for (rc = r->record_hash[record_hash(pos)]; rc; rc = rc->next)
- {
- if (pos == rc->pos)
- {
- if (strcmp_null(r->schema, rc->schema))
- continue;
- if (strcmp_null(elementSetName,rc->elementSetName))
- continue;
- if (strcmp_null(syntax, rc->syntax))
- continue;
- return &rc->rec;
- }
- }
- return 0;
-}
-
-