Remove the oid_name_to_dotstring() function, which is now in oid.c
[yaz-moved-to-github.git] / zutil / zoom-c.c
index b2bfeea..d67461a 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (c) 2000-2003, Index Data
  * See the file LICENSE for details.
  *
- * $Id: zoom-c.c,v 1.33 2003-04-29 21:20:34 adam Exp $
+ * $Id: zoom-c.c,v 1.38 2003-06-03 13:59:28 adam Exp $
  *
  * ZOOM layer for C, connections, result sets, queries.
  */
@@ -68,7 +68,10 @@ static ZOOM_Event ZOOM_connection_get_event(ZOOM_connection c)
 {
     ZOOM_Event event = c->m_queue_front;
     if (!event)
+    {
+        c->last_event = ZOOM_EVENT_NONE;
        return 0;
+    }
     assert (c->m_queue_back);
     c->m_queue_front = event->prev;
     if (c->m_queue_front)
@@ -505,6 +508,7 @@ ZOOM_resultset ZOOM_resultset_create ()
     r->setname = 0;
     r->schema = 0;
     r->count = 0;
+    r->step = 0;
     r->record_cache = 0;
     r->r_sort_spec = 0;
     r->query = 0;
@@ -540,6 +544,7 @@ ZOOM_connection_search(ZOOM_connection c, ZOOM_query q)
 
     r->start = ZOOM_options_get_int(r->options, "start", 0);
     r->count = ZOOM_options_get_int(r->options, "count", 0);
+    r->step = ZOOM_options_get_int(r->options, "step", 0);
     r->piggyback = ZOOM_options_get_bool (r->options, "piggyback", 1);
     cp = ZOOM_options_get (r->options, "setname");
     if (cp)
@@ -594,8 +599,12 @@ ZOOM_resultset_destroy(ZOOM_resultset r)
         ZOOM_record_cache rc;
 
         for (rc = r->record_cache; rc; rc = rc->next)
+       {
             if (rc->rec.wrbuf_marc)
                 wrbuf_free (rc->rec.wrbuf_marc, 1);
+            if (rc->rec.wrbuf_iconv)
+                wrbuf_free (rc->rec.wrbuf_iconv, 1);
+       }
        if (r->connection)
        {
            /* remove ourselves from the resultsets in connection */
@@ -1114,7 +1123,8 @@ static zoom_ret ZOOM_connection_srw_send_search(ZOOM_connection c)
         return zoom_complete;
     }
     sr->u.request->startRecord = odr_intdup (c->odr_out, resultset->start + 1);
-    sr->u.request->maximumRecords = odr_intdup (c->odr_out, resultset->count);
+    sr->u.request->maximumRecords = odr_intdup (
+        c->odr_out, resultset->step>0 ? resultset->step : resultset->count);
     sr->u.request->recordSchema = resultset->schema;
 
     recordPacking = ZOOM_resultset_option_get (resultset, "recordPacking");
@@ -1188,8 +1198,7 @@ static zoom_ret ZOOM_connection_send_search (ZOOM_connection c)
        /* Regular piggyback - do it unless we're going to do sort */
        *search_req->largeSetLowerBound = 2000000000;
        *search_req->smallSetUpperBound = 0;
-       *search_req->mediumSetPresentNumber = r->count;
-       smallSetElementSetName = 0;
+       *search_req->mediumSetPresentNumber = r->step>0 ? r->step : r->count;
     }
     else
     {
@@ -1294,6 +1303,7 @@ ZOOM_record_clone (ZOOM_record srec)
     nrec = (ZOOM_record) xmalloc (sizeof(*nrec));
     nrec->odr = odr_createmem(ODR_DECODE);
     nrec->wrbuf_marc = 0;
+    nrec->wrbuf_iconv = 0;
     odr_setbuf (nrec->odr, buf, size, 0);
     z_NamePlusRecord (nrec->odr, &nrec->npr, 0, 0);
     
@@ -1331,9 +1341,78 @@ ZOOM_record_destroy (ZOOM_record rec)
     xfree (rec);
 }
 
