287 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			287 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| //
 | |
| //  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>
 | |
| 
 | |
| #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 HAVE_FMEMOPEN
 | |
|     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);
 | |
|       if (rc < 0) {
 | |
|         Yap_Error( EVALUATION_ERROR_UNDEFINED, MkAtomTerm(at), "failure in user-defined blob to string code" );
 | |
|       }
 | |
|       fclose(f);    // return the final result.
 | |
|     return s;
 | |
|     } else {
 | |
| #endif
 | |
| #if __APPLE__
 | |
|         size_t sz0 = strlcpy( s, (char *)RepAtom( AtomSWIStream )->StrOfAE, sz);
 | |
| #else
 | |
|         size_t sz0;
 | |
| 	char *f = (char *)memcpy(s, (char *)RepAtom( AtomSWIStream )->StrOfAE, sz);
 | |
| 	f[0]='\0';
 | |
| 	sz0 = f-s;
 | |
| #endif
 | |
|         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;
 | |
| #if HAVE_FMEMOPEN
 | |
|    }
 | |
|     return NULL;
 | |
| #endif
 | |
| }
 | |
| 
 | |
| 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;
 | |
|     YAP_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)
 | |
| {
 | |
|     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)) {
 | |
|                 UNLOCK(Blobs_Lock);
 | |
|                 return ae;
 | |
|             }
 | |
|             ae = RepAtom(ae->NextOfAE);
 | |
|         }
 | |
|     }
 | |
|     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) {
 | |
|         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((char *)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)
 | |
| {
 | |
|     
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * @}
 | |
|  */
 |