diff --git a/C/blobs.c b/C/blobs.c new file mode 100644 index 000000000..124fd2aba --- /dev/null +++ b/C/blobs.c @@ -0,0 +1,269 @@ +// +// blobs.c +// yap +// +// Created by VITOR SANTOS COSTA on 09/05/15. +// Copyright (c) 2015 VITOR SANTOS COSTA. All rights reserved. +// + +#include +#include + +#include "Yap.h" +#include "Yatom.h" +#include "iopreds.h" +#include "yapio.h" + +/* for freeBSD9.1 */ +#define _WITH_DPRINTF + +#ifdef __APPLE__ +#include "fmemopen.h" +#endif + +#include "blobs.h" + +static blob_type_t unregistered_blob_atom = +{ YAP_BLOB_MAGIC_B, + PL_BLOB_NOCOPY|PL_BLOB_TEXT, + "unregistered" +}; + +char * Yap_blob_to_string(AtomEntry *ref, const char *s0, size_t sz) +{ + int rc; + char *s = (char *)s0; + + blob_type_t *type = RepBlobProp(ref->PropsOfAE)->blob_type; + if (type->write) { + FILE *f = fmemopen( s, sz, "w"); + if (f == NULL){ + // could not find stream; + return NULL; + } + Atom at = AbsAtom(ref); + rc = type->write(f, at, 0); + fclose(f); // return the final result. + return s; + } else { + size_t sz0 = strlcpy( s, RepAtom( AtomSWIStream )->StrOfAE, sz); + s = s+sz0; + sz -= sz0; +#if defined(__linux__) || defined(__APPLE__) + snprintf(s+strlen(s), sz0, "(%p)", ref); +#else + snprintf(s+strlen(s), sz0, "(0x%p)", ref); +#endif + return s; + } + return NULL; +} + +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 { +#if defined(__linux__) || defined(__APPLE__) + return fprintf(stream, "\'%s\'(%p)", RepAtom(AtomSWIStream)->StrOfAE, ref); +#else + return fprintf(stream, "\'%s\'(0x%p)", RepAtom(AtomSWIStream)->StrOfAE, ref); +#endif + + } + return 0; + } + + +bool +YAP_is_blob(Term t, blob_type_t **type) +{ + CACHE_REGS + Term yt = Yap_GetFromSlot(t); + Atom a; + BlobPropEntry *b; + + 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; +} + + +/* void check_chain(void); */ + +/* void check_chain(void) { */ +/* AtomEntry *ae, *old; */ +/* ae = Blobs; */ +/* old = NULL; */ +/* while (ae) { */ +/* old = ae; */ +/* ae = RepAtom(ae->NextOfAE); */ +/* } */ +/* } */ + +AtomEntry * +Yap_lookupBlob(void *blob, size_t len, void *type0, int *new) +{ + 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)) { + UNLOCK(Blobs_Lock); + return ae; + } + ae = RepAtom(ae->NextOfAE); + } + } + if (new) + *new = TRUE; + b = (BlobPropEntry *)Yap_AllocCodeSpace(sizeof(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) { + UNLOCK(Blobs_Lock); + 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; +} + +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; +} + +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; +} + +void * +YAP_blob_data(Atom x, size_t *len, blob_type_t **type) +{ + + if (!IsBlob(x)) { + if (IsWideAtom(x)) { + if ( len ) + *len = wcslen(x->WStrOfAE); + if ( type ) + *type = &unregistered_blob_atom; + return x->WStrOfAE; + } + if ( len ) + *len = strlen(x->StrOfAE); + 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; +} + +void +YAP_register_blob_type(blob_type_t *type) +{ + type->next = (void *)BlobTypes; + BlobTypes = (void*)type; +} + +blob_type_t* +YAP_find_blob_type(const char* name) +{ + AtomEntry *a = RepAtom(Yap_LookupAtom(name)); + if (!IsBlob(a)) { + return &unregistered_blob_atom; + } + return RepBlobProp(a->PropsOfAE)->blob_type; +} + +bool +YAP_unregister_blob_type(blob_type_t *type) +{ + fprintf(stderr,"YAP_unregister_blob_type not implemented yet\n"); + return FALSE; +} + +void +Yap_install_blobs(void) +{ + +} + +/** + * @} + */