+static const char *record_iconv_return(ZOOM_record rec, int *len,
+                                      const char *buf, int sz,
+                                      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, ',');
+       int 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)))
+    {
+       char outbuf[12];
+       size_t inbytesleft = sz;
+       const char *inp = buf;
+       
+       if (!rec->wrbuf_iconv)
+           rec->wrbuf_iconv = wrbuf_alloc();
+
+       wrbuf_rewind(rec->wrbuf_iconv);
+
+       while (inbytesleft)
+       {
+           size_t outbytesleft = sizeof(outbuf);
+           char *outp = outbuf;
+           size_t r = yaz_iconv (cd, (char**) &inp,
+                                 &inbytesleft, 
+                                 &outp, &outbytesleft);
+           if (r == (size_t) (-1))
+           {
+               int e = yaz_iconv_error(cd);
+               if (e != YAZ_ICONV_E2BIG)
+                   break;
+           }
+           wrbuf_write(rec->wrbuf_iconv, outbuf, outp - outbuf);
+       }
+       wrbuf_puts(rec->wrbuf_iconv, "");
+       buf = wrbuf_buf(rec->wrbuf_iconv);
+       sz = wrbuf_len(rec->wrbuf_iconv);
+       yaz_iconv_close(cd);
+    }
+    if (len)
+       *len = sz;
+    return buf;
+}
+
 ZOOM_API(const char *)
-ZOOM_record_get (ZOOM_record rec, const char *type, int *len)
+ZOOM_record_get (ZOOM_record rec, const char *type_spec, int *len)
 {
+    char type[40];
+    char charset[40];
+    const char *cp;
+    int i;
     Z_NamePlusRecord *npr;
     
     if (len)
@@ -1344,6 +1423,34 @@ ZOOM_record_get (ZOOM_record rec, const char *type, int *len)
     npr = rec->npr;
     if (!npr)
        return 0;
+
+    cp = type_spec;
+    for (i = 0; cp[i] && i < sizeof(type)-1; i++)
+    {
+       if (cp[i] == ';' || cp[i] == ' ')
+           break;
+       type[i] = cp[i];
+    }
+    type[i] = '\0';
+    charset[0] = '\0';
+    if (type_spec[i] == ';')
+    {
+       i++;
+       while (type_spec[i] == ' ')
+           i++;
+       if (!strncmp(type_spec+i, "charset=", 8))
+       {
+           cp = type_spec+i+8;
+           for (i = 0; cp[i] && i < sizeof(charset)-1; i++)
+           {
+               if (cp[i] == ';' || cp[i] == ' ')
+                   break;
+               charset[i] = cp[i];
+           }
+           charset[i] = '\0';
+       }
+    }  
+
     if (!strcmp (type, "database"))
     {
        if (len)
@@ -1373,10 +1480,9 @@ ZOOM_record_get (ZOOM_record rec, const char *type, int *len)
         oident *ent = oid_getentbyoid(r->direct_reference);
         
         if (r->which == Z_External_sutrs)
-        {
-            if (len) *len = r->u.sutrs->len;
-            return (const char *) r->u.sutrs->buf;
-        }
+           return record_iconv_return(rec, len,
+                                      r->u.sutrs->buf, r->u.sutrs->len,
+                                      charset);
         else if (r->which == Z_External_octet)
         {
             yaz_marc_t mt;
@@ -1400,16 +1506,18 @@ ZOOM_record_get (ZOOM_record rec, const char *type, int *len)
                         r->u.octet_aligned->len,
                         rec->wrbuf_marc) > 0)
                 {
-                    if (len)
-                        *len = wrbuf_len(rec->wrbuf_marc);
                     yaz_marc_destroy(mt);
-                    return wrbuf_buf(rec->wrbuf_marc);
+                   return record_iconv_return(rec, len,
+                                              wrbuf_buf(rec->wrbuf_marc),
+                                              wrbuf_len(rec->wrbuf_marc),
+                                              charset);
                 }
                 yaz_marc_destroy(mt);
             }
