Expanded tabs in all source files. Added vim/emacs local variables
[yaz-moved-to-github.git] / src / odr.c
index acc7b19..8d4cff8 100644 (file)
--- a/src/odr.c
+++ b/src/odr.c
@@ -1,20 +1,31 @@
 /*
- * Copyright (c) 1995-2003, Index Data
+ * Copyright (C) 1995-2005, Index Data ApS
  * See the file LICENSE for details.
  *
- * $Id: odr.c,v 1.1 2003-10-27 12:21:33 adam Exp $
+ * $Id: odr.c,v 1.12 2005-06-25 15:46:04 adam Exp $
  *
  */
+
+/**
+ * \file odr.c
+ * \brief Implements fundamental ODR functionality
+ */
+
 #if HAVE_CONFIG_H
 #include <config.h>
 #endif
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <stdarg.h>
 
 #include <yaz/xmalloc.h>
+#include <yaz/log.h>
 #include "odr-priv.h"
 
+static int log_level=0;
+static int log_level_initialized=0;
+
 Odr_null *ODR_NULLVAL = (Odr_null *) "NULL";  /* the presence of a null value */
 
 Odr_null *odr_nullval (void)
@@ -68,11 +79,16 @@ int odr_geterrorx(ODR o, int *x)
     return o->error;
 }
 
-char *odr_getelement(ODR o)
+const char *odr_getelement(ODR o)
 {
     return o->op->element;
 }
 
+const char **odr_get_element_path(ODR o)
+{
+    return o->op->stack_names;
+}
+
 void odr_seterror(ODR o, int error, int id)
 {
     o->error = error;
@@ -89,9 +105,59 @@ void odr_setelement(ODR o, const char *element)
     }
 }
 
+void odr_FILE_write(ODR o, void *handle, int type,
+                    const char *buf, int len)
+{
+    int i;
+#if 0
+    if (type  == ODR_OCTETSTRING)
+    {
+        const char **stack_names = odr_get_element_path(o);
+        for (i = 0; stack_names[i]; i++)
+            fprintf((FILE*) handle, "[%s]", stack_names[i]);
+        fputs("\n", (FILE*) handle);
+    }
+#endif
+    for (i = 0; i<len; i++)
+    {
+        unsigned c = ((const unsigned char *) buf)[i];
+        if (i == 2000 && len > 3100)
+        {
+            fputs(" ..... ", (FILE*) handle);
+                i = len - 1000;
+        }
+        if (strchr("\r\n\f\t", c) || (c >= ' ' && c <= 126))
+            putc(c, (FILE*) handle);
+        else
+        {
+            char x[5];
+            sprintf(x, "\\X%02X", c);
+            fputs(x, (FILE*) handle);
+        }
+    }
+}
+
+void odr_FILE_close(void *handle)
+{
+    FILE *f = (FILE *) handle;
+    if (f && f != stderr && f != stdout)
+        fclose(f);
+}
+
 void odr_setprint(ODR o, FILE *file)
 {
-    o->print = file;
+    odr_set_stream(o, file, odr_FILE_write, odr_FILE_close);
+}
+
+void odr_set_stream(ODR o, void *handle,
+                    void (*stream_write)(ODR o, 
+                                         void *handle, int type,
+                                         const char *buf, int len),
+                    void (*stream_close)(void *handle))
+{
+    o->print = (FILE*) handle;
+    o->op->stream_write = stream_write;
+    o->op->stream_close = stream_close;
 }
 
 int odr_set_charset(ODR o, const char *to, const char *from)
@@ -108,31 +174,41 @@ int odr_set_charset(ODR o, const char *to, const char *from)
     return 0;
 }
 
-#include <yaz/log.h>
 
 ODR odr_createmem(int direction)
 {
-    ODR r;
+    ODR o;
+    if (!log_level_initialized)
+    {
+        log_level=yaz_log_module_level("odr");
+        log_level_initialized=1;
+    }
 
-    if (!(r = (ODR)xmalloc(sizeof(*r))))
+    if (!(o = (ODR)xmalloc(sizeof(*o))))
         return 0;
-    r->direction = direction;
-    r->print = stderr;
-    r->buf = 0;
-    r->size = r->pos = r->top = 0;
-    r->can_grow = 1;
-    r->mem = nmem_create();
-    r->enable_bias = 1;
-    r->op = (struct Odr_private *) xmalloc (sizeof(*r->op));
-    r->op->odr_ber_tag.lclass = -1;
-    r->op->iconv_handle = 0;
-    odr_reset(r);
-    yaz_log (LOG_DEBUG, "odr_createmem dir=%d o=%p", direction, r);
-    return r;
+    o->direction = direction;
+    o->buf = 0;
+    o->size = o->pos = o->top = 0;
+    o->can_grow = 1;
+    o->mem = nmem_create();
+    o->enable_bias = 1;
+    o->op = (struct Odr_private *) xmalloc (sizeof(*o->op));
+    o->op->odr_ber_tag.lclass = -1;
+    o->op->iconv_handle = 0;
+    odr_setprint(o, stderr);
+    odr_reset(o);
+    yaz_log (log_level, "odr_createmem dir=%d o=%p", direction, o);
+    return o;
 }
 
 void odr_reset(ODR o)
 {
+    if (!log_level_initialized)
+    {
+        log_level=yaz_log_module_level("odr");
+        log_level_initialized=1;
+    }
+
     odr_seterror(o, ONONE, 0);
     o->bp = o->buf;
     odr_seek(o, ODR_S_SET, 0);
@@ -146,7 +222,7 @@ void odr_reset(ODR o)
     o->lenlen = 1;
     if (o->op->iconv_handle != 0)
         yaz_iconv(o->op->iconv_handle, 0, 0, 0, 0);
-    yaz_log (LOG_DEBUG, "odr_reset o=%p", o);
+    yaz_log (log_level, "odr_reset o=%p", o);
 }
     
 void odr_destroy(ODR o)
@@ -154,17 +230,18 @@ void odr_destroy(ODR o)
     nmem_destroy(o->mem);
     if (o->buf && o->can_grow)
        xfree(o->buf);
-    if (o->print && o->print != stderr)
-        fclose(o->print);
+    if (o->op->stream_close)
+        o->op->stream_close(o->print);
     if (o->op->iconv_handle != 0)
         yaz_iconv_close (o->op->iconv_handle);
     xfree(o->op);
     xfree(o);
-    yaz_log (LOG_DEBUG, "odr_destroy o=%p", o);
+    yaz_log (log_level, "odr_destroy o=%p", o);
 }
 
 void odr_setbuf(ODR o, char *buf, int len, int can_grow)
 {
+    odr_seterror(o, ONONE, 0);
     o->bp = (unsigned char *) buf;
 
     o->buf = (unsigned char *) buf;
@@ -181,3 +258,29 @@ char *odr_getbuf(ODR o, int *len, int *size)
     return (char*) o->buf;
 }
 
+void odr_printf(ODR o, const char *fmt, ...)
+{
+    va_list ap;
+    char buf[4096];
+
+    va_start(ap, fmt);
+#ifdef WIN32
+    _vsnprintf(buf, sizeof(buf)-1, fmt, ap);
+#else
+#if HAVE_VSNPRINTF
+    vsnprintf(buf, sizeof(buf), fmt, ap);
+#else
+    vsprintf(buf, fmt, ap);
+#endif
+#endif
+    o->op->stream_write(o, o->print, ODR_VISIBLESTRING, buf, strlen(buf));
+    va_end(ap);
+}
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
+