YAP 7.1.0
blobs.c
1
2// @file blobs.c
3// @bried Support of SWI-like atom-extension blobs.
4//
5// blobs.c
6// yap
7//
8// Created by VITOR SANTOS COSTA on 09/05/15.
9// Copyright (c) 2015 VITOR SANTOS COSTA. All rights reserved.
10//
11
15
16#include <stdio.h>
17#include <string.h>
18
19#include "Yap.h"
20#include "YapHeap.h"
21#include "iopreds.h"
22#include "yapio.h"
23
24/* for freeBSD9.1 */
25#define _WITH_DPRINTF
26
27#include "YapBlobs.h"
28
29static blob_type_t unregistered_blob_atom = {
30 YAP_BLOB_MAGIC_B, PL_BLOB_NOCOPY | PL_BLOB_TEXT, "unregistered"};
31
32char *Yap_blob_to_string(AtomEntry *ref, const char *s0, size_t sz) {
33 // int rc;
34 char *s = (char *)s0;
35
36#if HAVE_FMEMOPEN
37 blob_type_t *type = RepBlobProp(ref->PropsOfAE)->blob_type;
38 if (type->write) {
39 FILE *f = fmemopen(s, sz, "w");
40 if (f == NULL) {
41 // could not find stream;
42 return NULL;
43 }
44 Atom at = AbsAtom(ref);
45 int rc = type->write(f, at, 0);
46 if (rc < 0) {
47 Yap_Error(EVALUATION_ERROR_UNDEFINED, MkAtomTerm(at),
48 "failure in user-defined blob to string code");
49 }
50 fclose(f); // return the final result.
51 return s;
52 } else {
53#endif
54#if __APPLE__
55 size_t sz0 = strlcpy(s, (char *)RepAtom(AtomSWIStream)->StrOfAE, sz);
56#else
57 size_t sz0;
58 char *f = (char *)memcpy(s, (char *)RepAtom(AtomSWIStream)->StrOfAE, sz);
59 f[0] = '\0';
60 sz0 = f - s;
61#endif
62 s = s + sz0;
63 sz -= sz0;
64#if defined(__linux__) || defined(__APPLE__)
65 snprintf(s + strlen(s), sz0, "(%p)", ref);
66#else
67 snprintf(s + strlen(s), sz0, "(0x%p)", ref);
68#endif
69 return s;
70#if HAVE_FMEMOPEN
71 }
72 return NULL;
73#endif
74}
75
76int Yap_write_blob(AtomEntry *ref, FILE *stream) {
77 blob_type_t *type = RepBlobProp(ref->PropsOfAE)->blob_type;
78
79 if (type->write) {
80
81 Atom at = AbsAtom(ref);
82 return type->write(stream, at, 0);
83 } else {
84#if defined(__linux__) || defined(__APPLE__)
85 return fprintf(stream, "\'%s\'(%p)", RepAtom(AtomSWIStream)->StrOfAE, ref);
86#else
87 return fprintf(stream, "\'%s\'(0x%p)", RepAtom(AtomSWIStream)->StrOfAE,
88 ref);
89#endif
90 }
91 return 0;
92}
93
94bool YAP_is_blob(Term t, blob_type_t **type) {
95 CACHE_REGS
96 Term yt = Yap_GetFromSlot(t);
97 Atom a;
99
100 if (IsVarTerm(yt))
101 return FALSE;
102 if (!IsAtomTerm(yt))
103 return FALSE;
104 a = AtomOfTerm(yt);
105 if (!IsBlob(a))
106 return FALSE;
107 b = RepBlobProp(a->PropsOfAE);
108 *type = b->blob_type;
109 return TRUE;
110}
111
112/* void check_chain(void); */
113
114/* void check_chain(void) { */
115/* AtomEntry *ae, *old; */
116/* ae = Blobs; */
117/* old = NULL; */
118/* while (ae) { */
119/* old = ae; */
120/* ae = RepAtom(ae->NextOfAE); */
121/* } */
122/* } */
123
124AtomEntry *Yap_lookupBlob(void *blob, size_t len, void *type0, int *new) {
126 AtomEntry *ae;
127 blob_type_t *type = type0;
128 if (new)
129 *new = FALSE;
130
131 LOCK(Blobs_Lock);
132 if (type->flags & PL_BLOB_UNIQUE) {
133 /* just keep a linked chain for now */
134 ae = Blobs;
135 while (ae) {
136 if (ae->PropsOfAE && RepBlobProp(ae->PropsOfAE)->blob_type == type &&
137 ae->rep.blob->length == len &&
138 !memcmp(ae->rep.blob->data, blob, len)) {
139 UNLOCK(Blobs_Lock);
140 return ae;
141 }
142 ae = RepAtom(ae->NextOfAE);
143 }
144 }
145 if (new)
146 *new = TRUE;
147 b = (YAP_BlobPropEntry *)Yap_AllocCodeSpace(sizeof(YAP_BlobPropEntry));
148 if (!b) {
149 UNLOCK(Blobs_Lock);
150 return NULL;
151 }
152 b->NextOfPE = NIL;
153 b->KindOfPE = BlobProperty;
154 b->blob_type = type;
155 ae =
156 (AtomEntry *)Yap_AllocCodeSpace(sizeof(AtomEntry) + len + sizeof(size_t));
157 if (!ae) {
158 UNLOCK(Blobs_Lock);
159 return NULL;
160 }
161 NOfBlobs++;
162 INIT_RWLOCK(ae->ARWLock);
163 ae->PropsOfAE = AbsBlobProp(b);
164 ae->NextOfAE = AbsAtom(Blobs);
165 ae->rep.blob->length = len;
166 memcpy(ae->rep.blob->data, blob, len);
167 Blobs = ae;
168 if (NOfBlobs > NOfBlobsMax) {
169 Yap_signal(YAP_CDOVF_SIGNAL);
170 }
171 UNLOCK(Blobs_Lock);
172 return ae;
173}
174
175bool YAP_unify_blob(Term *t, void *blob, size_t len, blob_type_t *type) {
176 AtomEntry *ae;
177
178 if (!blob)
179 return FALSE;
180 ae = Yap_lookupBlob(blob, len, type, NULL);
181 if (!ae) {
182 return FALSE;
183 }
184 if (type->acquire) {
185 type->acquire(AbsAtom(ae));
186 }
187 *t = MkAtomTerm(AbsAtom(ae));
188 return true;
189}
190
191bool YAP_get_blob(Term t, void **blob, size_t *len, blob_type_t **type) {
192 CACHE_REGS
193 Atom a;
194 Term tt;
195 AtomEntry *ae;
196
197 tt = Yap_GetFromSlot(t);
198 if (IsVarTerm(tt))
199 return FALSE;
200 if (!IsAtomTerm(tt))
201 return FALSE;
202 a = AtomOfTerm(tt);
203 if (!IsBlob(a))
204 return FALSE;
205 ae = RepAtom(a);
206 if (type)
207 *type = RepBlobProp(ae->PropsOfAE)->blob_type;
208 if (len)
209 *len = ae->rep.blob[0].length;
210 if (blob)
211 *blob = ae->rep.blob[0].data;
212 return TRUE;
213}
214
215void *YAP_blob_data(YAP_Atom at, size_t *len, blob_type_t **type) {
216Atom x = at;
217 if (!IsBlob(x)) {
218
219 if (len)
220 *len = strlen_utf8(x->UStrOfAE);
221 if (type)
222 *type = &unregistered_blob_atom;
223 return x->StrOfAE;
224 }
225 if (len)
226 *len = x->rep.blob[0].length;
227 if (type)
228 *type = RepBlobProp(x->PropsOfAE)->blob_type;
229 return x->rep.blob[0].data;
230}
231
232void YAP_register_blob_type(blob_type_t *type) {
233 type->next = (void *)BlobTypes;
234 BlobTypes = (void *)type;
235}
236
237blob_type_t *YAP_find_blob_type(const char *name) {
238 AtomEntry *a = RepAtom(Yap_LookupAtom(name));
239 if (!IsBlob(a)) {
240 return &unregistered_blob_atom;
241 }
242 return RepBlobProp(a->PropsOfAE)->blob_type;
243}
244
245bool YAP_unregister_blob_type(blob_type_t *type) {
246 fprintf(stderr, "YAP_unregister_blob_type not implemented yet\n");
247 return FALSE;
248}
249
250void Yap_install_blobs(void) {}
251
Main definitions.
Definition: Yatom.h:1150