-            if (len) 
-                *len = r->u.octet_aligned->len;
-            return (const char *) r->u.octet_aligned->buf;
+           return record_iconv_return(rec, len,
+                                      (const char *) r->u.octet_aligned->buf,
+                                      r->u.octet_aligned->len,
+                                      charset);
         }
         else if (r->which == Z_External_grs1)
         {
@@ -1417,9 +1525,10 @@ ZOOM_record_get (ZOOM_record rec, const char *type, int *len)
                 rec->wrbuf_marc = wrbuf_alloc();
             wrbuf_rewind (rec->wrbuf_marc);
             yaz_display_grs1(rec->wrbuf_marc, r->u.grs1, 0);
-            if (len) 
-                *len = wrbuf_len(rec->wrbuf_marc);
-            return wrbuf_buf(rec->wrbuf_marc);
+           return record_iconv_return(rec, len,
+                                      wrbuf_buf(rec->wrbuf_marc),
+                                      wrbuf_len(rec->wrbuf_marc),
+                                      charset);
         }
        return 0;
     }
@@ -1430,10 +1539,10 @@ ZOOM_record_get (ZOOM_record rec, const char *type, int *len)
         oident *ent = oid_getentbyoid(r->direct_reference);
         
         if (r->which == Z_External_sutrs)
-        {
-            if (len) *len = r->u.sutrs->len;
-            return (const char *) r->u.sutrs->buf;
-        }
+           return record_iconv_return(rec, len,
+                                      (const char *) r->u.sutrs->buf,
+                                      r->u.sutrs->len,
+                                      charset);
         else if (r->which == Z_External_octet)
         {
             yaz_marc_t mt;
@@ -1462,15 +1571,18 @@ ZOOM_record_get (ZOOM_record rec, const char *type, int *len)
                         r->u.octet_aligned->len,
                         rec->wrbuf_marc) > 0)
                 {
-                    if (len) 
-                        *len = wrbuf_len(rec->wrbuf_marc);
                     yaz_marc_destroy(mt);
-                    return wrbuf_buf(rec->wrbuf_marc);
+                   return record_iconv_return(rec, len,
+                                              wrbuf_buf(rec->wrbuf_marc),
+                                              wrbuf_len(rec->wrbuf_marc),
+                                              charset);
                 }
                 yaz_marc_destroy(mt);
             }
-            if (len) *len = r->u.octet_aligned->len;
-            return (const char *) r->u.octet_aligned->buf;
+           return record_iconv_return(rec, len,
+                                      (const char *) r->u.octet_aligned->buf,
+                                      r->u.octet_aligned->len,
+                                      charset);
         }
         else if (r->which == Z_External_grs1)
         {
@@ -1558,6 +1670,7 @@ static void record_cache_add (ZOOM_resultset r, Z_NamePlusRecord *npr,
     rc->rec.npr = npr; 
     rc->rec.odr = 0;
     rc->rec.wrbuf_marc = 0;
+    rc->rec.wrbuf_iconv = 0;
     if (elementSetName)
        rc->elementSetName = odr_strdup (r->odr, elementSetName);
     else
@@ -1811,7 +1924,8 @@ static zoom_ret send_present (ZOOM_connection c)
     resultset->start += i;
     resultset->count -= i;
     *req->resultSetStartPoint = resultset->start + 1;
-    *req->numberOfRecordsRequested = resultset->count;
+    *req->numberOfRecordsRequested = resultset->step>0 ?
+        resultset->step : resultset->count;
     assert (*req->numberOfRecordsRequested > 0);
 
     if (syntax && *syntax)