| 
									
										
										
										
											2015-07-22 19:00:28 -05: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>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #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; | 
					
						
							| 
									
										
										
										
											2016-01-31 10:05:15 +00:00
										 |  |  | #if HAVE_FMEMOPEN
 | 
					
						
							| 
									
										
										
										
											2015-07-22 19:00:28 -05:00
										 |  |  |     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); | 
					
						
							| 
									
										
										
										
											2015-11-05 15:14:11 +00: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-22 19:00:28 -05:00
										 |  |  |     return s; | 
					
						
							|  |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2016-01-31 10:05:15 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2015-10-20 08:06:46 +01:00
										 |  |  | #if __APPLE__
 | 
					
						
							| 
									
										
										
										
											2015-09-21 17:05:36 -05:00
										 |  |  |         size_t sz0 = strlcpy( s, (char *)RepAtom( AtomSWIStream )->StrOfAE, sz); | 
					
						
							| 
									
										
										
										
											2015-10-20 08:06:46 +01:00
										 |  |  | #else
 | 
					
						
							|  |  |  |         size_t sz0; | 
					
						
							|  |  |  | 	char *f = (char *)memcpy(s, (char *)RepAtom( AtomSWIStream )->StrOfAE, sz); | 
					
						
							|  |  |  | 	f[0]='\0'; | 
					
						
							|  |  |  | 	sz0 = f-s; | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2015-07-22 19:00:28 -05:00
										 |  |  |         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; | 
					
						
							| 
									
										
										
										
											2016-01-31 10:05:15 +00:00
										 |  |  | #if HAVE_FMEMOPEN
 | 
					
						
							|  |  |  |    } | 
					
						
							| 
									
										
										
										
											2015-07-22 19:00:28 -05:00
										 |  |  |     return NULL; | 
					
						
							| 
									
										
										
										
											2016-01-31 10:05:15 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2015-07-22 19:00:28 -05: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); | 
					
						
							| 
									
										
										
										
											2015-10-22 00:33:38 +01:00
										 |  |  |             return type->write(stream, at, 0); | 
					
						
							| 
									
										
										
										
											2015-07-22 19:00:28 -05:00
										 |  |  |     } 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; | 
					
						
							| 
									
										
										
										
											2015-10-22 00:33:38 +01:00
										 |  |  |     YAP_BlobPropEntry *b; | 
					
						
							| 
									
										
										
										
											2015-07-22 19:00:28 -05: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; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* 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) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2015-10-22 00:33:38 +01:00
										 |  |  |     YAP_BlobPropEntry *b; | 
					
						
							| 
									
										
										
										
											2015-07-22 19:00:28 -05:00
										 |  |  |     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; | 
					
						
							| 
									
										
										
										
											2015-10-22 00:33:38 +01:00
										 |  |  |     b = (YAP_BlobPropEntry *)Yap_AllocCodeSpace(sizeof(YAP_BlobPropEntry)); | 
					
						
							| 
									
										
										
										
											2015-07-22 19:00:28 -05:00
										 |  |  |     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 ) | 
					
						
							| 
									
										
										
										
											2015-10-22 00:33:38 +01:00
										 |  |  |                | 
					
						
							|  |  |  |                | 
					
						
							|  |  |  |                | 
					
						
							|  |  |  |               *type = &unregistered_blob_atom; | 
					
						
							| 
									
										
										
										
											2015-07-22 19:00:28 -05:00
										 |  |  |             return x->WStrOfAE; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if ( len ) | 
					
						
							| 
									
										
										
										
											2015-09-21 17:05:36 -05:00
										 |  |  |             *len = strlen((char *)x->StrOfAE); | 
					
						
							| 
									
										
										
										
											2015-07-22 19:00:28 -05: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; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * @} | 
					
						
							|  |  |  |  */ |