/*---------------------------------------------------------------------------*
 |              pCOS - PDF Information Retrieval Tool
 +---------------------------------------------------------------------------+
 |           Copyright (c) 2005 PDFlib GmbH. All rights reserved.            |
 +---------------------------------------------------------------------------+
 |          Proprietary source code -- do not redistribute!                  |
 *---------------------------------------------------------------------------*/

// $Id: pcos.cpp,v 1.10 2007/09/07 13:28:58 stm Exp $
//
// Implementation of C++ wrapper for pCOS
//
//

#include "pcos.hpp"

#define CHAR(s) (s).c_str()
#define LEN(s)  ((int) (s).size())

pCOS::Exception::Exception(string errmsg, int errnum, string apiname,
        void *opaque)
: m_errmsg(errmsg),
  m_errnum(errnum),
  m_apiname(apiname),
  m_opaque(opaque)
{ }

string pCOS::Exception::get_errmsg() { return m_errmsg; }
int pCOS::Exception::get_errnum() { return m_errnum; }
string pCOS::Exception::get_apiname() { return m_apiname; }
const void * pCOS::Exception::get_opaque() { return m_opaque; }

#define PCOSCPP_TRY     pCOS_TRY(pcos)
#define PCOSCPP_CATCH  \
pCOS_CATCH(pcos) {\
    throw Exception(pCOS_get_errmsg(pcos), pCOS_get_errnum(pcos),\
                            pCOS_get_apiname(pcos), pCOS_get_opaque(pcos));\
}

pCOS::pCOS(pcos_error_fp errorhandler, void *opaque) throw(pCOS::Exception)
{

    pcos = pCOS_new2(errorhandler, opaque);

    if (pcos == (pCOS_cpp *)0) {
        throw Exception("No memory for pCOS object", 0, "pcoslib.cpp", opaque);
    }

    PCOSCPP_TRY
    {
        pCOS_set_option(pcos, "binding={C++} objorient");
    }
    PCOSCPP_CATCH;
}

pCOS::~pCOS() throw()
{
    pCOS_delete(pcos);
}


void
pCOS::close_document(int doc) throw(pCOS::Exception)
{
    PCOSCPP_TRY
        pCOS_close_document(pcos, doc);
    PCOSCPP_CATCH;
}

string
pCOS::get_apiname() throw(pCOS::Exception)
{
    const char *retval = NULL;

    PCOSCPP_TRY
        retval = pCOS_get_apiname(pcos);
    PCOSCPP_CATCH;

    if (retval)
        return retval;
    else
        return "";
}

string
pCOS::get_errmsg() throw(pCOS::Exception)
{
    const char *retval = NULL;

    PCOSCPP_TRY
        retval = pCOS_get_errmsg(pcos);
    PCOSCPP_CATCH;

    if (retval)
        return retval;
    else
        return "";
}

int
pCOS::get_errnum() throw(pCOS::Exception)
{
    int retval = 0;

    PCOSCPP_TRY
        retval = pCOS_get_errnum(pcos);
    PCOSCPP_CATCH;

    return retval;

}

void *
pCOS::get_opaque() throw(pCOS::Exception)
{
    void *retval = NULL;

    PCOSCPP_TRY
        retval = pCOS_get_opaque(pcos);
    PCOSCPP_CATCH;

    return retval;
}

int
pCOS::open_document(string filename, string optlist)
    throw(pCOS::Exception)
{
    int retval = 0;

    PCOSCPP_TRY
        retval = pCOS_open_document(pcos, CHAR(filename), 0, CHAR(optlist));
    PCOSCPP_CATCH;

    return retval;
}

int
pCOS::open_document_callback(void *opaque, size_t filesize,
    size_t (*readproc)(void *opaque, void *buffer, size_t size),
    int (*seekproc)(void *opaque, long offset), string optlist)
    throw(pCOS::Exception)
{
    int retval = 0;

    PCOSCPP_TRY
        retval = pCOS_open_document_callback(pcos, opaque, filesize,
                readproc, seekproc, CHAR(optlist));
    PCOSCPP_CATCH;
    
    return retval;
}

int
pCOS::open_document_mem(const void *data, size_t size, string optlist)
{

    int retval = -1;
    
    PCOSCPP_TRY
        retval = pCOS_open_document_mem(pcos, data, size, CHAR(optlist));
    PCOSCPP_CATCH;
    
    return retval;
}

double
pCOS::get_number(int doc, string path) throw(pCOS::Exception)
{
    double retval = 0;

    PCOSCPP_TRY
        retval = pCOS_get_number(pcos, doc, "%s", CHAR(path));
    PCOSCPP_CATCH;

    return retval;
}

string
pCOS::get_string(int doc, string path) throw(pCOS::Exception)
{
    const char *cretval = NULL;
    string retval = "";

    PCOSCPP_TRY
        cretval = pCOS_get_string(pcos, doc, "%s", CHAR(path));
        if (cretval)
            retval = string(cretval, strlen(cretval));
    PCOSCPP_CATCH;

    return retval;
}

const unsigned char *
pCOS::get_stream(int doc, int *length, string optlist, string path)
    throw(pCOS::Exception)
{
    const unsigned char *retval = NULL;

    PCOSCPP_TRY
        retval = pCOS_get_stream(pcos, doc, length, CHAR(optlist),
                "%s", CHAR(path));
    PCOSCPP_CATCH;

    return retval;
}

void
pCOS::set_option(string optlist) throw(pCOS::Exception)
{
    PCOSCPP_TRY
        pCOS_set_option(pcos, CHAR(optlist));
    PCOSCPP_CATCH;
}

string
pCOS::utf8_to_utf16(string utf8string, string ordering) throw(pCOS::Exception)
{
    int size;
    const char *buf;
    string retval = "";

    PCOSCPP_TRY
        buf = pCOS_utf8_to_utf16(pcos, CHAR(utf8string), CHAR(ordering), &size);
        if (buf)
            retval = string(buf, size);
    PCOSCPP_CATCH;

    return retval;
}

std::string
pCOS::utf16_to_utf8(std::string utf16string) throw(pCOS::Exception)
{
    const char *retval = NULL;

    PCOSCPP_TRY
        retval = pCOS_utf16_to_utf8(pcos, CHAR(utf16string),
            (int) LEN(utf16string), NULL);
    PCOSCPP_CATCH;

    if (retval)
        return retval;
    else
        return "";
}
