Pass /manifest option always YAZ-804
[yaz-moved-to-github.git] / ztest / read-marc.c
index 9f90f82..0b9dc1d 100644 (file)
@@ -1,18 +1,39 @@
-/*
- * Copyright (c) 2002, Index Data.
+/* This file is part of the YAZ toolkit.
+ * Copyright (C) Index Data
  * See the file LICENSE for details.
- *
- * $Id: read-marc.c,v 1.2 2002-03-19 13:48:27 adam Exp $
  */
-
-/*
- * Little toy-thing to read a MARC records from a fixed array.
+/** \file
+ * \brief Little toy-thing to read MARC records from a fixed array.
  */
-#include <ctype.h>
-#include <yaz/odr.h>
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
 #include <yaz/wrbuf.h>
+#include <yaz/marcdisp.h>
+#include <yaz/odr.h>
+#include <yaz/log.h>
+
+#include "ztest.h"
+
+#if HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef WIN32
+#include <sys/stat.h>
+#endif
 
-char *marc_records[] = {
+#include <stdlib.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#define NO_MARC_RECORDS 24
+
+char *marc_records[NO_MARC_RECORDS] = {
 
   "\x30\x30\x33\x36\x36\x6E\x61\x6D\x20\x20\x32\x32\x30\x30\x31\x36"
   "\x39\x38\x61\x20\x34\x35\x30\x30\x30\x30\x31\x30\x30\x31\x33\x30"
@@ -1483,22 +1504,22 @@ char *marc_records[] = {
   "\x61\x6C\x20\x44\x69\x66\x66\x75\x73\x69\x6F\x6E\x20\x4E\x65\x74"
   "\x77\x6F\x72\x6B\x2C\x20\x4E\x44\x4E\x2E\x1E\x1D"
 ,
-  "\x30\x30\x37\x32\x35\x6E\x61\x6D\x30\x20\x32\x32\x30\x30\x32\x35"
-  "\x33\x20\x20\x20\x34\x35\x20\x20\x30\x30\x31\x30\x30\x31\x35\x30"
+  "\x30\x30\x37\x32\x39\x6E\x61\x6D\x30\x20\x32\x32\x30\x30\x32\x35"
+  "\x33\x20\x20\x20\x34\x35\x30\x20\x30\x30\x31\x30\x30\x31\x35\x30"
   "\x30\x30\x30\x30\x30\x30\x34\x30\x30\x31\x35\x30\x30\x30\x31\x35"
   "\x30\x30\x38\x30\x30\x32\x33\x30\x30\x30\x33\x30\x30\x32\x31\x30"
   "\x30\x33\x34\x30\x30\x30\x35\x33\x30\x34\x31\x30\x30\x31\x33\x30"
   "\x30\x30\x38\x37\x31\x30\x30\x30\x30\x31\x38\x30\x30\x31\x30\x30"
   "\x32\x34\x31\x30\x30\x31\x35\x30\x30\x31\x31\x38\x32\x34\x35\x30"
-  "\x31\x32\x33\x30\x30\x31\x33\x33\x32\x35\x30\x30\x30\x32\x34\x30"
-  "\x30\x32\x35\x36\x32\x36\x30\x30\x30\x33\x32\x30\x30\x32\x38\x30"
-  "\x33\x30\x30\x30\x30\x32\x37\x30\x30\x33\x31\x32\x35\x32\x30\x30"
-  "\x30\x33\x31\x30\x30\x33\x33\x39\x36\x35\x32\x30\x30\x31\x31\x30"
-  "\x30\x33\x37\x30\x30\x31\x30\x30\x30\x32\x31\x30\x30\x33\x38\x31"
-  "\x30\x39\x36\x30\x30\x31\x31\x30\x30\x34\x30\x32\x32\x35\x31\x30"
-  "\x30\x32\x34\x30\x30\x34\x31\x33\x32\x36\x31\x30\x30\x30\x39\x30"
-  "\x30\x34\x33\x37\x39\x37\x30\x30\x30\x31\x33\x30\x30\x34\x34\x36"
-  "\x39\x37\x30\x30\x30\x31\x32\x30\x30\x34\x35\x39\x1E\x30\x30\x1F"
+  "\x31\x32\x36\x30\x30\x31\x33\x33\x32\x35\x30\x30\x30\x32\x34\x30"
+  "\x30\x32\x35\x39\x32\x36\x30\x30\x30\x33\x33\x30\x30\x32\x38\x33"
+  "\x33\x30\x30\x30\x30\x32\x37\x30\x30\x33\x31\x36\x35\x32\x30\x30"
+  "\x30\x33\x31\x30\x30\x33\x34\x33\x36\x35\x32\x30\x30\x31\x31\x30"
+  "\x30\x33\x37\x34\x30\x31\x30\x30\x30\x32\x31\x30\x30\x33\x38\x35"
+  "\x30\x39\x36\x30\x30\x31\x31\x30\x30\x34\x30\x36\x32\x35\x31\x30"
+  "\x30\x32\x34\x30\x30\x34\x31\x37\x32\x36\x31\x30\x30\x30\x39\x30"
+  "\x30\x34\x34\x31\x39\x37\x30\x30\x30\x31\x33\x30\x30\x34\x35\x30"
+  "\x39\x37\x30\x30\x30\x31\x32\x30\x30\x34\x36\x33\x1E\x30\x30\x1F"
   "\x61\x44\x30\x30\x30\x30\x31\x35\x39\x33\x37\x1E\x30\x30\x1F\x73"
   "\x61\x1F\x74\x6D\x1F\x72\x6E\x1F\x75\x30\x1E\x30\x30\x1F\x61\x72"
   "\x31\x39\x38\x38\x31\x39\x38\x31\x1F\x62\x64\x6B\x1F\x6C\x64\x61"
@@ -1507,113 +1528,226 @@ char *marc_records[] = {
   "\x2C\x30\x30\x1E\x30\x30\x1F\x61\x64\x61\x6E\x1F\x63\x65\x6E\x67"
   "\x1E\x30\x30\x1F\x61\x41\x6E\x64\x65\x72\x73\x6F\x6E\x1F\x68\x42"
   "\x6F\x62\x1E\x30\x30\x1F\x61\x53\x74\x72\x65\x74\x63\x68\x69\x6E"
-  "\x67\x1E\x30\x30\x1F\x61\x53\x74\x72\xE6\x6B\xF8\x76\x65\x6C\x73"
-  "\x65\x72\x1F\x64\x42\x6F\x62\x20\x41\x6E\x64\x65\x72\x73\x6F\x6E"
-  "\x1F\x66\x69\x6C\x6C\x75\x73\x74\x72\x65\x72\x65\x74\x20\x61\x66"
-  "\x20\x4A\x65\x61\x6E\x20\x41\x6E\x64\x65\x72\x73\x6F\x6E\x1F\x66"
-  "\x64\x61\x6E\x73\x6B\x20\x75\x64\x67\x61\x76\x65\x20\x76\x65\x64"
-  "\x20\x4C\x69\x73\x20\x45\x6E\x67\x65\x6C\x1F\x66\x5B\x6F\x76\x65"
-  "\x72\x73\xE6\x74\x74\x65\x6C\x73\x65\x20\x76\x65\x64\x20\x4A\x65"
-  "\x73\x70\x65\x72\x20\x4C\x61\x6E\x67\x65\x72\x5D\x1E\x30\x30\x1F"
-  "\x61\x31\x2E\x20\x75\x64\x67\x61\x76\x65\x2C\x20\x34\x2E\x20\x6F"
-  "\x70\x6C\x61\x67\x1E\x30\x30\x1F\x61\x5B\x4B\x62\x68\x2E\x5D\x1F"
-  "\x62\x43\x6C\x61\x75\x73\x65\x6E\x20\x62\xF8\x67\x65\x72\x1F\x63"
-  "\x31\x39\x38\x38\x1E\x30\x30\x1F\x61\x31\x39\x32\x20\x73\x69\x64"
-  "\x65\x72\x1F\x62\x69\x6C\x6C\x2E\x1F\x63\x32\x36\x20\x63\x6D\x1E"
-  "\x30\x30\x1F\x61\x54\x69\x64\x6C\x69\x67\x65\x72\x65\x3A\x20\x31"
-  "\x2E\x20\x75\x64\x67\x61\x76\x65\x2E\x20\x31\x39\x38\x31\x1E\x30"
-  "\x30\x1F\x61\x37\x39\x2E\x36\x30\x31\x1E\x30\x30\x1F\x61\x38\x37"
-  "\x30\x39\x37\x30\x1F\x62\x30\x35\x36\x37\x35\x30\x33\x30\x1E\x30"
-  "\x30\x1F\x7A\x38\x37\x30\x39\x37\x30\x1E\x30\x30\x1F\x61\x31\x2E"
-  "\x20\x75\x64\x67\x61\x76\x65\x2C\x20\x34\x2E\x20\x6F\x70\x6C\x61"
-  "\x67\x1E\x30\x30\x1F\x63\x31\x39\x38\x38\x1E\x30\x30\x1F\x62\x30"
-  "\x35\x36\x37\x35\x30\x33\x30\x1E\x30\x30\x1F\x63\x44\x42\x46\x38"
-  "\x38\x34\x32\x1E\x1D"
+  "\x67\x1E\x30\x30\x1F\x61\x53\x74\x72\xC3\xA6\x6B\xC3\xB8\x76\x65"
+  "\x6C\x73\x65\x72\x1F\x64\x42\x6F\x62\x20\x41\x6E\x64\x65\x72\x73"
+  "\x6F\x6E\x1F\x66\x69\x6C\x6C\x75\x73\x74\x72\x65\x72\x65\x74\x20"
+  "\x61\x66\x20\x4A\x65\x61\x6E\x20\x41\x6E\x64\x65\x72\x73\x6F\x6E"
+  "\x1F\x66\x64\x61\x6E\x73\x6B\x20\x75\x64\x67\x61\x76\x65\x20\x76"
+  "\x65\x64\x20\x4C\x69\x73\x20\x45\x6E\x67\x65\x6C\x1F\x66\x5B\x6F"
+  "\x76\x65\x72\x73\xC3\xA6\x74\x74\x65\x6C\x73\x65\x20\x76\x65\x64"
+  "\x20\x4A\x65\x73\x70\x65\x72\x20\x4C\x61\x6E\x67\x65\x72\x5D\x1E"
+  "\x30\x30\x1F\x61\x31\x2E\x20\x75\x64\x67\x61\x76\x65\x2C\x20\x34"
+  "\x2E\x20\x6F\x70\x6C\x61\x67\x1E\x30\x30\x1F\x61\x5B\x4B\x62\x68"
+  "\x2E\x5D\x1F\x62\x43\x6C\x61\x75\x73\x65\x6E\x20\x62\xC3\xB8\x67"
+  "\x65\x72\x1F\x63\x31\x39\x38\x38\x1E\x30\x30\x1F\x61\x31\x39\x32"
+  "\x20\x73\x69\x64\x65\x72\x1F\x62\x69\x6C\x6C\x2E\x1F\x63\x32\x36"
+  "\x20\x63\x6D\x1E\x30\x30\x1F\x61\x54\x69\x64\x6C\x69\x67\x65\x72"
+  "\x65\x3A\x20\x31\x2E\x20\x75\x64\x67\x61\x76\x65\x2E\x20\x31\x39"
+  "\x38\x31\x1E\x30\x30\x1F\x61\x37\x39\x2E\x36\x30\x31\x1E\x30\x30"
+  "\x1F\x61\x38\x37\x30\x39\x37\x30\x1F\x62\x30\x35\x36\x37\x35\x30"
+  "\x33\x30\x1E\x30\x30\x1F\x7A\x38\x37\x30\x39\x37\x30\x1E\x30\x30"
+  "\x1F\x61\x31\x2E\x20\x75\x64\x67\x61\x76\x65\x2C\x20\x34\x2E\x20"
+  "\x6F\x70\x6C\x61\x67\x1E\x30\x30\x1F\x63\x31\x39\x38\x38\x1E\x30"
+  "\x30\x1F\x62\x30\x35\x36\x37\x35\x30\x33\x30\x1E\x30\x30\x1F\x63"
+  "\x44\x42\x46\x38\x38\x34\x32\x1E\x1D"
 };
 
-static int atoin (const char *buf, int n)
+static char *marc_record0 =
+  "00366nam  220016"
+  "98a 450000100130"
+  "0000003000400013"
+  "0050017000170080"
+  "0410003401000170"
+  "0179040001300075"
+  "0500012000881000"
+  "0170010024500300"
+  "0117260001200147"
+  "2630009001593000"
+  "01100168" "\x1E" "   1122"
+  "4466 " "\x1E" "DLC" "\x1E" "000000"
+  "00000000.0" "\x1E" "91071"
+  "0c19910701nju   "
+  "        00010 en"
+  "g  " "\x1E" "  " "\x1F" "aDLC" "\x1F" "cDLC"
+  "" "\x1E" "00" "\x1F" "a123-xyz" "\x1E" "10" "\x1F" ""
+  "aJack Collins" "\x1E" "10"
+  "" "\x1F" "aHow to program"
+  " a computer" "\x1E" "1 " "\x1F" "a"
+  "Penguin" "\x1E" "  " "\x1F" "a8710"
+  "" "\x1E" "  " "\x1F" "ap. cm." "\x1E" "  " "\x1F" "a"
+  "   11224466 " "\x1E" "" "\x1D" ""
+;
+
+/* read MARC record from offset 'num' */
+char *dummy_marc_record(int num, ODR odr)
 {
-    int val = 0;
-    while (--n >= 0)
+    if (num < 1)
+        return 0;
+    if (num >= NO_MARC_RECORDS)
     {
-        if (isdigit(*buf))
-            val = val*10 + (*buf - '0');
-        buf++;
+        char *p = odr_strdup(odr, marc_record0);
+        sprintf(p + 279, "%-5d", num);
+        p[284] = ' ';
+        return p;
     }
-    return val;
-}
-
-/* read one MARC record from a file */
-char *marc_read(FILE *inf, ODR odr)
-{
-    char length_str[5];
-    size_t size;
-    char *buf;
-
-    if (fread (length_str, 1, 5, inf) != 5)
-        return NULL;
-    size = atoin (length_str, 5);
-    if (size <= 6)
-        return NULL;
-    if (!(buf = (char*) odr_malloc (odr, size+1)))
-        return NULL;
-    if (fread (buf+5, 1, size-5, inf) != (size-5))
+    else
     {
-        xfree (buf);
-        return NULL;
+        return marc_records[(num-1) % NO_MARC_RECORDS];
     }
-    memcpy (buf, length_str, 5);
-    buf[size] = '\0';
-    return buf;
 }
 
-/* read MARC record from offset 'num' */
-char *dummy_marc_record (int num, ODR odr)
+#define PZ_CBEGIN "<pz:cluster xmlns:pz=\"http://www.indexdata.com/pazpar2/1.0\">\n"
+#define PZ_CEND "</pz:cluster>\n"
+#define PZ_BEGIN "<record xmlns=\"http://www.indexdata.com/pazpar2/1.0\">\n"
+#define PZ_END "</record>\n"
+#define PZ_METADATA(x, y) " <metadata type=\"" #x "\">" y "</metadata>\n"
+
+static char *dummy_pz2_record(int num, ODR odr)
 {
-    FILE *inf;
-    char *buf = 0;
+    const char *rec[] = {
+        PZ_CBEGIN
+        PZ_BEGIN
+        PZ_METADATA(author,"Jack Collins")
+        PZ_METADATA(medium, "book")
+        PZ_METADATA(date, "1995")
+        PZ_METADATA(title, "How to program a computer vol1")
+        PZ_END
+        PZ_BEGIN
+        PZ_METADATA(author,"Jack Collins")
+        PZ_METADATA(medium, "book")
+        PZ_METADATA(date, "1995")
+        PZ_METADATA(title, "How to program a computer vol2")
+        PZ_END
+        PZ_CEND
+        ,
+        PZ_CBEGIN
+        PZ_BEGIN
+        PZ_METADATA(author,"Jack Collins")
+        PZ_METADATA(medium, "book")
+        PZ_METADATA(date, "1995")
+        PZ_METADATA(title, "How to program a computer vol3")
+        PZ_END
+        PZ_BEGIN
+        PZ_METADATA(author,"Jack Collins")
+        PZ_METADATA(medium, "book")
+        PZ_METADATA(date, "1995")
+        PZ_METADATA(title, "How to program a computer vol2")
+        PZ_END
+        PZ_CEND
+        ,
+        PZ_BEGIN
+        PZ_METADATA(author,"Jack Collins")
+        PZ_METADATA(medium, "book")
+        PZ_METADATA(date, "1995")
+        PZ_METADATA(title, "How to program a computer vol1")
+        PZ_END
+        ,
+        /* identical to first */
+        PZ_CBEGIN
+        PZ_BEGIN
+        PZ_METADATA(author,"Jack Collins")
+        PZ_METADATA(medium, "book")
+        PZ_METADATA(date, "1995")
+        PZ_METADATA(title, "How to program a computer vol1")
+        PZ_END
+        PZ_BEGIN
+        PZ_METADATA(author,"Jack Collins")
+        PZ_METADATA(medium, "book")
+        PZ_METADATA(date, "1995")
+        PZ_METADATA(title, "How to program a computer vol4")
+        PZ_END
+        PZ_CEND
+    };
+    if (num > 0 && num <= sizeof(rec)/sizeof(*rec))
+        return odr_strdup(odr, rec[num - 1]);
+    return 0;
+}
 
-    if (num == 98) 
-    {   /* this will generate a very bad MARC record (testing only) */
-        buf = (char*) odr_malloc(odr, 2101);
-        memset(buf, '7', 2100);
-        buf[2100] = '\0';
+/* read MARC record and convert to XML */
+char *dummy_xml_record(int num, ODR odr, const char *esn)
+{
+    if (esn && !strcmp(esn, "pz2"))
+    {
+        return dummy_pz2_record(num, odr);
     }
-    inf = fopen ("dummy-records", "r");
-    if (!inf) 
-    { /* file not there. Get them from fixed array */
-        if (num < 1 || num > 24)
-            return 0;
-        return marc_records[num-1];
+    else if (!esn || !strcmp(esn, "marcxml") || !strcmp(esn, "OP"))
+    {
+        /* MARCXML and OPACXML */
+        char *rec = dummy_marc_record(num, odr);
+        if (rec)
+        {
+            WRBUF w = wrbuf_alloc();
+            yaz_marc_t mt = yaz_marc_create();
+            yaz_marc_xml(mt, YAZ_MARC_MARCXML);
+            if (esn && !strcmp(esn, "OP"))
+            {
+                /* generate OPACXML (OPAC in XML) */
+                Z_OPACRecord *opac = dummy_opac(num, odr, rec);
+                yaz_opac_decode_wrbuf(mt, opac, w);
+            }
+            else
+            {
+                /* generate MARCXML */
+                yaz_marc_decode_wrbuf(mt, rec, -1, w);
+            }
+            rec = odr_strdup(odr, wrbuf_cstr(w));
+            yaz_marc_destroy(mt);
+            wrbuf_destroy(w);
+            return rec;
+        }
     }
-    /* OK, try to get proper MARC records from the file */
-    while (--num >= 0)
+    else
     {
-        buf = marc_read (inf, odr);
-        if (!buf)
-            break;
+        char *buf = 0;
+        const char *e = getenv("YAZ_ZTEST_XML_FETCH");
+        if (e)
+        {
+            WRBUF w = wrbuf_alloc();
+            struct stat sbuf;
+            FILE *file = 0;
+
+            wrbuf_printf(w, "%s%s.%d.xml", e, esn, num);
+            if (stat(wrbuf_cstr(w), &sbuf) == 0 &&
+                (file = fopen(wrbuf_cstr(w), "rb")))
+            {
+                buf = odr_malloc(odr, 1 + sbuf.st_size);
+                fread(buf, 1, sbuf.st_size, file);
+                buf[sbuf.st_size] = '\0';
+            }
+            if (file)
+                fclose(file);
+        }
+        return buf;
     }
-    fclose(inf);
-    return buf;
+    return 0;
 }
 
-/* read MARC record and convert to XML */
-char *dummy_xml_record (int num, ODR odr)
+char *dummy_json_record(int num, ODR odr, const char *esn)
 {
-    WRBUF wr = wrbuf_alloc ();
-    char *rec = dummy_marc_record (num, odr);
-    int len;
-    if (!rec)
-        return 0;
-
-    len = yaz_marc_decode (rec, wr, 0, -1, 1);
-    if (len > 1)
+    if (!esn || !strcmp(esn, "marcinjson"))
     {
-        len = wrbuf_len(wr);
-        rec = odr_malloc (odr, len+1);
-        memcpy (rec, wrbuf_buf(wr), len+1);
-        rec[len] = 0;
+        char *rec = dummy_marc_record(num, odr);
+        if (rec)
+        {
+            WRBUF w = wrbuf_alloc();
+            yaz_marc_t mt = yaz_marc_create();
+            yaz_marc_xml(mt, YAZ_MARC_JSON);
+            yaz_marc_decode_wrbuf(mt, rec, -1, w);
+            rec = odr_strdup(odr, wrbuf_cstr(w));
+            yaz_marc_destroy(mt);
+            wrbuf_destroy(w);
+            return rec;
+        }
     }
-    wrbuf_free (wr, 1);
-    return rec;
+    return 0;
 }
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * c-file-style: "Stroustrup"
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
+