1 // C99 port from c++ is protected by a GNU Lesser GPLv3
2 // Copyright © 2013 Sylvain BERTRAND <sylvain.bertrand@gmail.com>
3 // <sylware@legeek.net>
10 #include "hb-private.h"
11 #include "hb-atomic-private.h"
12 #include "hb-open-file-private.h"
13 #include "hb-blob-private.h"
16 atomic_int32_t ref_cnt
;
21 hb_memory_mode_t mode
;
24 hb_destroy_func_t destroy
;
27 static hb_blob_t hb_blob_nil
= {
28 REF_CNT_INVALID_VAL
,//ref_cnt
32 HB_MEMORY_MODE_READONLY
,//mode
38 hb_blob_get_empty(void)
44 hb_blob_reference(hb_blob_t
*blob
)
46 if (hb_atomic_int32_get(&blob
->ref_cnt
) != REF_CNT_INVALID_VAL
)
47 hb_atomic_int32_add(&blob
->ref_cnt
, 1);
52 hb_blob_make_immutable(hb_blob_t
*blob
)
54 if (hb_atomic_int32_get(&blob
->ref_cnt
) == REF_CNT_INVALID_VAL
)
56 blob
->immutable
= TRUE
;
60 hb_blob_get_length(hb_blob_t
*blob
)
66 hb_blob_get_data(hb_blob_t
*blob
, unsigned *length
)
69 *length
= blob
->length
;
74 try_make_writable_inplace_unix(hb_blob_t
*blob
)
76 uintptr_t pagesize
= -1, mask
, length
;
79 pagesize
= (uintptr_t)sysconf(_SC_PAGESIZE
);
81 if ((uintptr_t) -1L == pagesize
)
85 addr
= (const char*)(((uintptr_t)blob
->data
) & mask
);
86 length
= (const char*)(((uintptr_t)blob
->data
+ blob
->length
+ pagesize
-1)
88 if (-1 == mprotect((void*)addr
, length
, PROT_READ
| PROT_WRITE
))
91 blob
->mode
= HB_MEMORY_MODE_WRITABLE
;
96 try_writable_inplace(hb_blob_t
*blob
)
98 if (try_make_writable_inplace_unix(blob
))
101 //Failed to make writable inplace, mark that
102 blob
->mode
= HB_MEMORY_MODE_READONLY
;
107 hb_blob_destroy_user_data(hb_blob_t
*blob
)
110 blob
->destroy(blob
->user_data
);
111 blob
->user_data
= NULL
;
112 blob
->destroy
= NULL
;
117 try_writable(hb_blob_t
*blob
)
122 if (blob
->mode
== HB_MEMORY_MODE_WRITABLE
)
125 if (blob
->mode
== HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE
126 && try_writable_inplace(blob
))
129 if (blob
->mode
== HB_MEMORY_MODE_WRITABLE
)
134 new_data
= malloc(blob
->length
);
138 memcpy(new_data
, blob
->data
, blob
->length
);
139 hb_blob_destroy_user_data(blob
);
140 blob
->mode
= HB_MEMORY_MODE_WRITABLE
;
141 blob
->data
= new_data
;
142 blob
->user_data
= new_data
;
143 blob
->destroy
= free
;
148 hb_blob_destroy(hb_blob_t
*blob
)
152 if (hb_atomic_int32_get(&blob
->ref_cnt
) == REF_CNT_INVALID_VAL
)
154 hb_atomic_int32_add(&blob
->ref_cnt
, -1);
155 if (hb_atomic_int32_get(&blob
->ref_cnt
) > 0)
157 hb_atomic_int32_set(&blob
->ref_cnt
, REF_CNT_INVALID_VAL
);
159 hb_blob_destroy_user_data(blob
);
164 hb_blob_create_sub_blob(hb_blob_t
*parent
,
170 if (!length
|| offset
>= parent
->length
)
171 return hb_blob_get_empty();
173 hb_blob_make_immutable(parent
);
175 blob
= hb_blob_create(parent
->data
+ offset
,
176 MIN(length
, parent
->length
- offset
),
177 HB_MEMORY_MODE_READONLY
,
178 hb_blob_reference(parent
),
179 (hb_destroy_func_t
)hb_blob_destroy
);
184 hb_blob_create(const char *data
,
186 hb_memory_mode_t mode
,
188 hb_destroy_func_t destroy
)
190 hb_blob_t
*blob
= calloc(1, sizeof(*blob
));
191 if (!length
|| !blob
) {
196 return hb_blob_get_empty();
198 hb_atomic_int32_set(&blob
->ref_cnt
, 1);
199 blob
->immutable
= FALSE
;
202 blob
->length
= length
;
205 blob
->user_data
= user_data
;
206 blob
->destroy
= destroy
;
208 if (blob
->mode
== HB_MEMORY_MODE_DUPLICATE
) {
209 blob
->mode
= HB_MEMORY_MODE_READONLY
;
210 if (!try_writable(blob
)) {
211 hb_blob_destroy(blob
);
212 return hb_blob_get_empty();
219 hb_blob_lock_instance(hb_blob_t
*blob
)
221 hb_blob_make_immutable (blob
);
222 const char *base
= hb_blob_get_data(blob
, NULL
);
223 return (struct ot_fnt_file
*)base
;