-// $Id: master-header,v 1.11 2002-11-25 13:33:22 mike Exp $
+// $Id: master-header,v 1.12 2002-11-30 22:33:21 mike Exp $
//
// ZOOM C++ Binding.
// The ZOOM homepage is at http://zoom.z3950.org/
class YAZ_EXPORT resultSet {
* connection &owner;
* ZOOM_resultset rs;
+* friend class record; // for _getYazResultSet() & _getYazConnection()
+* ZOOM_resultset _getYazResultSet () const { return rs; }
+* ZOOM_connection _getYazConnection () const {
+* return owner._getYazConnection(); }
// resultSets are non-copyable.
resultSet (const resultSet &);
resultSet &operator= (const resultSet &);
};
class YAZ_EXPORT record {
-* const resultSet *owner;
+* const resultSet &owner;
* ZOOM_record r;
* friend class resultSet; // so it can use this constructor
-* record::record (const resultSet *rs, ZOOM_record rec):
-* owner (rs), r (rec) {}
public:
class syntax {
public:
enum value {
UNKNOWN, GRS1, SUTRS, USMARC, UKMARC, XML
};
- syntax (value rs) : i(rs) {};
+* private:
+* enum value val;
+* public:
+ syntax (value rs);
operator std::string () const;
bool operator== (const syntax &s) const;
bool operator== (value rs) const;
public:
systemException (); // Uses value of system `errno'
systemException (int code);
+* virtual std::string errmsg () const; // Why do I have to repeat this?
};
// bib1Exception::errcode() returns a code from the
// Bib-1 Diagnostic Set.
class YAZ_EXPORT bib1Exception: public exception {
-* const char *info;
+* const string &info;
public:
* ~bib1Exception ();
bib1Exception (int code, const std::string &addinfo);
+* virtual std::string errmsg () const; // Why do I have to repeat this?
std::string addinfo () const;
};
class YAZ_EXPORT queryException : public exception {
-* const char *q;
+* const string &q;
public:
* ~queryException ();
enum { PREFIX, CCL };
queryException (int qtype, const std::string &source);
+* virtual std::string errmsg () const; // Why do I have to repeat this?
std::string addinfo () const;
};
}
-// $Header: /home/cvsroot/yaz++/zoom/zclient.cpp,v 1.4 2002-10-09 09:07:10 mike Exp $
+// $Id: zclient.cpp,v 1.5 2002-11-30 22:33:21 mike Exp $
// Simple sample client
int main(int argc, char **argv)
{
if (argc != 5) {
- cerr << "Usage: " << argv[0] <<
- " <host> <port> <db> <@prefix-search>\n";
+ cerr << "Usage: " <<
+ argv[0] << " <host> <port> <dbname> <@prefix-search>\n";
return 1;
}
- const char *hostname = argv[1];
- const int port = atoi(argv[2]);
- const char *dbname = argv[3];
- const char *searchSpec = argv[4];
-
- ZOOM::connection *conn;
+ using namespace ZOOM;
try {
- conn = new ZOOM::connection(hostname, port);
- } catch(ZOOM::bib1Exception& err) {
- cerr << argv[0] << ": connect: bib1Exception " <<
+ connection conn(argv[1], atoi(argv[2]));
+ conn.option("databaseName", argv[3]);
+ conn.option("preferredRecordSyntax",
+ record::syntax(record::syntax::XML));
+ prefixQuery pq(argv[4]);
+ resultSet rs(conn, pq);
+
+ size_t n = rs.size();
+ cout << "found " << n << " records:\n";
+ for (size_t i = 0; i < n; i++) {
+ const record rec(rs, i);
+ cout << "=== record " << i+1 <<
+ " (record-syntax " << (string) rec.recsyn() << ")" <<
+ " ===\n" << rec.render();
+ }
+
+ } catch(bib1Exception& err) {
+ cerr << argv[0] << ": bib1Exception " <<
err.errmsg() << " (" << err.addinfo() << ")\n";
return 2;
- } catch(ZOOM::exception& err) {
- cerr << argv[0] << ": connect: exception " <<
- err.errmsg() << "\n";
- return 2;
- }
- conn->option("databaseName", dbname);
- ZOOM::prefixQuery pq(searchSpec);
- ZOOM::resultSet *rs;
- try {
- rs = new ZOOM::resultSet(*conn, pq);
- } catch(ZOOM::bib1Exception err) {
- //fprintf(stderr, "caught exception 0x%lx\n", (long) &err);
- cerr << argv[0] << ": search: " <<
- err.errmsg() << " (" << err.addinfo() << ")\n";
+ } catch(exception& err) {
+ cerr << argv[0] << ": exception " <<
+ err.errmsg() << "\n";
return 3;
}
- size_t n = rs->size();
- cout << "found " << n << " records:\n";
- for (size_t i = 0; i < n; i++) {
- const ZOOM::record *rec = rs->getRecord(i);
- cout << "=== record " << i+1 << " (recsyn " << rec->recsyn()
- << ") ===\n" << rec->render();
- }
-
return 0;
}
-// $Header: /home/cvsroot/yaz++/zoom/zconn.cpp,v 1.3 2002-10-09 09:07:10 mike Exp $
+// $Header: /home/cvsroot/yaz++/zoom/zconn.cpp,v 1.4 2002-11-30 22:33:21 mike Exp $
// Z39.50 Connection class
namespace ZOOM {
- connection::connection(const char *hostname, int portnum) {
- c = ZOOM_connection_new(hostname, portnum);
+ connection::connection(const string &hostname, int portnum) {
+ const char *line_printer_size_hostname = hostname.c_str();
+ //###cerr << "opening " << hostname << ":" << portnum << "\n";
+ c = ZOOM_connection_new(line_printer_size_hostname, portnum);
+ //###cerr << "opened, got " << c << "\n";
int errcode;
const char *errmsg; // unused: carries same info as `errcode'
const char *addinfo;
if ((errcode = ZOOM_connection_error(c, &errmsg, &addinfo)) != 0) {
+ //###cerr << "oops: no connect, errcode=" << errcode << "\n";
throw bib1Exception(errcode, addinfo);
}
}
- const char *connection::option(const char *key) const {
- return ZOOM_connection_option_get(c, key);
+ string connection::option(const string &key) const {
+ return ZOOM_connection_option_get(c, key.c_str());
}
- const char *connection::option(const char *key, const char *val) {
- // ### There may be memory-management issues here.
- const char *old = ZOOM_connection_option_get(c, key);
- ZOOM_connection_option_set(c, key, val);
- return old;
+ bool connection::option(const string &key, const string &val) {
+ // No way to tell whether ZOOM_connection_option_set() accepts key
+ ZOOM_connection_option_set(c, key.c_str(), val.c_str());
+ return true;
}
connection::~connection() {
-// $Header: /home/cvsroot/yaz++/zoom/zexcept.cpp,v 1.6 2002-11-12 22:43:56 mike Exp $
+// $Header: /home/cvsroot/yaz++/zoom/zexcept.cpp,v 1.7 2002-11-30 22:33:21 mike Exp $
// Z39.50 Exception classes
#include <errno.h>
#include <string.h> // for strerror(), strlen(), strcpy()
#include <stdio.h> // for sprintf()
-#include <yaz/diagbib1.h>
#include "zoom.h"
code = errcode;
}
+ exception::~exception() {
+ // Nothing to do, but G++ requires this to be explicit anyway
+ }
+
int exception::errcode() const {
return code;
}
- const char *exception::errmsg() const {
+ string exception::errmsg() const {
static char buf[40];
sprintf(buf, "error #%d", code);
return buf;
code = errno;
}
- const char *systemException::errmsg() const {
+ string systemException::errmsg() const {
return strerror(code);
}
- bib1Exception::bib1Exception(int errcode, const char *addinfo) :
- exception(errcode) {
- info = new char[strlen(addinfo)+1];
- strcpy((char*) info, addinfo);
- //fprintf(stderr, "made new bib1Exception 0x%lx (%d, 0x%lx=%s)\n",
- //(long) this, code, (long) info, info);
+ bib1Exception::bib1Exception(int errcode, const string &addinfo) :
+ exception(errcode), info(addinfo) {
+ cerr << "WARNING: made bib1Exception(" << errcode << "=" <<
+ ZOOM_diag_str(errcode) << ", '" << addinfo << "')\n";
}
-#if 0
- bib1Exception::bib1Exception(bib1Exception& src) :
- exception(src) {
- code = src.code;
- info = new char[strlen(src.info)+1];
- strcpy((char*) info, src.info);
- //fprintf(stderr, "copied bib1Exception 0x%lx to 0x%lx (%d, 0x%lx=%s)\n",
- //(long) &src, (long) this, code, (long) info, info);
- }
-#endif
-
bib1Exception::~bib1Exception() {
//fprintf(stderr, "deleting bib1Exception 0x%lx (%d, 0x%lx=%s)\n",
//(long) this, code, (long) info, info);
// ### Don't actually do the deletion for now. Exception
// reference semantics are too weird for me to grok so I'm
// doing The Wrong Thing in the knowledge that it will more
- // or less work -- it just leaks memory.
+ // or less work -- it just leaks memory. (Or does it?)
}
- const char *bib1Exception::errmsg() const {
- return diagbib1_str(code);
+ string bib1Exception::errmsg() const {
+ return ZOOM_diag_str(code);
}
- const char *bib1Exception::addinfo() const {
+ string bib1Exception::addinfo() const {
return info;
}
- queryException::queryException(int qtype, const char *source) :
- exception(qtype) {
- q = new char[strlen(source)+1];
- strcpy((char*) q, source);
- }
+ queryException::queryException(int qtype, const string &source) :
+ exception(qtype), q(source) {}
queryException::~queryException() {
//delete q; // ### see comment on bib1Exception destructor
}
- const char *queryException::errmsg() const {
+ string queryException::errmsg() const {
switch (code) {
case PREFIX: return "bad prefix search";
case CCL: return "bad CCL search";
return "bad search (unknown type)";
}
- const char *queryException::addinfo() const {
+ string queryException::addinfo() const {
return q;
}
}
-// $Header: /home/cvsroot/yaz++/zoom/zquery.cpp,v 1.3 2002-10-09 09:07:10 mike Exp $
+// $Header: /home/cvsroot/yaz++/zoom/zquery.cpp,v 1.4 2002-11-30 22:33:21 mike Exp $
// Z39.50 Query classes
- prefixQuery::prefixQuery(const char *pqn) {
+ prefixQuery::prefixQuery(const string &pqn) {
q = ZOOM_query_create();
- if (ZOOM_query_prefix(q, pqn) == -1) {
+ if (ZOOM_query_prefix(q, pqn.c_str()) == -1) {
ZOOM_query_destroy(q);
throw queryException(queryException::PREFIX, pqn);
}
- CCLQuery::CCLQuery(const char *ccl, void *qualset) {
+ CCLQuery::CCLQuery(const string &ccl, void *qualset) {
throw "Oops. No CCL support in ZOOM-C yet. Sorry.";
}
-// $Header: /home/cvsroot/yaz++/zoom/zrec.cpp,v 1.4 2002-10-09 09:07:10 mike Exp $
+// $Header: /home/cvsroot/yaz++/zoom/zrec.cpp,v 1.5 2002-11-30 22:33:21 mike Exp $
// Z39.50 Record class
namespace ZOOM {
- record::~record() {
- if (owner == 0) {
- // Must have been clone()d
- ZOOM_record_destroy(r);
+ record::syntax::syntax (value rs): val(rs) {}
+
+ record::syntax::operator string() const {
+ switch (val) {
+ case GRS1: return "grs1";
+ case SUTRS: return "sutrs";
+ case USMARC: return "usmarc";
+ case UKMARC: return "ukmarc";
+ case XML: return "xml";
+ default: break;
}
+ return "unknown";
+ }
+
+ bool record::syntax::operator==(const record::syntax &s) const {
+ return s.val == val;
}
- // ### Would this operation be better expressed as a copy constructor?
- record *record::clone() const {
- // It's tempting just to replace `r' with a clone, and return
- // `this', but probably more honest to allocate a new C++
- // record object.
+ bool record::syntax::operator==(record::syntax::value rs) const {
+ return rs == val;
+ }
- record *rec = new record(0, 0);
- if ((rec->r = ZOOM_record_clone(r)) == 0) {
- // Presumably an out-of-memory error
- throw systemException();
+ record::syntax::operator record::syntax::value() const {
+ return val;
+ }
+
+
+ record::record(resultSet &rs, size_t i): owner(rs) {
+ if ((r = ZOOM_resultset_record(rs._getYazResultSet(), i)) == 0) {
+ const char *errmsg; // unused: carries same info as `errcode'
+ const char *addinfo;
+ int errcode = ZOOM_connection_error(rs._getYazConnection(),
+ &errmsg, &addinfo);
+ throw bib1Exception(errcode, addinfo);
}
- return rec;
+ // Memory management is odd here. The ZOOM-C record we've
+ // just fetched (`r') is owned by the ZOOM-C result-set we
+ // fetched it from (`rs.rs'), so the underlying (ZOOM-C)
+ // record is _not_ destroyed when this object is destroyed:
+ // it's done when the underlying result-set is deleted.
+ }
+
+ record::~record() {
+ // Nothing to do -- see comment in constructor
}
// It's tempting to modify this method just to return either the
// These string constants are from yaz/util/oid.c
if (!yaz_matchstr(syn, "xml"))
- return XML;
+ return syntax::XML;
else if (!yaz_matchstr(syn, "GRS-1"))
- return GRS1;
+ return syntax::GRS1;
else if (!yaz_matchstr(syn, "SUTRS"))
- return SUTRS;
+ return syntax::SUTRS;
else if (!yaz_matchstr(syn, "USmarc"))
- return USMARC;
+ return syntax::USMARC;
else if (!yaz_matchstr(syn, "UKmarc"))
- return UKMARC;
+ return syntax::UKMARC;
else if (!yaz_matchstr(syn, "XML") ||
!yaz_matchstr(syn, "text-XML") ||
!yaz_matchstr(syn, "application-XML"))
- return XML;
+ return syntax::XML;
- return UNKNOWN;
+ return syntax::UNKNOWN;
}
- const char *record::render() const {
+ string record::render() const {
int len;
return ZOOM_record_get(r, "render", &len);
}
- const char *record::rawdata() const {
+ string record::rawdata() const {
int len;
return ZOOM_record_get(r, "raw", &len);
}
-// $Header: /home/cvsroot/yaz++/zoom/zrs.cpp,v 1.3 2002-10-09 09:07:10 mike Exp $
+// $Header: /home/cvsroot/yaz++/zoom/zrs.cpp,v 1.4 2002-11-30 22:33:21 mike Exp $
// Z39.50 Result Set class
ZOOM_resultset_destroy(rs);
}
- const char *resultSet::option(const char *key) const {
- return ZOOM_resultset_option_get(rs, key);
+ string resultSet::option(const string &key) const {
+ return ZOOM_resultset_option_get(rs, key.c_str());
}
- const char *resultSet::option(const char *key, const char *val) {
- // ### There may be memory-management issues here.
- const char *old = ZOOM_resultset_option_get(rs, key);
- ZOOM_resultset_option_set(rs, key, val);
- return old;
+ bool resultSet::option(const string &key, const string &val) {
+ ZOOM_resultset_option_set(rs, key.c_str(), val.c_str());
+ return true;
}
size_t resultSet::size() const {
return ZOOM_resultset_size(rs);
}
-
- const record *resultSet::getRecord(size_t i) const {
- ZOOM_record rec;
- if ((rec = ZOOM_resultset_record(rs, i)) == 0) {
- const char *errmsg; // unused: carries same info as `errcode'
- const char *addinfo;
- int errcode = ZOOM_connection_error(owner._getYazConnection(),
- &errmsg, &addinfo);
- throw bib1Exception(errcode, addinfo);
- }
-
- // Memory management is odd here. The ZOOM-C record we've
- // just fetched (`rec') is owned by the ZOOM-C result-set we
- // fetched it from (`rs'), so all we need to allocate is a
- // ZOOM-C++ wrapper for it, which is destroyed at the
- // appropriate time -- but the underlying (ZOOM-C) record is
- // _not_ destroyed at that time, because it's done when the
- // underlying result-set is deleted.
- return new record(this, rec);
- }
}