X-Git-Url: http://git.indexdata.com/?p=yaz-moved-to-github.git;a=blobdiff_plain;f=src%2Fmarcdisp.c;h=8a25d609b48a992bdd401d0e22d5754fd7609bae;hp=62200faaa4e00aea5420b6957b3b1c24a235b146;hb=4bed35ab0329789b94620258dc57db5db37bfe02;hpb=8d691989077a0addcbd840d769dce6700f3d9622 diff --git a/src/marcdisp.c b/src/marcdisp.c index 62200fa..8a25d60 100644 --- a/src/marcdisp.c +++ b/src/marcdisp.c @@ -1,8 +1,6 @@ -/* - * Copyright (C) 1995-2007, Index Data ApS +/* This file is part of the YAZ toolkit. + * Copyright (C) 1995-2009 Index Data * See the file LICENSE for details. - * - * $Id: marcdisp.c,v 1.42 2007-01-03 08:42:15 adam Exp $ */ /** @@ -20,18 +18,26 @@ #include #include +#include #include #include #include #include #include #include +#include #if YAZ_HAVE_XML2 #include #include #endif +enum yaz_collection_state { + no_collection, + collection_first, + collection_second +}; + /** \brief node types for yaz_marc_node */ enum YAZ_MARC_NODE_TYPE { @@ -84,6 +90,7 @@ struct yaz_marc_t_ { int xml; int debug; int write_using_libxml2; + enum yaz_collection_state enable_collection; yaz_iconv_t iconv_cd; char subfield_str[8]; char endline_str[8]; @@ -99,6 +106,7 @@ yaz_marc_t yaz_marc_create(void) mt->xml = YAZ_MARC_LINE; mt->debug = 0; mt->write_using_libxml2 = 0; + mt->enable_collection = no_collection; mt->m_wr = wrbuf_alloc(); mt->iconv_cd = 0; mt->leader_spec = 0; @@ -115,7 +123,7 @@ void yaz_marc_destroy(yaz_marc_t mt) if (!mt) return ; nmem_destroy(mt->nmem); - wrbuf_free(mt->m_wr, 1); + wrbuf_destroy(mt->m_wr); xfree(mt->leader_spec); xfree(mt); } @@ -125,13 +133,19 @@ NMEM yaz_marc_get_nmem(yaz_marc_t mt) return mt->nmem; } +static void marc_iconv_reset(yaz_marc_t mt, WRBUF wr) +{ + wrbuf_iconv_reset(wr, mt->iconv_cd); +} + static int marc_exec_leader(const char *leader_spec, char *leader, size_t size); static struct yaz_marc_node *yaz_marc_add_node(yaz_marc_t mt) { - struct yaz_marc_node *n = nmem_malloc(mt->nmem, sizeof(*n)); + struct yaz_marc_node *n = (struct yaz_marc_node *) + nmem_malloc(mt->nmem, sizeof(*n)); n->next = 0; *mt->nodes_pp = n; mt->nodes_pp = &n->next; @@ -161,19 +175,9 @@ void yaz_marc_cprintf(yaz_marc_t mt, const char *fmt, ...) { va_list ap; char buf[200]; - va_start(ap, fmt); -#ifdef WIN32 - _vsnprintf(buf, sizeof(buf)-1, fmt, ap); -#else -/* !WIN32 */ -#if HAVE_VSNPRINTF - vsnprintf(buf, sizeof(buf), fmt, ap); -#else - vsprintf(buf, fmt, ap); -#endif -#endif -/* WIN32 */ + va_start(ap, fmt); + yaz_vsnprintf(buf, sizeof(buf)-1, fmt, ap); yaz_marc_add_comment(mt, buf); va_end (ap); } @@ -260,7 +264,8 @@ void yaz_marc_add_subfield(yaz_marc_t mt, if (mt->subfield_pp) { - struct yaz_marc_subfield *n = nmem_malloc(mt->nmem, sizeof(*n)); + struct yaz_marc_subfield *n = (struct yaz_marc_subfield *) + nmem_malloc(mt->nmem, sizeof(*n)); n->code_data = nmem_strdupn(mt->nmem, code_data, code_data_len); n->next = 0; /* mark subfield_pp to point to this one, so we append here next */ @@ -420,7 +425,7 @@ int yaz_marc_write_check(yaz_marc_t mt, WRBUF wr) case YAZ_MARC_COMMENT: wrbuf_iconv_write(wr, mt->iconv_cd, n->u.comment, strlen(n->u.comment)); - wrbuf_puts(wr, ")\n"); + wrbuf_puts(wr, "\n"); break; default: break; @@ -429,6 +434,17 @@ int yaz_marc_write_check(yaz_marc_t mt, WRBUF wr) return 0; } +static size_t get_subfield_len(yaz_marc_t mt, const char *data, + int identifier_length) +{ + /* if identifier length is 2 (most MARCs) or less (probably an error), + the code is a single character .. However we've + seen multibyte codes, so see how big it really is */ + if (identifier_length > 2) + return identifier_length - 1; + else + return cdata_one_character(mt, data); +} int yaz_marc_write_line(yaz_marc_t mt, WRBUF wr) { @@ -458,13 +474,8 @@ int yaz_marc_write_line(yaz_marc_t mt, WRBUF wr) n->u.datafield.indicator); for (s = n->u.datafield.subfields; s; s = s->next) { - /* if identifier length is 2 (most MARCs), - the code is a single character .. However we've - seen multibyte codes, so see how big it really is */ - size_t using_code_len = - (identifier_length != 2) ? identifier_length - 1 - : - cdata_one_character(mt, s->code_data); + size_t using_code_len = get_subfield_len(mt, s->code_data, + identifier_length); wrbuf_puts (wr, mt->subfield_str); wrbuf_iconv_write(wr, mt->iconv_cd, s->code_data, @@ -472,8 +483,7 @@ int yaz_marc_write_line(yaz_marc_t mt, WRBUF wr) wrbuf_iconv_puts(wr, mt->iconv_cd, " "); wrbuf_iconv_puts(wr, mt->iconv_cd, s->code_data + using_code_len); - wrbuf_iconv_puts(wr, mt->iconv_cd, " "); - wr->pos--; + marc_iconv_reset(mt, wr); } wrbuf_puts (wr, mt->endline_str); break; @@ -481,14 +491,14 @@ int yaz_marc_write_line(yaz_marc_t mt, WRBUF wr) wrbuf_printf(wr, "%s", n->u.controlfield.tag); wrbuf_iconv_puts(wr, mt->iconv_cd, " "); wrbuf_iconv_puts(wr, mt->iconv_cd, n->u.controlfield.data); - wrbuf_iconv_puts(wr, mt->iconv_cd, " "); - wr->pos--; + marc_iconv_reset(mt, wr); wrbuf_puts (wr, mt->endline_str); break; case YAZ_MARC_COMMENT: wrbuf_puts(wr, "("); wrbuf_iconv_write(wr, mt->iconv_cd, n->u.comment, strlen(n->u.comment)); + marc_iconv_reset(mt, wr); wrbuf_puts(wr, ")\n"); break; case YAZ_MARC_LEADER: @@ -499,6 +509,28 @@ int yaz_marc_write_line(yaz_marc_t mt, WRBUF wr) return 0; } +int yaz_marc_write_trailer(yaz_marc_t mt, WRBUF wr) +{ + if (mt->enable_collection == collection_second) + { + switch(mt->xml) + { + case YAZ_MARC_MARCXML: + wrbuf_printf(wr, "\n"); + break; + case YAZ_MARC_XCHANGE: + wrbuf_printf(wr, "\n"); + break; + } + } + return 0; +} + +void yaz_marc_enable_collection(yaz_marc_t mt) +{ + mt->enable_collection = collection_first; +} + int yaz_marc_write_mode(yaz_marc_t mt, WRBUF wr) { switch(mt->xml) @@ -544,8 +576,18 @@ static int yaz_marc_write_marcxml_ns1(yaz_marc_t mt, WRBUF wr, return -1; if (!atoi_n_check(leader+11, 1, &identifier_length)) return -1; - - wrbuf_printf(wr, "enable_collection != no_collection) + { + if (mt->enable_collection == collection_first) + wrbuf_printf(wr, "\n", ns); + mt->enable_collection = collection_second; + wrbuf_printf(wr, "\n"); for (s = n->u.datafield.subfields; s; s = s->next) { - /* if identifier length is 2 (most MARCs), - the code is a single character .. However we've - seen multibyte codes, so see how big it really is */ - size_t using_code_len = - (identifier_length != 2) ? identifier_length - 1 - : - cdata_one_character(mt, s->code_data); - + size_t using_code_len = get_subfield_len(mt, s->code_data, + identifier_length); wrbuf_iconv_puts(wr, mt->iconv_cd, " iconv_cd, s->code_data, using_code_len); @@ -591,6 +627,7 @@ static int yaz_marc_write_marcxml_ns1(yaz_marc_t mt, WRBUF wr, wrbuf_iconv_write_cdata(wr, mt->iconv_cd, s->code_data + using_code_len, strlen(s->code_data + using_code_len)); + marc_iconv_reset(mt, wr); wrbuf_iconv_puts(wr, mt->iconv_cd, ""); wrbuf_puts(wr, "\n"); } @@ -601,7 +638,11 @@ static int yaz_marc_write_marcxml_ns1(yaz_marc_t mt, WRBUF wr, wrbuf_iconv_write_cdata(wr, mt->iconv_cd, n->u.controlfield.tag, strlen(n->u.controlfield.tag)); wrbuf_iconv_puts(wr, mt->iconv_cd, "\">"); - wrbuf_iconv_puts(wr, mt->iconv_cd, n->u.controlfield.data); + wrbuf_iconv_write_cdata(wr, mt->iconv_cd, + n->u.controlfield.data, + strlen(n->u.controlfield.data)); + + marc_iconv_reset(mt, wr); wrbuf_iconv_puts(wr, mt->iconv_cd, ""); wrbuf_puts(wr, "\n"); break; @@ -629,6 +670,7 @@ static int yaz_marc_write_marcxml_ns(yaz_marc_t mt, WRBUF wr, { if (mt->write_using_libxml2) { +#if YAZ_HAVE_XML2 int ret; xmlNode *root_ptr; @@ -648,6 +690,9 @@ static int yaz_marc_write_marcxml_ns(yaz_marc_t mt, WRBUF wr, xmlFreeDoc(doc); } return ret; +#else + return -1; +#endif } else return yaz_marc_write_marcxml_ns1(mt, wr, ns, format, type); @@ -655,6 +700,8 @@ static int yaz_marc_write_marcxml_ns(yaz_marc_t mt, WRBUF wr, int yaz_marc_write_marcxml(yaz_marc_t mt, WRBUF wr) { + /* set leader 09 to 'a' for UNICODE */ + /* http://www.loc.gov/marc/bibliographic/ecbdldrd.html#mrcblea */ if (!mt->leader_spec) yaz_marc_modify_leader(mt, 9, "a"); return yaz_marc_write_marcxml_ns(mt, wr, "http://www.loc.gov/MARC21/slim", @@ -666,22 +713,23 @@ int yaz_marc_write_marcxchange(yaz_marc_t mt, WRBUF wr, const char *type) { return yaz_marc_write_marcxml_ns(mt, wr, - "http://www.bs.dk/standards/MarcXchange", + "info:lc/xmlns/marcxchange-v1", 0, 0); } +#if YAZ_HAVE_XML2 int yaz_marc_write_xml(yaz_marc_t mt, xmlNode **root_ptr, const char *ns, const char *format, const char *type) { -#if YAZ_HAVE_XML2 struct yaz_marc_node *n; int identifier_length; const char *leader = 0; xmlNode *record_ptr; xmlNsPtr ns_record; + WRBUF wr_cdata = 0; for (n = mt->nodes; n; n = n->next) if (n->which == YAZ_MARC_LEADER) @@ -695,6 +743,8 @@ int yaz_marc_write_xml(yaz_marc_t mt, xmlNode **root_ptr, if (!atoi_n_check(leader+11, 1, &identifier_length)) return -1; + wr_cdata = wrbuf_alloc(); + record_ptr = xmlNewNode(0, BAD_CAST "record"); *root_ptr = record_ptr; @@ -731,35 +781,32 @@ int yaz_marc_write_xml(yaz_marc_t mt, xmlNode **root_ptr, } for (s = n->u.datafield.subfields; s; s = s->next) { - char code_val[8]; - xmlNode *ptr_subfield; - /* if identifier length is 2 (most MARCs), - the code is a single character .. However we've - seen multibyte codes, so see how big it really is */ - size_t using_code_len = - (identifier_length != 2) ? identifier_length - 1 - : - cdata_one_character(mt, s->code_data); - - if (using_code_len >= sizeof(code_val)-1) - continue; - + size_t using_code_len = get_subfield_len(mt, s->code_data, + identifier_length); + wrbuf_rewind(wr_cdata); + wrbuf_iconv_puts(wr_cdata, mt->iconv_cd, + s->code_data + using_code_len); + marc_iconv_reset(mt, wr_cdata); ptr_subfield = xmlNewTextChild( ptr, ns_record, - BAD_CAST "subfield", - BAD_CAST (s->code_data + using_code_len)); - - memcpy(code_val, s->code_data, using_code_len); - code_val[using_code_len] = '\0'; + BAD_CAST "subfield", BAD_CAST wrbuf_cstr(wr_cdata)); - xmlNewProp(ptr_subfield, BAD_CAST "code", BAD_CAST code_val); + wrbuf_rewind(wr_cdata); + wrbuf_iconv_write(wr_cdata, mt->iconv_cd, + s->code_data, using_code_len); + xmlNewProp(ptr_subfield, BAD_CAST "code", + BAD_CAST wrbuf_cstr(wr_cdata)); } break; case YAZ_MARC_CONTROLFIELD: + wrbuf_rewind(wr_cdata); + wrbuf_iconv_puts(wr_cdata, mt->iconv_cd, n->u.controlfield.data); + marc_iconv_reset(mt, wr_cdata); + ptr = xmlNewTextChild(record_ptr, ns_record, BAD_CAST "controlfield", - BAD_CAST n->u.controlfield.data); + BAD_CAST wrbuf_cstr(wr_cdata)); xmlNewProp(ptr, BAD_CAST "tag", BAD_CAST n->u.controlfield.tag); break; @@ -773,11 +820,10 @@ int yaz_marc_write_xml(yaz_marc_t mt, xmlNode **root_ptr, break; } } + wrbuf_destroy(wr_cdata); return 0; -#else - return -1; -#endif } +#endif int yaz_marc_write_iso2709(yaz_marc_t mt, WRBUF wr) { @@ -827,9 +873,11 @@ int yaz_marc_write_iso2709(yaz_marc_t mt, WRBUF wr) /* write dummy IDFS + content */ wrbuf_iconv_putchar(wr_data_tmp, mt->iconv_cd, ' '); wrbuf_iconv_puts(wr_data_tmp, mt->iconv_cd, s->code_data); + marc_iconv_reset(mt, wr_data_tmp); } /* write dummy FS (makes MARC-8 to become ASCII) */ wrbuf_iconv_putchar(wr_data_tmp, mt->iconv_cd, ' '); + marc_iconv_reset(mt, wr_data_tmp); data_length += wrbuf_len(wr_data_tmp); break; case YAZ_MARC_CONTROLFIELD: @@ -838,7 +886,9 @@ int yaz_marc_write_iso2709(yaz_marc_t mt, WRBUF wr) wrbuf_rewind(wr_data_tmp); wrbuf_iconv_puts(wr_data_tmp, mt->iconv_cd, n->u.controlfield.data); + marc_iconv_reset(mt, wr_data_tmp); wrbuf_iconv_putchar(wr_data_tmp, mt->iconv_cd, ' ');/* field sep */ + marc_iconv_reset(mt, wr_data_tmp); data_length += wrbuf_len(wr_data_tmp); break; case YAZ_MARC_COMMENT: @@ -872,9 +922,9 @@ int yaz_marc_write_iso2709(yaz_marc_t mt, WRBUF wr) wrbuf_write(wr, wrbuf_buf(wr_head), 24); wrbuf_write(wr, wrbuf_buf(wr_dir), wrbuf_len(wr_dir)); - wrbuf_free(wr_head, 1); - wrbuf_free(wr_dir, 1); - wrbuf_free(wr_data_tmp, 1); + wrbuf_destroy(wr_head); + wrbuf_destroy(wr_dir); + wrbuf_destroy(wr_data_tmp); for (n = mt->nodes; n; n = n->next) { @@ -889,17 +939,13 @@ int yaz_marc_write_iso2709(yaz_marc_t mt, WRBUF wr) { wrbuf_putc(wr, ISO2709_IDFS); wrbuf_iconv_puts(wr, mt->iconv_cd, s->code_data); - /* write dummy blank - makes MARC-8 to become ASCII */ - wrbuf_iconv_putchar(wr, mt->iconv_cd, ' '); - wr->pos--; + marc_iconv_reset(mt, wr); } wrbuf_putc(wr, ISO2709_FS); break; case YAZ_MARC_CONTROLFIELD: wrbuf_iconv_puts(wr, mt->iconv_cd, n->u.controlfield.data); - /* write dummy blank - makes MARC-8 to become ASCII */ - wrbuf_iconv_putchar(wr, mt->iconv_cd, ' '); - wr->pos--; + marc_iconv_reset(mt, wr); wrbuf_putc(wr, ISO2709_FS); break; case YAZ_MARC_COMMENT: @@ -925,14 +971,14 @@ int yaz_marc_decode_wrbuf(yaz_marc_t mt, const char *buf, int bsize, WRBUF wr) } int yaz_marc_decode_buf (yaz_marc_t mt, const char *buf, int bsize, - char **result, int *rsize) + const char **result, size_t *rsize) { int r; wrbuf_rewind(mt->m_wr); r = yaz_marc_decode_wrbuf(mt, buf, bsize, mt->m_wr); if (result) - *result = wrbuf_buf(mt->m_wr); + *result = wrbuf_cstr(mt->m_wr); if (rsize) *rsize = wrbuf_len(mt->m_wr); return r; @@ -955,6 +1001,11 @@ void yaz_marc_iconv(yaz_marc_t mt, yaz_iconv_t cd) mt->iconv_cd = cd; } +yaz_iconv_t yaz_marc_get_iconv(yaz_marc_t mt) +{ + return mt->iconv_cd; +} + void yaz_marc_modify_leader(yaz_marc_t mt, size_t off, const char *str) { struct yaz_marc_node *n; @@ -968,53 +1019,6 @@ void yaz_marc_modify_leader(yaz_marc_t mt, size_t off, const char *str) } } -/* deprecated */ -int yaz_marc_decode(const char *buf, WRBUF wr, int debug, int bsize, int xml) -{ - yaz_marc_t mt = yaz_marc_create(); - int r; - - mt->debug = debug; - mt->xml = xml; - r = yaz_marc_decode_wrbuf(mt, buf, bsize, wr); - yaz_marc_destroy(mt); - return r; -} - -/* deprecated */ -int marc_display_wrbuf (const char *buf, WRBUF wr, int debug, int bsize) -{ - return yaz_marc_decode(buf, wr, debug, bsize, 0); -} - -/* deprecated */ -int marc_display_exl (const char *buf, FILE *outf, int debug, int bsize) -{ - yaz_marc_t mt = yaz_marc_create(); - int r; - - mt->debug = debug; - r = yaz_marc_decode_wrbuf (mt, buf, bsize, mt->m_wr); - if (!outf) - outf = stdout; - if (r > 0) - fwrite (wrbuf_buf(mt->m_wr), 1, wrbuf_len(mt->m_wr), outf); - yaz_marc_destroy(mt); - return r; -} - -/* deprecated */ -int marc_display_ex (const char *buf, FILE *outf, int debug) -{ - return marc_display_exl (buf, outf, debug, -1); -} - -/* deprecated */ -int marc_display (const char *buf, FILE *outf) -{ - return marc_display_ex (buf, outf, 0); -} - int yaz_marc_leader_spec(yaz_marc_t mt, const char *leader_spec) { xfree(mt->leader_spec); @@ -1041,7 +1045,7 @@ static int marc_exec_leader(const char *leader_spec, char *leader, size_t size) no = sscanf(cp, "%d=%20[^,]%n", &pos, val, &no_read); if (no < 2 || no_read < 3) return -1; - if (pos < 0 || pos >= size) + if (pos < 0 || (size_t) pos >= size) return -1; if (*val == '\'') @@ -1094,6 +1098,7 @@ void yaz_marc_write_using_libxml2(yaz_marc_t mt, int enable) /* * Local variables: * c-basic-offset: 4 + * c-file-style: "Stroustrup" * indent-tabs-mode: nil * End: * vim: shiftwidth=4 tabstop=8 expandtab