2 Port from c++ is protected by a GNU Lesser GPLv3
3 Copyright © 2013 Sylvain BERTRAND <sylvain.bertrand@gmail.com>
11 #include "hb-private.h"
12 #include "hb-atomic-private.h"
13 #include "hb-open-file-private.h"
14 #include "hb-blob-private.h"
17 atomic_int32_t ref_cnt
;
22 hb_memory_mode_t mode
;
25 hb_destroy_func_t destroy
;
28 /*XXX:should go in lib "global init"*/
29 static hb_blob_t hb_blob_nil
= {
30 REF_CNT_INVALID_VAL
, /*ref_cnt */
34 HB_MEMORY_MODE_READONLY
, /*mode */
39 hb_blob_t
*hb_blob_get_empty(void)
44 hb_blob_t
*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);
51 void hb_blob_make_immutable(hb_blob_t
* blob
)
53 if (hb_atomic_int32_get(&blob
->ref_cnt
) == REF_CNT_INVALID_VAL
)
55 blob
->immutable
= TRUE
;
58 unsigned hb_blob_get_length(hb_blob_t
* blob
)
63 const char *hb_blob_get_data(hb_blob_t
* blob
, unsigned *length
)
66 *length
= blob
->length
;
70 static hb_bool_t
try_make_writable_inplace_unix(hb_blob_t
* blob
)
72 uintptr_t pagesize
, mask
, length
;
75 pagesize
= (uintptr_t) sysconf(_SC_PAGESIZE
);
77 if ((uintptr_t) - 1L == pagesize
)
80 mask
= ~(pagesize
- 1);
81 addr
= (const char *)(((uintptr_t) blob
->data
) & mask
);
84 *)(((uintptr_t) blob
->data
+ blob
->length
+ pagesize
- 1)
86 if (-1 == mprotect((void *)addr
, length
, PROT_READ
| PROT_WRITE
))
89 blob
->mode
= HB_MEMORY_MODE_WRITABLE
;
93 static hb_bool_t
try_writable_inplace(hb_blob_t
* blob
)
95 if (try_make_writable_inplace_unix(blob
))
98 /*Failed to make writable inplace, mark that */
99 blob
->mode
= HB_MEMORY_MODE_READONLY
;
103 static void hb_blob_destroy_user_data(hb_blob_t
* blob
)
106 blob
->destroy(blob
->user_data
);
107 blob
->user_data
= NULL
;
108 blob
->destroy
= NULL
;
112 static hb_bool_t
try_writable(hb_blob_t
* blob
)
119 if (blob
->mode
== HB_MEMORY_MODE_WRITABLE
)
122 if (blob
->mode
== HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE
123 && try_writable_inplace(blob
))
126 if (blob
->mode
== HB_MEMORY_MODE_WRITABLE
)
129 new_data
= malloc(blob
->length
);
133 memcpy(new_data
, blob
->data
, blob
->length
);
134 hb_blob_destroy_user_data(blob
);
135 blob
->mode
= HB_MEMORY_MODE_WRITABLE
;
136 blob
->data
= new_data
;
137 blob
->user_data
= new_data
;
138 blob
->destroy
= free
;
142 void hb_blob_destroy(hb_blob_t
* blob
)
146 if (hb_atomic_int32_get(&blob
->ref_cnt
) == REF_CNT_INVALID_VAL
)
148 hb_atomic_int32_add(&blob
->ref_cnt
, -1);
149 if (hb_atomic_int32_get(&blob
->ref_cnt
) > 0)
151 hb_atomic_int32_set(&blob
->ref_cnt
, REF_CNT_INVALID_VAL
);
153 hb_blob_destroy_user_data(blob
);
157 hb_blob_t
*hb_blob_create_sub_blob(hb_blob_t
* parent
,
158 unsigned offset
, unsigned length
)
162 if (!length
|| offset
>= parent
->length
)
163 return hb_blob_get_empty();
165 hb_blob_make_immutable(parent
);
167 blob
= hb_blob_create(parent
->data
+ offset
,
168 MIN(length
, parent
->length
- offset
),
169 HB_MEMORY_MODE_READONLY
,
170 hb_blob_reference(parent
),
171 (hb_destroy_func_t
) hb_blob_destroy
);
175 hb_blob_t
*hb_blob_create(const char *data
, unsigned length
,
176 hb_memory_mode_t mode
, void *user_data
,
177 hb_destroy_func_t destroy
)
179 hb_blob_t
*blob
= calloc(1, sizeof(*blob
));
180 if (!length
|| !blob
) {
185 return hb_blob_get_empty();
187 hb_atomic_int32_set(&blob
->ref_cnt
, 1);
188 blob
->immutable
= FALSE
;
191 blob
->length
= length
;
194 blob
->user_data
= user_data
;
195 blob
->destroy
= destroy
;
197 if (blob
->mode
== HB_MEMORY_MODE_DUPLICATE
) {
198 blob
->mode
= HB_MEMORY_MODE_READONLY
;
199 if (!try_writable(blob
)) {
200 hb_blob_destroy(blob
);
201 return hb_blob_get_empty();
207 struct ot_fnt_file
*hb_blob_lock_instance(hb_blob_t
* blob
)
211 hb_blob_make_immutable(blob
);
212 base
= hb_blob_get_data(blob
, NULL
);
213 return (struct ot_fnt_file
*)base
;