Net-Z3950

 view release on metacpan or  search on metacpan

yazwrap/send.c  view on Meta::CPAN

    *req->numberOfRecordsRequested = numberOfRecordsRequested;
    req->num_ranges = 0;	/* ### would be nice to support this */
    req->recordComposition = &rcomp;
    rcomp.which = Z_RecordComp_simple;	/* ### espec suppport would be nice */
    rcomp.u.simple = &esname;
    esname.which = Z_ElementSetNames_generic;
    esname.u.generic = elementSetName;
    if ((req->preferredRecordSyntax =
	 record_syntax(odr, preferredRecordSyntax)) == 0)
	return nodata(*errmsgp = "can't convert record syntax");

    return encode_apdu(odr, apdu, errmsgp);
}


databuf makeDeleteRSRequest(databuf referenceId,
			    char *resultSetId,
			    char **errmsgp)
{
    static ODR odr = 0;
    Z_APDU *apdu;
    Z_DeleteResultSetRequest *req;
    Z_ReferenceId zr;
    Z_ResultSetId *rsList[1];
    int x;

    if (!prepare_odr(&odr, errmsgp))
	return nodata((char*) 0);
    apdu = zget_APDU(odr, Z_APDU_deleteResultSetRequest);
    req = apdu->u.deleteResultSetRequest;

    req->referenceId = make_ref_id(&zr, referenceId);
    req->deleteFunction = &x;
    x = Z_DeleteResultSetRequest_list;
    req->num_resultSetList = 1;
    req->resultSetList = &rsList[0];
    rsList[0] = resultSetId;

    return encode_apdu(odr, apdu, errmsgp);
}


/*
 * If refId is non-null, copy it into the provided buffer, and return
 * a pointer to it; otherwise, return a null pointer.  Either way, the
 * result is suitable to by plugged into an APDU structure.
 */
Z_ReferenceId *make_ref_id(Z_ReferenceId *buf, databuf refId)
{
    if (refId.data == 0)
	return 0;

    buf->buf = (unsigned char*) refId.data;
    buf->len = (int) refId.len;
    return buf;
}


static Odr_oid *record_syntax(ODR odr, int preferredRecordSyntax)
{
    oident prefsyn;
    int oidbuf[20];		/* more than enough */
    int *oid;

    prefsyn.proto = PROTO_Z3950;
    prefsyn.oclass = CLASS_RECSYN;
    prefsyn.value = (oid_value) preferredRecordSyntax;
    if ((oid = oid_ent_to_oid(&prefsyn, oidbuf)) == 0)
	return 0;

    return odr_oiddup(odr, oid);
}


/*
 * Memory management strategy: every APDU we're asked to allocate
 * obliterates the previous one by overwriting our static ODR buffer,
 * so the caller _must_ ensure that it copies or otherwise consumes
 * the return value before the next call is made.  (This strategy
 * would normally stink, but it's actually not error-prone in this
 * context, since we know that the Perl XS code is about to copy the
 * data onto its stack.)
 */
static databuf encode_apdu(ODR odr, Z_APDU *apdu, char **errmsgp)
{
    databuf res;
    int len;
    res.len = 0;		/* Not needed, but prevents compiler warning */
    res.data = 0;

    if (!z_APDU(odr, &apdu, 0, (char*) 0)) {
	*errmsgp = odr_errmsg(odr_geterror(odr));
	return res;
    }

    res.data = odr_getbuf(odr, &len, (int*) 0);
    res.len = len;
    return res;
}


static int prepare_odr(ODR *odrp, char **errmsgp)
{
    if (*odrp != 0) {
	odr_reset(*odrp);
    } else if ((*odrp = odr_createmem(ODR_ENCODE)) == 0) {
	*errmsgp = "can't create ODR stream";
	return 0;
    }

    return 1;
}


/*
 * Return a databuf with a null pointer (used as an error indicator)
 * (In passing, we also report to stderr what the problem was.)
 */
static databuf nodata(char *msg)
{
    databuf buf;

#ifndef NDEBUG
    if (msg != 0) {
	fprintf(stderr, "DEBUG nodata(): %s\n", msg);
    }
#endif
    buf.len = 0;		/* Not needed, but prevents compiler warning */



( run in 1.915 second using v1.01-cache-2.11-cpan-0bb4e1dffa6 )