2015-07-23 01:00:28 +01:00
|
|
|
//
|
|
|
|
// blobs.c
|
|
|
|
// yap
|
|
|
|
//
|
|
|
|
// Created by VITOR SANTOS COSTA on 09/05/15.
|
|
|
|
// Copyright (c) 2015 VITOR SANTOS COSTA. All rights reserved.
|
|
|
|
//
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
2016-04-05 02:18:47 +01:00
|
|
|
#include "Yap.h"
|
|
|
|
#include "Yatom.h"
|
2015-07-23 01:00:28 +01:00
|
|
|
#include "iopreds.h"
|
2016-04-05 02:18:47 +01:00
|
|
|
#include "yapio.h"
|
2015-07-23 01:00:28 +01:00
|
|
|
|
|
|
|
/* for freeBSD9.1 */
|
|
|
|
#define _WITH_DPRINTF
|
|
|
|
|
|
|
|
#ifdef __APPLE__
|
|
|
|
#include "fmemopen.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "blobs.h"
|
|
|
|
|
2016-04-05 02:18:47 +01:00
|
|
|
static blob_type_t unregistered_blob_atom = {
|
|
|
|
YAP_BLOB_MAGIC_B, PL_BLOB_NOCOPY | PL_BLOB_TEXT, "unregistered"};
|
2015-07-23 01:00:28 +01:00
|
|
|
|
2016-04-05 02:18:47 +01:00
|
|
|
char *Yap_blob_to_string(AtomEntry *ref, const char *s0, size_t sz) {
|
2016-03-29 01:51:48 +01:00
|
|
|
// int rc;
|
2016-04-05 02:18:47 +01:00
|
|
|
char *s = (char *)s0;
|
|
|
|
|
2016-04-12 15:18:42 +01:00
|
|
|
#if HAVE_FMEMOPEN
|
|
|
|
blob_type_t *type = RepBlobProp(ref->PropsOfAE)->blob_type;
|
2016-04-05 02:18:47 +01:00
|
|
|
if (type->write) {
|
|
|
|
FILE *f = fmemopen(s, sz, "w");
|
|
|
|
if (f == NULL) {
|
|
|
|
// could not find stream;
|
|
|
|
return NULL;
|
2015-07-23 01:00:28 +01:00
|
|
|
}
|
|
|
|
Atom at = AbsAtom(ref);
|
2016-04-12 15:18:42 +01:00
|
|
|
int rc = type->write(f, at, 0);
|
2016-04-05 02:18:47 +01:00
|
|
|
if (rc < 0) {
|
|
|
|
Yap_Error(EVALUATION_ERROR_UNDEFINED, MkAtomTerm(at),
|
|
|
|
"failure in user-defined blob to string code");
|
|
|
|
}
|
|
|
|
fclose(f); // return the final result.
|
2015-07-23 01:00:28 +01:00
|
|
|
return s;
|
2016-04-05 02:18:47 +01:00
|
|
|
} else {
|
2016-01-31 10:05:15 +00:00
|
|
|
#endif
|
2015-10-20 08:06:46 +01:00
|
|
|
#if __APPLE__
|
2016-04-05 02:18:47 +01:00
|
|
|
size_t sz0 = strlcpy(s, (char *)RepAtom(AtomSWIStream)->StrOfAE, sz);
|
2015-10-20 08:06:46 +01:00
|
|
|
#else
|
2016-04-05 02:18:47 +01:00
|
|
|
size_t sz0;
|
|
|
|
char *f = (char *)memcpy(s, (char *)RepAtom(AtomSWIStream)->StrOfAE, sz);
|
|
|
|
f[0] = '\0';
|
|
|
|
sz0 = f - s;
|
2015-10-20 08:06:46 +01:00
|
|
|
#endif
|
2016-04-05 02:18:47 +01:00
|
|
|
s = s + sz0;
|
|
|
|
sz -= sz0;
|
2015-07-23 01:00:28 +01:00
|
|
|
#if defined(__linux__) || defined(__APPLE__)
|
2016-04-05 02:18:47 +01:00
|
|
|
snprintf(s + strlen(s), sz0, "(%p)", ref);
|
2015-07-23 01:00:28 +01:00
|
|
|
#else
|
2016-04-05 02:18:47 +01:00
|
|
|
snprintf(s + strlen(s), sz0, "(0x%p)", ref);
|
2015-07-23 01:00:28 +01:00
|
|
|
#endif
|
2016-04-05 02:18:47 +01:00
|
|
|
return s;
|
2016-01-31 10:05:15 +00:00
|
|
|
#if HAVE_FMEMOPEN
|
2016-04-05 02:18:47 +01:00
|
|
|
}
|
|
|
|
return NULL;
|
2016-01-31 10:05:15 +00:00
|
|
|
#endif
|
2015-07-23 01:00:28 +01:00
|
|
|
}
|
|
|
|
|
2016-04-05 02:18:47 +01:00
|
|
|
int Yap_write_blob(AtomEntry *ref, FILE *stream) {
|
|
|
|
blob_type_t *type = RepBlobProp(ref->PropsOfAE)->blob_type;
|
|
|
|
|
|
|
|
if (type->write) {
|
|
|
|
|
|
|
|
Atom at = AbsAtom(ref);
|
|
|
|
return type->write(stream, at, 0);
|
|
|
|
} else {
|
2015-07-23 01:00:28 +01:00
|
|
|
#if defined(__linux__) || defined(__APPLE__)
|
2016-04-05 02:18:47 +01:00
|
|
|
return fprintf(stream, "\'%s\'(%p)", RepAtom(AtomSWIStream)->StrOfAE, ref);
|
2015-07-23 01:00:28 +01:00
|
|
|
#else
|
2016-04-05 02:18:47 +01:00
|
|
|
return fprintf(stream, "\'%s\'(0x%p)", RepAtom(AtomSWIStream)->StrOfAE,
|
|
|
|
ref);
|
2015-07-23 01:00:28 +01:00
|
|
|
#endif
|
2016-04-05 02:18:47 +01:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
2015-07-23 01:00:28 +01:00
|
|
|
|
2016-04-05 02:18:47 +01:00
|
|
|
bool YAP_is_blob(Term t, blob_type_t **type) {
|
|
|
|
CACHE_REGS
|
|
|
|
Term yt = Yap_GetFromSlot(t);
|
|
|
|
Atom a;
|
|
|
|
YAP_BlobPropEntry *b;
|
2015-07-23 01:00:28 +01:00
|
|
|
|
2016-04-05 02:18:47 +01:00
|
|
|
if (IsVarTerm(yt))
|
|
|
|
return FALSE;
|
|
|
|
if (!IsAtomTerm(yt))
|
|
|
|
return FALSE;
|
|
|
|
a = AtomOfTerm(yt);
|
|
|
|
if (!IsBlob(a))
|
|
|
|
return FALSE;
|
|
|
|
b = RepBlobProp(a->PropsOfAE);
|
|
|
|
*type = b->blob_type;
|
|
|
|
return TRUE;
|
2015-07-23 01:00:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* void check_chain(void); */
|
|
|
|
|
|
|
|
/* void check_chain(void) { */
|
|
|
|
/* AtomEntry *ae, *old; */
|
|
|
|
/* ae = Blobs; */
|
|
|
|
/* old = NULL; */
|
|
|
|
/* while (ae) { */
|
|
|
|
/* old = ae; */
|
|
|
|
/* ae = RepAtom(ae->NextOfAE); */
|
|
|
|
/* } */
|
|
|
|
/* } */
|
|
|
|
|
2016-04-05 02:18:47 +01:00
|
|
|
AtomEntry *Yap_lookupBlob(void *blob, size_t len, void *type0, int *new) {
|
|
|
|
YAP_BlobPropEntry *b;
|
|
|
|
AtomEntry *ae;
|
|
|
|
blob_type_t *type = type0;
|
|
|
|
if (new)
|
|
|
|
*new = FALSE;
|
|
|
|
|
|
|
|
LOCK(Blobs_Lock);
|
|
|
|
if (type->flags & PL_BLOB_UNIQUE) {
|
|
|
|
/* just keep a linked chain for now */
|
|
|
|
ae = Blobs;
|
|
|
|
while (ae) {
|
|
|
|
if (ae->PropsOfAE && RepBlobProp(ae->PropsOfAE)->blob_type == type &&
|
|
|
|
ae->rep.blob->length == len &&
|
|
|
|
!memcmp(ae->rep.blob->data, blob, len)) {
|
2015-07-23 01:00:28 +01:00
|
|
|
UNLOCK(Blobs_Lock);
|
2016-04-05 02:18:47 +01:00
|
|
|
return ae;
|
|
|
|
}
|
|
|
|
ae = RepAtom(ae->NextOfAE);
|
2015-07-23 01:00:28 +01:00
|
|
|
}
|
2016-04-05 02:18:47 +01:00
|
|
|
}
|
|
|
|
if (new)
|
|
|
|
*new = TRUE;
|
|
|
|
b = (YAP_BlobPropEntry *)Yap_AllocCodeSpace(sizeof(YAP_BlobPropEntry));
|
|
|
|
if (!b) {
|
|
|
|
UNLOCK(Blobs_Lock);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
b->NextOfPE = NIL;
|
|
|
|
b->KindOfPE = BlobProperty;
|
|
|
|
b->blob_type = type;
|
|
|
|
ae =
|
|
|
|
(AtomEntry *)Yap_AllocCodeSpace(sizeof(AtomEntry) + len + sizeof(size_t));
|
|
|
|
if (!ae) {
|
2015-07-23 01:00:28 +01:00
|
|
|
UNLOCK(Blobs_Lock);
|
2016-04-05 02:18:47 +01:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
NOfBlobs++;
|
|
|
|
INIT_RWLOCK(ae->ARWLock);
|
|
|
|
ae->PropsOfAE = AbsBlobProp(b);
|
|
|
|
ae->NextOfAE = AbsAtom(Blobs);
|
|
|
|
ae->rep.blob->length = len;
|
|
|
|
memcpy(ae->rep.blob->data, blob, len);
|
|
|
|
Blobs = ae;
|
|
|
|
if (NOfBlobs > NOfBlobsMax) {
|
|
|
|
Yap_signal(YAP_CDOVF_SIGNAL);
|
|
|
|
}
|
|
|
|
UNLOCK(Blobs_Lock);
|
|
|
|
return ae;
|
2015-07-23 01:00:28 +01:00
|
|
|
}
|
|
|
|
|
2016-04-05 02:18:47 +01:00
|
|
|
bool YAP_unify_blob(Term *t, void *blob, size_t len, blob_type_t *type) {
|
|
|
|
AtomEntry *ae;
|
|
|
|
|
|
|
|
if (!blob)
|
|
|
|
return FALSE;
|
|
|
|
ae = Yap_lookupBlob(blob, len, type, NULL);
|
|
|
|
if (!ae) {
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
if (type->acquire) {
|
|
|
|
type->acquire(AbsAtom(ae));
|
|
|
|
}
|
|
|
|
*t = MkAtomTerm(AbsAtom(ae));
|
|
|
|
return true;
|
2015-07-23 01:00:28 +01:00
|
|
|
}
|
|
|
|
|
2016-04-05 02:18:47 +01:00
|
|
|
bool YAP_get_blob(Term t, void **blob, size_t *len, blob_type_t **type) {
|
|
|
|
CACHE_REGS
|
|
|
|
Atom a;
|
|
|
|
Term tt;
|
|
|
|
AtomEntry *ae;
|
|
|
|
|
|
|
|
tt = Yap_GetFromSlot(t);
|
|
|
|
if (IsVarTerm(tt))
|
|
|
|
return FALSE;
|
|
|
|
if (!IsAtomTerm(tt))
|
|
|
|
return FALSE;
|
|
|
|
a = AtomOfTerm(tt);
|
|
|
|
if (!IsBlob(a))
|
|
|
|
return FALSE;
|
|
|
|
ae = RepAtom(a);
|
|
|
|
if (type)
|
|
|
|
*type = RepBlobProp(ae->PropsOfAE)->blob_type;
|
|
|
|
if (len)
|
|
|
|
*len = ae->rep.blob[0].length;
|
|
|
|
if (blob)
|
|
|
|
*blob = ae->rep.blob[0].data;
|
|
|
|
return TRUE;
|
2015-07-23 01:00:28 +01:00
|
|
|
}
|
|
|
|
|
2016-04-05 02:18:47 +01:00
|
|
|
void *YAP_blob_data(Atom x, size_t *len, blob_type_t **type) {
|
|
|
|
|
|
|
|
if (!IsBlob(x)) {
|
|
|
|
|
|
|
|
if (len)
|
2016-11-02 05:16:36 +00:00
|
|
|
*len = strlen_utf8(x->UStrOfAE);
|
2016-04-05 02:18:47 +01:00
|
|
|
if (type)
|
|
|
|
*type = &unregistered_blob_atom;
|
|
|
|
return x->StrOfAE;
|
|
|
|
}
|
|
|
|
if (len)
|
|
|
|
*len = x->rep.blob[0].length;
|
|
|
|
if (type)
|
|
|
|
*type = RepBlobProp(x->PropsOfAE)->blob_type;
|
|
|
|
return x->rep.blob[0].data;
|
2015-07-23 01:00:28 +01:00
|
|
|
}
|
|
|
|
|
2016-04-05 02:18:47 +01:00
|
|
|
void YAP_register_blob_type(blob_type_t *type) {
|
2015-07-23 01:00:28 +01:00
|
|
|
type->next = (void *)BlobTypes;
|
2016-04-05 02:18:47 +01:00
|
|
|
BlobTypes = (void *)type;
|
2015-07-23 01:00:28 +01:00
|
|
|
}
|
|
|
|
|
2016-04-05 02:18:47 +01:00
|
|
|
blob_type_t *YAP_find_blob_type(const char *name) {
|
2015-07-23 01:00:28 +01:00
|
|
|
AtomEntry *a = RepAtom(Yap_LookupAtom(name));
|
2016-04-05 02:18:47 +01:00
|
|
|
if (!IsBlob(a)) {
|
|
|
|
return &unregistered_blob_atom;
|
|
|
|
}
|
|
|
|
return RepBlobProp(a->PropsOfAE)->blob_type;
|
2015-07-23 01:00:28 +01:00
|
|
|
}
|
|
|
|
|
2016-04-05 02:18:47 +01:00
|
|
|
bool YAP_unregister_blob_type(blob_type_t *type) {
|
|
|
|
fprintf(stderr, "YAP_unregister_blob_type not implemented yet\n");
|
|
|
|
return FALSE;
|
2015-07-23 01:00:28 +01:00
|
|
|
}
|
|
|
|
|
2016-04-05 02:18:47 +01:00
|
|
|
void Yap_install_blobs(void) {}
|
2015-07-23 01:00:28 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @}
|
|
|
|
*/
|