| File: | src/fccharset.c |
| Location: | line 216, column 5 |
| Description: | Potential leak of memory pointed to by 'leaves' |
| 1 | /* | |||
| 2 | * fontconfig/src/fccharset.c | |||
| 3 | * | |||
| 4 | * Copyright © 2001 Keith Packard | |||
| 5 | * | |||
| 6 | * Permission to use, copy, modify, distribute, and sell this software and its | |||
| 7 | * documentation for any purpose is hereby granted without fee, provided that | |||
| 8 | * the above copyright notice appear in all copies and that both that | |||
| 9 | * copyright notice and this permission notice appear in supporting | |||
| 10 | * documentation, and that the name of the author(s) not be used in | |||
| 11 | * advertising or publicity pertaining to distribution of the software without | |||
| 12 | * specific, written prior permission. The authors make no | |||
| 13 | * representations about the suitability of this software for any purpose. It | |||
| 14 | * is provided "as is" without express or implied warranty. | |||
| 15 | * | |||
| 16 | * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, | |||
| 17 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO | |||
| 18 | * EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR | |||
| 19 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, | |||
| 20 | * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER | |||
| 21 | * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR | |||
| 22 | * PERFORMANCE OF THIS SOFTWARE. | |||
| 23 | */ | |||
| 24 | ||||
| 25 | #include "fcint.h" | |||
| 26 | #include <stdlib.h> | |||
| 27 | ||||
| 28 | /* #define CHECK */ | |||
| 29 | ||||
| 30 | FcCharSet * | |||
| 31 | FcCharSetCreate (void) | |||
| 32 | { | |||
| 33 | FcCharSet *fcs; | |||
| 34 | ||||
| 35 | fcs = (FcCharSet *) malloc (sizeof (FcCharSet)); | |||
| 36 | if (!fcs) | |||
| 37 | return 0; | |||
| 38 | FcRefInit (&fcs->ref, 1); | |||
| 39 | fcs->num = 0; | |||
| 40 | fcs->leaves_offset = 0; | |||
| 41 | fcs->numbers_offset = 0; | |||
| 42 | return fcs; | |||
| 43 | } | |||
| 44 | ||||
| 45 | FcCharSet * | |||
| 46 | FcCharSetPromote (FcValuePromotionBuffer *vbuf) | |||
| 47 | { | |||
| 48 | FcCharSet *fcs = (FcCharSet *) vbuf; | |||
| 49 | ||||
| 50 | FC_ASSERT_STATIC (sizeof (FcCharSet) <= sizeof (FcValuePromotionBuffer))typedef int _static_assert_on_line_50_failed[(((sizeof (FcCharSet ) <= sizeof (FcValuePromotionBuffer))))?1:-1] __attribute__ ((unused)); | |||
| 51 | ||||
| 52 | FcRefSetConst (&fcs->ref); | |||
| 53 | fcs->num = 0; | |||
| 54 | fcs->leaves_offset = 0; | |||
| 55 | fcs->numbers_offset = 0; | |||
| 56 | ||||
| 57 | return fcs; | |||
| 58 | } | |||
| 59 | ||||
| 60 | FcCharSet * | |||
| 61 | FcCharSetNew (void) | |||
| 62 | { | |||
| 63 | return FcCharSetCreate (); | |||
| 64 | } | |||
| 65 | ||||
| 66 | void | |||
| 67 | FcCharSetDestroy (FcCharSet *fcs) | |||
| 68 | { | |||
| 69 | int i; | |||
| 70 | ||||
| 71 | if (fcs) | |||
| 72 | { | |||
| 73 | if (FcRefIsConst (&fcs->ref)) | |||
| 74 | { | |||
| 75 | FcCacheObjectDereference (fcs); | |||
| 76 | return; | |||
| 77 | } | |||
| 78 | if (FcRefDec (&fcs->ref) != 1) | |||
| 79 | return; | |||
| 80 | for (i = 0; i < fcs->num; i++) | |||
| 81 | free (FcCharSetLeaf (fcs, i)(((FcCharLeaf *) ((intptr_t) (((intptr_t *) ((intptr_t) (fcs) + ((fcs)->leaves_offset)))) + (((intptr_t *) ((intptr_t) ( fcs) + ((fcs)->leaves_offset)))[i]))))); | |||
| 82 | if (fcs->num) | |||
| 83 | { | |||
| 84 | free (FcCharSetLeaves (fcs)((intptr_t *) ((intptr_t) (fcs) + ((fcs)->leaves_offset)))); | |||
| 85 | free (FcCharSetNumbers (fcs)((FcChar16 *) ((intptr_t) (fcs) + ((fcs)->numbers_offset)) )); | |||
| 86 | } | |||
| 87 | free (fcs); | |||
| 88 | } | |||
| 89 | } | |||
| 90 | ||||
| 91 | /* | |||
| 92 | * Search for the leaf containing with the specified num. | |||
| 93 | * Return its index if it exists, otherwise return negative of | |||
| 94 | * the (position + 1) where it should be inserted | |||
| 95 | */ | |||
| 96 | ||||
| 97 | ||||
| 98 | static int | |||
| 99 | FcCharSetFindLeafForward (const FcCharSet *fcs, int start, FcChar16 num) | |||
| 100 | { | |||
| 101 | FcChar16 *numbers = FcCharSetNumbers(fcs)((FcChar16 *) ((intptr_t) (fcs) + ((fcs)->numbers_offset)) ); | |||
| 102 | FcChar16 page; | |||
| 103 | int low = start; | |||
| 104 | int high = fcs->num - 1; | |||
| 105 | ||||
| 106 | if (!numbers) | |||
| 107 | return -1; | |||
| 108 | while (low <= high) | |||
| 109 | { | |||
| 110 | int mid = (low + high) >> 1; | |||
| 111 | page = numbers[mid]; | |||
| 112 | if (page == num) | |||
| 113 | return mid; | |||
| 114 | if (page < num) | |||
| 115 | low = mid + 1; | |||
| 116 | else | |||
| 117 | high = mid - 1; | |||
| 118 | } | |||
| 119 | if (high < 0 || (high < fcs->num && numbers[high] < num)) | |||
| 120 | high++; | |||
| 121 | return -(high + 1); | |||
| 122 | } | |||
| 123 | ||||
| 124 | /* | |||
| 125 | * Locate the leaf containing the specified char, return | |||
| 126 | * its index if it exists, otherwise return negative of | |||
| 127 | * the (position + 1) where it should be inserted | |||
| 128 | */ | |||
| 129 | ||||
| 130 | static int | |||
| 131 | FcCharSetFindLeafPos (const FcCharSet *fcs, FcChar32 ucs4) | |||
| 132 | { | |||
| 133 | return FcCharSetFindLeafForward (fcs, 0, ucs4 >> 8); | |||
| 134 | } | |||
| 135 | ||||
| 136 | static FcCharLeaf * | |||
| 137 | FcCharSetFindLeaf (const FcCharSet *fcs, FcChar32 ucs4) | |||
| 138 | { | |||
| 139 | int pos = FcCharSetFindLeafPos (fcs, ucs4); | |||
| 140 | if (pos >= 0) | |||
| 141 | return FcCharSetLeaf(fcs, pos)(((FcCharLeaf *) ((intptr_t) (((intptr_t *) ((intptr_t) (fcs) + ((fcs)->leaves_offset)))) + (((intptr_t *) ((intptr_t) ( fcs) + ((fcs)->leaves_offset)))[pos])))); | |||
| 142 | return 0; | |||
| 143 | } | |||
| 144 | ||||
| 145 | #define FC_IS_ZERO_OR_POWER_OF_TWO(x)(!((x) & ((x)-1))) (!((x) & ((x)-1))) | |||
| 146 | ||||
| 147 | static FcBool | |||
| 148 | FcCharSetPutLeaf (FcCharSet *fcs, | |||
| 149 | FcChar32 ucs4, | |||
| 150 | FcCharLeaf *leaf, | |||
| 151 | int pos) | |||
| 152 | { | |||
| 153 | intptr_t *leaves = FcCharSetLeaves (fcs)((intptr_t *) ((intptr_t) (fcs) + ((fcs)->leaves_offset))); | |||
| 154 | FcChar16 *numbers = FcCharSetNumbers (fcs)((FcChar16 *) ((intptr_t) (fcs) + ((fcs)->numbers_offset)) ); | |||
| 155 | ||||
| 156 | ucs4 >>= 8; | |||
| 157 | if (ucs4 >= 0x10000) | |||
| 158 | return FcFalse0; | |||
| 159 | ||||
| 160 | if (FC_IS_ZERO_OR_POWER_OF_TWO (fcs->num)(!((fcs->num) & ((fcs->num)-1)))) | |||
| 161 | { | |||
| 162 | if (!fcs->num) | |||
| 163 | { | |||
| 164 | unsigned int alloced = 8; | |||
| 165 | leaves = malloc (alloced * sizeof (*leaves)); | |||
| 166 | numbers = malloc (alloced * sizeof (*numbers)); | |||
| 167 | if (!leaves || !numbers) | |||
| 168 | { | |||
| 169 | if (leaves) | |||
| 170 | free (leaves); | |||
| 171 | if (numbers) | |||
| 172 | free (numbers); | |||
| 173 | return FcFalse0; | |||
| 174 | } | |||
| 175 | } | |||
| 176 | else | |||
| 177 | { | |||
| 178 | unsigned int alloced = fcs->num; | |||
| 179 | intptr_t *new_leaves, distance; | |||
| 180 | ||||
| 181 | alloced *= 2; | |||
| 182 | new_leaves = realloc (leaves, alloced * sizeof (*leaves)); | |||
| 183 | if (!new_leaves) | |||
| 184 | return FcFalse0; | |||
| 185 | numbers = realloc (numbers, alloced * sizeof (*numbers)); | |||
| 186 | if (!numbers) | |||
| 187 | { | |||
| 188 | /* Revert the reallocation of leaves */ | |||
| 189 | leaves = realloc (new_leaves, (alloced / 2) * sizeof (*new_leaves)); | |||
| 190 | /* unlikely to fail though */ | |||
| 191 | if (!leaves) | |||
| 192 | return FcFalse0; | |||
| 193 | fcs->leaves_offset = FcPtrToOffset (fcs, leaves)((intptr_t) (leaves) - (intptr_t) (fcs)); | |||
| 194 | return FcFalse0; | |||
| 195 | } | |||
| 196 | distance = (intptr_t) new_leaves - (intptr_t) leaves; | |||
| 197 | if (new_leaves && distance) | |||
| 198 | { | |||
| 199 | int i; | |||
| 200 | for (i = 0; i < fcs->num; i++) | |||
| 201 | new_leaves[i] -= distance; | |||
| 202 | } | |||
| 203 | leaves = new_leaves; | |||
| 204 | } | |||
| 205 | ||||
| 206 | fcs->leaves_offset = FcPtrToOffset (fcs, leaves)((intptr_t) (leaves) - (intptr_t) (fcs)); | |||
| 207 | fcs->numbers_offset = FcPtrToOffset (fcs, numbers)((intptr_t) (numbers) - (intptr_t) (fcs)); | |||
| 208 | } | |||
| 209 | ||||
| 210 | memmove (leaves + pos + 1, leaves + pos,__builtin___memmove_chk (leaves + pos + 1, leaves + pos, (fcs ->num - pos) * sizeof (*leaves), __builtin_object_size (leaves + pos + 1, 0)) | |||
| 211 | (fcs->num - pos) * sizeof (*leaves))__builtin___memmove_chk (leaves + pos + 1, leaves + pos, (fcs ->num - pos) * sizeof (*leaves), __builtin_object_size (leaves + pos + 1, 0)); | |||
| 212 | memmove (numbers + pos + 1, numbers + pos,__builtin___memmove_chk (numbers + pos + 1, numbers + pos, (fcs ->num - pos) * sizeof (*numbers), __builtin_object_size (numbers + pos + 1, 0)) | |||
| 213 | (fcs->num - pos) * sizeof (*numbers))__builtin___memmove_chk (numbers + pos + 1, numbers + pos, (fcs ->num - pos) * sizeof (*numbers), __builtin_object_size (numbers + pos + 1, 0)); | |||
| 214 | numbers[pos] = (FcChar16) ucs4; | |||
| 215 | leaves[pos] = FcPtrToOffset (leaves, leaf)((intptr_t) (leaf) - (intptr_t) (leaves)); | |||
| 216 | fcs->num++; | |||
| ||||
| 217 | return FcTrue1; | |||
| 218 | } | |||
| 219 | ||||
| 220 | /* | |||
| 221 | * Locate the leaf containing the specified char, creating it | |||
| 222 | * if desired | |||
| 223 | */ | |||
| 224 | ||||
| 225 | FcCharLeaf * | |||
| 226 | FcCharSetFindLeafCreate (FcCharSet *fcs, FcChar32 ucs4) | |||
| 227 | { | |||
| 228 | int pos; | |||
| 229 | FcCharLeaf *leaf; | |||
| 230 | ||||
| 231 | pos = FcCharSetFindLeafPos (fcs, ucs4); | |||
| 232 | if (pos >= 0) | |||
| 233 | return FcCharSetLeaf(fcs, pos)(((FcCharLeaf *) ((intptr_t) (((intptr_t *) ((intptr_t) (fcs) + ((fcs)->leaves_offset)))) + (((intptr_t *) ((intptr_t) ( fcs) + ((fcs)->leaves_offset)))[pos])))); | |||
| 234 | ||||
| 235 | leaf = calloc (1, sizeof (FcCharLeaf)); | |||
| 236 | if (!leaf) | |||
| 237 | return 0; | |||
| 238 | ||||
| 239 | pos = -pos - 1; | |||
| 240 | if (!FcCharSetPutLeaf (fcs, ucs4, leaf, pos)) | |||
| 241 | { | |||
| 242 | free (leaf); | |||
| 243 | return 0; | |||
| 244 | } | |||
| 245 | return leaf; | |||
| 246 | } | |||
| 247 | ||||
| 248 | static FcBool | |||
| 249 | FcCharSetInsertLeaf (FcCharSet *fcs, FcChar32 ucs4, FcCharLeaf *leaf) | |||
| 250 | { | |||
| 251 | int pos; | |||
| 252 | ||||
| 253 | pos = FcCharSetFindLeafPos (fcs, ucs4); | |||
| 254 | if (pos >= 0) | |||
| 255 | { | |||
| 256 | free (FcCharSetLeaf (fcs, pos)(((FcCharLeaf *) ((intptr_t) (((intptr_t *) ((intptr_t) (fcs) + ((fcs)->leaves_offset)))) + (((intptr_t *) ((intptr_t) ( fcs) + ((fcs)->leaves_offset)))[pos]))))); | |||
| 257 | FcCharSetLeaves(fcs)((intptr_t *) ((intptr_t) (fcs) + ((fcs)->leaves_offset)))[pos] = FcPtrToOffset (FcCharSetLeaves(fcs),((intptr_t) (leaf) - (intptr_t) (((intptr_t *) ((intptr_t) (fcs ) + ((fcs)->leaves_offset))))) | |||
| 258 | leaf)((intptr_t) (leaf) - (intptr_t) (((intptr_t *) ((intptr_t) (fcs ) + ((fcs)->leaves_offset))))); | |||
| 259 | return FcTrue1; | |||
| 260 | } | |||
| 261 | pos = -pos - 1; | |||
| 262 | return FcCharSetPutLeaf (fcs, ucs4, leaf, pos); | |||
| 263 | } | |||
| 264 | ||||
| 265 | FcBool | |||
| 266 | FcCharSetAddChar (FcCharSet *fcs, FcChar32 ucs4) | |||
| 267 | { | |||
| 268 | FcCharLeaf *leaf; | |||
| 269 | FcChar32 *b; | |||
| 270 | ||||
| 271 | if (fcs == NULL((void*)0) || FcRefIsConst (&fcs->ref)) | |||
| 272 | return FcFalse0; | |||
| 273 | leaf = FcCharSetFindLeafCreate (fcs, ucs4); | |||
| 274 | if (!leaf) | |||
| 275 | return FcFalse0; | |||
| 276 | b = &leaf->map[(ucs4 & 0xff) >> 5]; | |||
| 277 | *b |= (1 << (ucs4 & 0x1f)); | |||
| 278 | return FcTrue1; | |||
| 279 | } | |||
| 280 | ||||
| 281 | FcBool | |||
| 282 | FcCharSetDelChar (FcCharSet *fcs, FcChar32 ucs4) | |||
| 283 | { | |||
| 284 | FcCharLeaf *leaf; | |||
| 285 | FcChar32 *b; | |||
| 286 | ||||
| 287 | if (fcs == NULL((void*)0) || FcRefIsConst (&fcs->ref)) | |||
| 288 | return FcFalse0; | |||
| 289 | leaf = FcCharSetFindLeaf (fcs, ucs4); | |||
| 290 | if (!leaf) | |||
| 291 | return FcTrue1; | |||
| 292 | b = &leaf->map[(ucs4 & 0xff) >> 5]; | |||
| 293 | *b &= ~(1 << (ucs4 & 0x1f)); | |||
| 294 | /* We don't bother removing the leaf if it's empty */ | |||
| 295 | return FcTrue1; | |||
| 296 | } | |||
| 297 | ||||
| 298 | /* | |||
| 299 | * An iterator for the leaves of a charset | |||
| 300 | */ | |||
| 301 | ||||
| 302 | typedef struct _fcCharSetIter { | |||
| 303 | FcCharLeaf *leaf; | |||
| 304 | FcChar32 ucs4; | |||
| 305 | int pos; | |||
| 306 | } FcCharSetIter; | |||
| 307 | ||||
| 308 | /* | |||
| 309 | * Set iter->leaf to the leaf containing iter->ucs4 or higher | |||
| 310 | */ | |||
| 311 | ||||
| 312 | static void | |||
| 313 | FcCharSetIterSet (const FcCharSet *fcs, FcCharSetIter *iter) | |||
| 314 | { | |||
| 315 | int pos = FcCharSetFindLeafPos (fcs, iter->ucs4); | |||
| 316 | ||||
| 317 | if (pos < 0) | |||
| 318 | { | |||
| 319 | pos = -pos - 1; | |||
| 320 | if (pos == fcs->num) | |||
| 321 | { | |||
| 322 | iter->ucs4 = ~0; | |||
| 323 | iter->leaf = 0; | |||
| 324 | return; | |||
| 325 | } | |||
| 326 | iter->ucs4 = (FcChar32) FcCharSetNumbers(fcs)((FcChar16 *) ((intptr_t) (fcs) + ((fcs)->numbers_offset)) )[pos] << 8; | |||
| 327 | } | |||
| 328 | iter->leaf = FcCharSetLeaf(fcs, pos)(((FcCharLeaf *) ((intptr_t) (((intptr_t *) ((intptr_t) (fcs) + ((fcs)->leaves_offset)))) + (((intptr_t *) ((intptr_t) ( fcs) + ((fcs)->leaves_offset)))[pos])))); | |||
| 329 | iter->pos = pos; | |||
| 330 | } | |||
| 331 | ||||
| 332 | static void | |||
| 333 | FcCharSetIterNext (const FcCharSet *fcs, FcCharSetIter *iter) | |||
| 334 | { | |||
| 335 | int pos = iter->pos + 1; | |||
| 336 | if (pos >= fcs->num) | |||
| 337 | { | |||
| 338 | iter->ucs4 = ~0; | |||
| 339 | iter->leaf = 0; | |||
| 340 | } | |||
| 341 | else | |||
| 342 | { | |||
| 343 | iter->ucs4 = (FcChar32) FcCharSetNumbers(fcs)((FcChar16 *) ((intptr_t) (fcs) + ((fcs)->numbers_offset)) )[pos] << 8; | |||
| 344 | iter->leaf = FcCharSetLeaf(fcs, pos)(((FcCharLeaf *) ((intptr_t) (((intptr_t *) ((intptr_t) (fcs) + ((fcs)->leaves_offset)))) + (((intptr_t *) ((intptr_t) ( fcs) + ((fcs)->leaves_offset)))[pos])))); | |||
| 345 | iter->pos = pos; | |||
| 346 | } | |||
| 347 | } | |||
| 348 | ||||
| 349 | ||||
| 350 | static void | |||
| 351 | FcCharSetIterStart (const FcCharSet *fcs, FcCharSetIter *iter) | |||
| 352 | { | |||
| 353 | iter->ucs4 = 0; | |||
| 354 | iter->pos = 0; | |||
| 355 | FcCharSetIterSet (fcs, iter); | |||
| 356 | } | |||
| 357 | ||||
| 358 | FcCharSet * | |||
| 359 | FcCharSetCopy (FcCharSet *src) | |||
| 360 | { | |||
| 361 | if (src) | |||
| 362 | { | |||
| 363 | if (!FcRefIsConst (&src->ref)) | |||
| 364 | FcRefInc (&src->ref); | |||
| 365 | else | |||
| 366 | FcCacheObjectReference (src); | |||
| 367 | } | |||
| 368 | return src; | |||
| 369 | } | |||
| 370 | ||||
| 371 | FcBool | |||
| 372 | FcCharSetEqual (const FcCharSet *a, const FcCharSet *b) | |||
| 373 | { | |||
| 374 | FcCharSetIter ai, bi; | |||
| 375 | int i; | |||
| 376 | ||||
| 377 | if (a == b) | |||
| 378 | return FcTrue1; | |||
| 379 | if (!a || !b) | |||
| 380 | return FcFalse0; | |||
| 381 | for (FcCharSetIterStart (a, &ai), FcCharSetIterStart (b, &bi); | |||
| 382 | ai.leaf && bi.leaf; | |||
| 383 | FcCharSetIterNext (a, &ai), FcCharSetIterNext (b, &bi)) | |||
| 384 | { | |||
| 385 | if (ai.ucs4 != bi.ucs4) | |||
| 386 | return FcFalse0; | |||
| 387 | for (i = 0; i < 256/32; i++) | |||
| 388 | if (ai.leaf->map[i] != bi.leaf->map[i]) | |||
| 389 | return FcFalse0; | |||
| 390 | } | |||
| 391 | return ai.leaf == bi.leaf; | |||
| 392 | } | |||
| 393 | ||||
| 394 | static FcBool | |||
| 395 | FcCharSetAddLeaf (FcCharSet *fcs, | |||
| 396 | FcChar32 ucs4, | |||
| 397 | FcCharLeaf *leaf) | |||
| 398 | { | |||
| 399 | FcCharLeaf *new = FcCharSetFindLeafCreate (fcs, ucs4); | |||
| 400 | if (!new) | |||
| 401 | return FcFalse0; | |||
| 402 | *new = *leaf; | |||
| 403 | return FcTrue1; | |||
| 404 | } | |||
| 405 | ||||
| 406 | static FcCharSet * | |||
| 407 | FcCharSetOperate (const FcCharSet *a, | |||
| 408 | const FcCharSet *b, | |||
| 409 | FcBool (*overlap) (FcCharLeaf *result, | |||
| 410 | const FcCharLeaf *al, | |||
| 411 | const FcCharLeaf *bl), | |||
| 412 | FcBool aonly, | |||
| 413 | FcBool bonly) | |||
| 414 | { | |||
| 415 | FcCharSet *fcs; | |||
| 416 | FcCharSetIter ai, bi; | |||
| 417 | ||||
| 418 | if (!a || !b) | |||
| 419 | goto bail0; | |||
| 420 | fcs = FcCharSetCreate (); | |||
| 421 | if (!fcs) | |||
| 422 | goto bail0; | |||
| 423 | FcCharSetIterStart (a, &ai); | |||
| 424 | FcCharSetIterStart (b, &bi); | |||
| 425 | while ((ai.leaf || (bonly && bi.leaf)) && (bi.leaf || (aonly && ai.leaf))) | |||
| 426 | { | |||
| 427 | if (ai.ucs4 < bi.ucs4) | |||
| 428 | { | |||
| 429 | if (aonly) | |||
| 430 | { | |||
| 431 | if (!FcCharSetAddLeaf (fcs, ai.ucs4, ai.leaf)) | |||
| 432 | goto bail1; | |||
| 433 | FcCharSetIterNext (a, &ai); | |||
| 434 | } | |||
| 435 | else | |||
| 436 | { | |||
| 437 | ai.ucs4 = bi.ucs4; | |||
| 438 | FcCharSetIterSet (a, &ai); | |||
| 439 | } | |||
| 440 | } | |||
| 441 | else if (bi.ucs4 < ai.ucs4 ) | |||
| 442 | { | |||
| 443 | if (bonly) | |||
| 444 | { | |||
| 445 | if (!FcCharSetAddLeaf (fcs, bi.ucs4, bi.leaf)) | |||
| 446 | goto bail1; | |||
| 447 | FcCharSetIterNext (b, &bi); | |||
| 448 | } | |||
| 449 | else | |||
| 450 | { | |||
| 451 | bi.ucs4 = ai.ucs4; | |||
| 452 | FcCharSetIterSet (b, &bi); | |||
| 453 | } | |||
| 454 | } | |||
| 455 | else | |||
| 456 | { | |||
| 457 | FcCharLeaf leaf; | |||
| 458 | ||||
| 459 | if ((*overlap) (&leaf, ai.leaf, bi.leaf)) | |||
| 460 | { | |||
| 461 | if (!FcCharSetAddLeaf (fcs, ai.ucs4, &leaf)) | |||
| 462 | goto bail1; | |||
| 463 | } | |||
| 464 | FcCharSetIterNext (a, &ai); | |||
| 465 | FcCharSetIterNext (b, &bi); | |||
| 466 | } | |||
| 467 | } | |||
| 468 | return fcs; | |||
| 469 | bail1: | |||
| 470 | FcCharSetDestroy (fcs); | |||
| 471 | bail0: | |||
| 472 | return 0; | |||
| 473 | } | |||
| 474 | ||||
| 475 | static FcBool | |||
| 476 | FcCharSetIntersectLeaf (FcCharLeaf *result, | |||
| 477 | const FcCharLeaf *al, | |||
| 478 | const FcCharLeaf *bl) | |||
| 479 | { | |||
| 480 | int i; | |||
| 481 | FcBool nonempty = FcFalse0; | |||
| 482 | ||||
| 483 | for (i = 0; i < 256/32; i++) | |||
| 484 | if ((result->map[i] = al->map[i] & bl->map[i])) | |||
| 485 | nonempty = FcTrue1; | |||
| 486 | return nonempty; | |||
| 487 | } | |||
| 488 | ||||
| 489 | FcCharSet * | |||
| 490 | FcCharSetIntersect (const FcCharSet *a, const FcCharSet *b) | |||
| 491 | { | |||
| 492 | return FcCharSetOperate (a, b, FcCharSetIntersectLeaf, FcFalse0, FcFalse0); | |||
| 493 | } | |||
| 494 | ||||
| 495 | static FcBool | |||
| 496 | FcCharSetUnionLeaf (FcCharLeaf *result, | |||
| 497 | const FcCharLeaf *al, | |||
| 498 | const FcCharLeaf *bl) | |||
| 499 | { | |||
| 500 | int i; | |||
| 501 | ||||
| 502 | for (i = 0; i < 256/32; i++) | |||
| 503 | result->map[i] = al->map[i] | bl->map[i]; | |||
| 504 | return FcTrue1; | |||
| 505 | } | |||
| 506 | ||||
| 507 | FcCharSet * | |||
| 508 | FcCharSetUnion (const FcCharSet *a, const FcCharSet *b) | |||
| 509 | { | |||
| 510 | return FcCharSetOperate (a, b, FcCharSetUnionLeaf, FcTrue1, FcTrue1); | |||
| 511 | } | |||
| 512 | ||||
| 513 | FcBool | |||
| 514 | FcCharSetMerge (FcCharSet *a, const FcCharSet *b, FcBool *changed) | |||
| 515 | { | |||
| 516 | int ai = 0, bi = 0; | |||
| 517 | FcChar16 an, bn; | |||
| 518 | ||||
| 519 | if (!a || !b) | |||
| 520 | return FcFalse0; | |||
| 521 | ||||
| 522 | if (FcRefIsConst (&a->ref)) { | |||
| 523 | if (changed) | |||
| 524 | *changed = FcFalse0; | |||
| 525 | return FcFalse0; | |||
| 526 | } | |||
| 527 | ||||
| 528 | if (changed) { | |||
| 529 | *changed = !FcCharSetIsSubset(b, a); | |||
| 530 | if (!*changed) | |||
| 531 | return FcTrue1; | |||
| 532 | } | |||
| 533 | ||||
| 534 | while (bi < b->num) | |||
| 535 | { | |||
| 536 | an = ai < a->num ? FcCharSetNumbers(a)((FcChar16 *) ((intptr_t) (a) + ((a)->numbers_offset)))[ai] : ~0; | |||
| 537 | bn = FcCharSetNumbers(b)((FcChar16 *) ((intptr_t) (b) + ((b)->numbers_offset)))[bi]; | |||
| 538 | ||||
| 539 | if (an < bn) | |||
| 540 | { | |||
| 541 | ai = FcCharSetFindLeafForward (a, ai + 1, bn); | |||
| 542 | if (ai < 0) | |||
| 543 | ai = -ai - 1; | |||
| 544 | } | |||
| 545 | else | |||
| 546 | { | |||
| 547 | FcCharLeaf *bl = FcCharSetLeaf(b, bi)(((FcCharLeaf *) ((intptr_t) (((intptr_t *) ((intptr_t) (b) + ((b)->leaves_offset)))) + (((intptr_t *) ((intptr_t) (b) + ((b)->leaves_offset)))[bi])))); | |||
| 548 | if (bn < an) | |||
| 549 | { | |||
| 550 | if (!FcCharSetAddLeaf (a, bn << 8, bl)) | |||
| 551 | return FcFalse0; | |||
| 552 | } | |||
| 553 | else | |||
| 554 | { | |||
| 555 | FcCharLeaf *al = FcCharSetLeaf(a, ai)(((FcCharLeaf *) ((intptr_t) (((intptr_t *) ((intptr_t) (a) + ((a)->leaves_offset)))) + (((intptr_t *) ((intptr_t) (a) + ((a)->leaves_offset)))[ai])))); | |||
| 556 | FcCharSetUnionLeaf (al, al, bl); | |||
| 557 | } | |||
| 558 | ||||
| 559 | ai++; | |||
| 560 | bi++; | |||
| 561 | } | |||
| 562 | } | |||
| 563 | ||||
| 564 | return FcTrue1; | |||
| 565 | } | |||
| 566 | ||||
| 567 | static FcBool | |||
| 568 | FcCharSetSubtractLeaf (FcCharLeaf *result, | |||
| 569 | const FcCharLeaf *al, | |||
| 570 | const FcCharLeaf *bl) | |||
| 571 | { | |||
| 572 | int i; | |||
| 573 | FcBool nonempty = FcFalse0; | |||
| 574 | ||||
| 575 | for (i = 0; i < 256/32; i++) | |||
| 576 | if ((result->map[i] = al->map[i] & ~bl->map[i])) | |||
| 577 | nonempty = FcTrue1; | |||
| 578 | return nonempty; | |||
| 579 | } | |||
| 580 | ||||
| 581 | FcCharSet * | |||
| 582 | FcCharSetSubtract (const FcCharSet *a, const FcCharSet *b) | |||
| 583 | { | |||
| 584 | return FcCharSetOperate (a, b, FcCharSetSubtractLeaf, FcTrue1, FcFalse0); | |||
| 585 | } | |||
| 586 | ||||
| 587 | FcBool | |||
| 588 | FcCharSetHasChar (const FcCharSet *fcs, FcChar32 ucs4) | |||
| 589 | { | |||
| 590 | FcCharLeaf *leaf; | |||
| 591 | ||||
| 592 | if (!fcs) | |||
| 593 | return FcFalse0; | |||
| 594 | leaf = FcCharSetFindLeaf (fcs, ucs4); | |||
| 595 | if (!leaf) | |||
| 596 | return FcFalse0; | |||
| 597 | return (leaf->map[(ucs4 & 0xff) >> 5] & (1 << (ucs4 & 0x1f))) != 0; | |||
| 598 | } | |||
| 599 | ||||
| 600 | static FcChar32 | |||
| 601 | FcCharSetPopCount (FcChar32 c1) | |||
| 602 | { | |||
| 603 | #if __GNUC__4 > 3 || (__GNUC__4 == 3 && __GNUC_MINOR__2 >= 4) | |||
| 604 | return __builtin_popcount (c1); | |||
| 605 | #else | |||
| 606 | /* hackmem 169 */ | |||
| 607 | FcChar32 c2 = (c1 >> 1) & 033333333333; | |||
| 608 | c2 = c1 - c2 - ((c2 >> 1) & 033333333333); | |||
| 609 | return (((c2 + (c2 >> 3)) & 030707070707) % 077); | |||
| 610 | #endif | |||
| 611 | } | |||
| 612 | ||||
| 613 | FcChar32 | |||
| 614 | FcCharSetIntersectCount (const FcCharSet *a, const FcCharSet *b) | |||
| 615 | { | |||
| 616 | FcCharSetIter ai, bi; | |||
| 617 | FcChar32 count = 0; | |||
| 618 | ||||
| 619 | if (a && b) | |||
| 620 | { | |||
| 621 | FcCharSetIterStart (a, &ai); | |||
| 622 | FcCharSetIterStart (b, &bi); | |||
| 623 | while (ai.leaf && bi.leaf) | |||
| 624 | { | |||
| 625 | if (ai.ucs4 == bi.ucs4) | |||
| 626 | { | |||
| 627 | FcChar32 *am = ai.leaf->map; | |||
| 628 | FcChar32 *bm = bi.leaf->map; | |||
| 629 | int i = 256/32; | |||
| 630 | while (i--) | |||
| 631 | count += FcCharSetPopCount (*am++ & *bm++); | |||
| 632 | FcCharSetIterNext (a, &ai); | |||
| 633 | } | |||
| 634 | else if (ai.ucs4 < bi.ucs4) | |||
| 635 | { | |||
| 636 | ai.ucs4 = bi.ucs4; | |||
| 637 | FcCharSetIterSet (a, &ai); | |||
| 638 | } | |||
| 639 | if (bi.ucs4 < ai.ucs4) | |||
| 640 | { | |||
| 641 | bi.ucs4 = ai.ucs4; | |||
| 642 | FcCharSetIterSet (b, &bi); | |||
| 643 | } | |||
| 644 | } | |||
| 645 | } | |||
| 646 | return count; | |||
| 647 | } | |||
| 648 | ||||
| 649 | FcChar32 | |||
| 650 | FcCharSetCount (const FcCharSet *a) | |||
| 651 | { | |||
| 652 | FcCharSetIter ai; | |||
| 653 | FcChar32 count = 0; | |||
| 654 | ||||
| 655 | if (a) | |||
| 656 | { | |||
| 657 | for (FcCharSetIterStart (a, &ai); ai.leaf; FcCharSetIterNext (a, &ai)) | |||
| 658 | { | |||
| 659 | int i = 256/32; | |||
| 660 | FcChar32 *am = ai.leaf->map; | |||
| 661 | ||||
| 662 | while (i--) | |||
| 663 | count += FcCharSetPopCount (*am++); | |||
| 664 | } | |||
| 665 | } | |||
| 666 | return count; | |||
| 667 | } | |||
| 668 | ||||
| 669 | FcChar32 | |||
| 670 | FcCharSetSubtractCount (const FcCharSet *a, const FcCharSet *b) | |||
| 671 | { | |||
| 672 | FcCharSetIter ai, bi; | |||
| 673 | FcChar32 count = 0; | |||
| 674 | ||||
| 675 | if (a && b) | |||
| 676 | { | |||
| 677 | FcCharSetIterStart (a, &ai); | |||
| 678 | FcCharSetIterStart (b, &bi); | |||
| 679 | while (ai.leaf) | |||
| 680 | { | |||
| 681 | if (ai.ucs4 <= bi.ucs4) | |||
| 682 | { | |||
| 683 | FcChar32 *am = ai.leaf->map; | |||
| 684 | int i = 256/32; | |||
| 685 | if (ai.ucs4 == bi.ucs4) | |||
| 686 | { | |||
| 687 | FcChar32 *bm = bi.leaf->map; | |||
| 688 | while (i--) | |||
| 689 | count += FcCharSetPopCount (*am++ & ~*bm++); | |||
| 690 | } | |||
| 691 | else | |||
| 692 | { | |||
| 693 | while (i--) | |||
| 694 | count += FcCharSetPopCount (*am++); | |||
| 695 | } | |||
| 696 | FcCharSetIterNext (a, &ai); | |||
| 697 | } | |||
| 698 | else if (bi.leaf) | |||
| 699 | { | |||
| 700 | bi.ucs4 = ai.ucs4; | |||
| 701 | FcCharSetIterSet (b, &bi); | |||
| 702 | } | |||
| 703 | } | |||
| 704 | } | |||
| 705 | return count; | |||
| 706 | } | |||
| 707 | ||||
| 708 | /* | |||
| 709 | * return FcTrue iff a is a subset of b | |||
| 710 | */ | |||
| 711 | FcBool | |||
| 712 | FcCharSetIsSubset (const FcCharSet *a, const FcCharSet *b) | |||
| 713 | { | |||
| 714 | int ai, bi; | |||
| 715 | FcChar16 an, bn; | |||
| 716 | ||||
| 717 | if (a == b) | |||
| 718 | return FcTrue1; | |||
| 719 | if (!a || !b) | |||
| 720 | return FcFalse0; | |||
| 721 | bi = 0; | |||
| 722 | ai = 0; | |||
| 723 | while (ai < a->num && bi < b->num) | |||
| 724 | { | |||
| 725 | an = FcCharSetNumbers(a)((FcChar16 *) ((intptr_t) (a) + ((a)->numbers_offset)))[ai]; | |||
| 726 | bn = FcCharSetNumbers(b)((FcChar16 *) ((intptr_t) (b) + ((b)->numbers_offset)))[bi]; | |||
| 727 | /* | |||
| 728 | * Check matching pages | |||
| 729 | */ | |||
| 730 | if (an == bn) | |||
| 731 | { | |||
| 732 | FcChar32 *am = FcCharSetLeaf(a, ai)(((FcCharLeaf *) ((intptr_t) (((intptr_t *) ((intptr_t) (a) + ((a)->leaves_offset)))) + (((intptr_t *) ((intptr_t) (a) + ((a)->leaves_offset)))[ai]))))->map; | |||
| 733 | FcChar32 *bm = FcCharSetLeaf(b, bi)(((FcCharLeaf *) ((intptr_t) (((intptr_t *) ((intptr_t) (b) + ((b)->leaves_offset)))) + (((intptr_t *) ((intptr_t) (b) + ((b)->leaves_offset)))[bi]))))->map; | |||
| 734 | ||||
| 735 | if (am != bm) | |||
| 736 | { | |||
| 737 | int i = 256/32; | |||
| 738 | /* | |||
| 739 | * Does am have any bits not in bm? | |||
| 740 | */ | |||
| 741 | while (i--) | |||
| 742 | if (*am++ & ~*bm++) | |||
| 743 | return FcFalse0; | |||
| 744 | } | |||
| 745 | ai++; | |||
| 746 | bi++; | |||
| 747 | } | |||
| 748 | /* | |||
| 749 | * Does a have any pages not in b? | |||
| 750 | */ | |||
| 751 | else if (an < bn) | |||
| 752 | return FcFalse0; | |||
| 753 | else | |||
| 754 | { | |||
| 755 | bi = FcCharSetFindLeafForward (b, bi + 1, an); | |||
| 756 | if (bi < 0) | |||
| 757 | bi = -bi - 1; | |||
| 758 | } | |||
| 759 | } | |||
| 760 | /* | |||
| 761 | * did we look at every page? | |||
| 762 | */ | |||
| 763 | return ai >= a->num; | |||
| 764 | } | |||
| 765 | ||||
| 766 | /* | |||
| 767 | * These two functions efficiently walk the entire charmap for | |||
| 768 | * other software (like pango) that want their own copy | |||
| 769 | */ | |||
| 770 | ||||
| 771 | FcChar32 | |||
| 772 | FcCharSetNextPage (const FcCharSet *a, | |||
| 773 | FcChar32 map[FC_CHARSET_MAP_SIZE(256/32)], | |||
| 774 | FcChar32 *next) | |||
| 775 | { | |||
| 776 | FcCharSetIter ai; | |||
| 777 | FcChar32 page; | |||
| 778 | ||||
| 779 | if (!a) | |||
| 780 | return FC_CHARSET_DONE((FcChar32) -1); | |||
| 781 | ai.ucs4 = *next; | |||
| 782 | FcCharSetIterSet (a, &ai); | |||
| 783 | if (!ai.leaf) | |||
| 784 | return FC_CHARSET_DONE((FcChar32) -1); | |||
| 785 | ||||
| 786 | /* | |||
| 787 | * Save current information | |||
| 788 | */ | |||
| 789 | page = ai.ucs4; | |||
| 790 | memcpy (map, ai.leaf->map, sizeof (ai.leaf->map))__builtin___memcpy_chk (map, ai.leaf->map, sizeof (ai.leaf ->map), __builtin_object_size (map, 0)); | |||
| 791 | /* | |||
| 792 | * Step to next page | |||
| 793 | */ | |||
| 794 | FcCharSetIterNext (a, &ai); | |||
| 795 | *next = ai.ucs4; | |||
| 796 | ||||
| 797 | return page; | |||
| 798 | } | |||
| 799 | ||||
| 800 | FcChar32 | |||
| 801 | FcCharSetFirstPage (const FcCharSet *a, | |||
| 802 | FcChar32 map[FC_CHARSET_MAP_SIZE(256/32)], | |||
| 803 | FcChar32 *next) | |||
| 804 | { | |||
| 805 | *next = 0; | |||
| 806 | return FcCharSetNextPage (a, map, next); | |||
| 807 | } | |||
| 808 | ||||
| 809 | /* | |||
| 810 | * old coverage API, rather hard to use correctly | |||
| 811 | */ | |||
| 812 | ||||
| 813 | FcChar32 | |||
| 814 | FcCharSetCoverage (const FcCharSet *a, FcChar32 page, FcChar32 *result) | |||
| 815 | { | |||
| 816 | FcCharSetIter ai; | |||
| 817 | ||||
| 818 | ai.ucs4 = page; | |||
| 819 | FcCharSetIterSet (a, &ai); | |||
| 820 | if (!ai.leaf) | |||
| 821 | { | |||
| 822 | memset (result, '\0', 256 / 8)__builtin___memset_chk (result, '\0', 256 / 8, __builtin_object_size (result, 0)); | |||
| 823 | page = 0; | |||
| 824 | } | |||
| 825 | else | |||
| 826 | { | |||
| 827 | memcpy (result, ai.leaf->map, sizeof (ai.leaf->map))__builtin___memcpy_chk (result, ai.leaf->map, sizeof (ai.leaf ->map), __builtin_object_size (result, 0)); | |||
| 828 | FcCharSetIterNext (a, &ai); | |||
| 829 | page = ai.ucs4; | |||
| 830 | } | |||
| 831 | return page; | |||
| 832 | } | |||
| 833 | ||||
| 834 | static FcBool | |||
| 835 | FcNameParseRange (FcChar8 **string, FcChar32 *pfirst, FcChar32 *plast) | |||
| 836 | { | |||
| 837 | char *s = (char *) *string; | |||
| 838 | char *t; | |||
| 839 | long first, last; | |||
| 840 | ||||
| 841 | while (isspace(*s)) | |||
| 842 | s++; | |||
| 843 | t = s; | |||
| 844 | errno(*__error()) = 0; | |||
| 845 | first = last = strtol (s, &s, 16); | |||
| 846 | if (errno(*__error())) | |||
| 847 | return FcFalse0; | |||
| 848 | while (isspace(*s)) | |||
| 849 | s++; | |||
| 850 | if (*s == '-') | |||
| 851 | { | |||
| 852 | s++; | |||
| 853 | errno(*__error()) = 0; | |||
| 854 | last = strtol (s, &s, 16); | |||
| 855 | if (errno(*__error())) | |||
| 856 | return FcFalse0; | |||
| 857 | } | |||
| 858 | ||||
| 859 | if (s == t || first < 0 || last < 0 || last < first || last > 0x10ffff) | |||
| 860 | return FcFalse0; | |||
| 861 | ||||
| 862 | *string = (FcChar8 *) s; | |||
| 863 | *pfirst = first; | |||
| 864 | *plast = last; | |||
| 865 | return FcTrue1; | |||
| 866 | } | |||
| 867 | ||||
| 868 | FcCharSet * | |||
| 869 | FcNameParseCharSet (FcChar8 *string) | |||
| 870 | { | |||
| 871 | FcCharSet *c; | |||
| 872 | FcChar32 first, last; | |||
| 873 | ||||
| 874 | c = FcCharSetCreate (); | |||
| 875 | if (!c) | |||
| 876 | goto bail0; | |||
| 877 | while (*string) | |||
| 878 | { | |||
| 879 | FcChar32 u; | |||
| 880 | ||||
| 881 | if (!FcNameParseRange (&string, &first, &last)) | |||
| 882 | goto bail1; | |||
| 883 | ||||
| 884 | for (u = first; u < last + 1; u++) | |||
| 885 | FcCharSetAddChar (c, u); | |||
| 886 | } | |||
| 887 | return c; | |||
| 888 | bail1: | |||
| 889 | FcCharSetDestroy (c); | |||
| 890 | bail0: | |||
| 891 | return NULL((void*)0); | |||
| 892 | } | |||
| 893 | ||||
| 894 | static void | |||
| 895 | FcNameUnparseUnicode (FcStrBuf *buf, FcChar32 u) | |||
| 896 | { | |||
| 897 | FcChar8 buf_static[64]; | |||
| 898 | snprintf ((char *) buf_static, sizeof (buf_static), "%x", u)__builtin___snprintf_chk ((char *) buf_static, sizeof (buf_static ), 0, __builtin_object_size ((char *) buf_static, 2 > 1 ? 1 : 0), "%x", u); | |||
| 899 | FcStrBufString (buf, buf_static); | |||
| 900 | } | |||
| 901 | ||||
| 902 | FcBool | |||
| 903 | FcNameUnparseCharSet (FcStrBuf *buf, const FcCharSet *c) | |||
| 904 | { | |||
| 905 | FcCharSetIter ci; | |||
| 906 | FcChar32 first, last; | |||
| 907 | int i; | |||
| 908 | #ifdef CHECK | |||
| 909 | int len = buf->len; | |||
| 910 | #endif | |||
| 911 | ||||
| 912 | first = last = 0x7FFFFFFF; | |||
| 913 | ||||
| 914 | for (FcCharSetIterStart (c, &ci); | |||
| 915 | ci.leaf; | |||
| 916 | FcCharSetIterNext (c, &ci)) | |||
| 917 | { | |||
| 918 | for (i = 0; i < 256/32; i++) | |||
| 919 | { | |||
| 920 | FcChar32 bits = ci.leaf->map[i]; | |||
| 921 | FcChar32 u = ci.ucs4 + i * 32; | |||
| 922 | ||||
| 923 | while (bits) | |||
| 924 | { | |||
| 925 | if (bits & 1) | |||
| 926 | { | |||
| 927 | if (u != last + 1) | |||
| 928 | { | |||
| 929 | if (last != first) | |||
| 930 | { | |||
| 931 | FcStrBufChar (buf, '-'); | |||
| 932 | FcNameUnparseUnicode (buf, last); | |||
| 933 | } | |||
| 934 | if (last != 0x7FFFFFFF) | |||
| 935 | FcStrBufChar (buf, ' '); | |||
| 936 | /* Start new range. */ | |||
| 937 | first = u; | |||
| 938 | FcNameUnparseUnicode (buf, u); | |||
| 939 | } | |||
| 940 | last = u; | |||
| 941 | } | |||
| 942 | bits >>= 1; | |||
| 943 | u++; | |||
| 944 | } | |||
| 945 | } | |||
| 946 | } | |||
| 947 | if (last != first) | |||
| 948 | { | |||
| 949 | FcStrBufChar (buf, '-'); | |||
| 950 | FcNameUnparseUnicode (buf, last); | |||
| 951 | } | |||
| 952 | #ifdef CHECK | |||
| 953 | { | |||
| 954 | FcCharSet *check; | |||
| 955 | FcChar32 missing; | |||
| 956 | FcCharSetIter ci, checki; | |||
| 957 | ||||
| 958 | /* null terminate for parser */ | |||
| 959 | FcStrBufChar (buf, '\0'); | |||
| 960 | /* step back over null for life after test */ | |||
| 961 | buf->len--; | |||
| 962 | check = FcNameParseCharSet (buf->buf + len); | |||
| 963 | FcCharSetIterStart (c, &ci); | |||
| 964 | FcCharSetIterStart (check, &checki); | |||
| 965 | while (ci.leaf || checki.leaf) | |||
| 966 | { | |||
| 967 | if (ci.ucs4 < checki.ucs4) | |||
| 968 | { | |||
| 969 | printf ("Missing leaf node at 0x%x\n", ci.ucs4); | |||
| 970 | FcCharSetIterNext (c, &ci); | |||
| 971 | } | |||
| 972 | else if (checki.ucs4 < ci.ucs4) | |||
| 973 | { | |||
| 974 | printf ("Extra leaf node at 0x%x\n", checki.ucs4); | |||
| 975 | FcCharSetIterNext (check, &checki); | |||
| 976 | } | |||
| 977 | else | |||
| 978 | { | |||
| 979 | int i = 256/32; | |||
| 980 | FcChar32 *cm = ci.leaf->map; | |||
| 981 | FcChar32 *checkm = checki.leaf->map; | |||
| 982 | ||||
| 983 | for (i = 0; i < 256; i += 32) | |||
| 984 | { | |||
| 985 | if (*cm != *checkm) | |||
| 986 | printf ("Mismatching sets at 0x%08x: 0x%08x != 0x%08x\n", | |||
| 987 | ci.ucs4 + i, *cm, *checkm); | |||
| 988 | cm++; | |||
| 989 | checkm++; | |||
| 990 | } | |||
| 991 | FcCharSetIterNext (c, &ci); | |||
| 992 | FcCharSetIterNext (check, &checki); | |||
| 993 | } | |||
| 994 | } | |||
| 995 | if ((missing = FcCharSetSubtractCount (c, check))) | |||
| 996 | printf ("%d missing in reparsed result\n", missing); | |||
| 997 | if ((missing = FcCharSetSubtractCount (check, c))) | |||
| 998 | printf ("%d extra in reparsed result\n", missing); | |||
| 999 | FcCharSetDestroy (check); | |||
| 1000 | } | |||
| 1001 | #endif | |||
| 1002 | ||||
| 1003 | return FcTrue1; | |||
| 1004 | } | |||
| 1005 | ||||
| 1006 | typedef struct _FcCharLeafEnt FcCharLeafEnt; | |||
| 1007 | ||||
| 1008 | struct _FcCharLeafEnt { | |||
| 1009 | FcCharLeafEnt *next; | |||
| 1010 | FcChar32 hash; | |||
| 1011 | FcCharLeaf leaf; | |||
| 1012 | }; | |||
| 1013 | ||||
| 1014 | #define FC_CHAR_LEAF_BLOCK(4096 / sizeof (FcCharLeafEnt)) (4096 / sizeof (FcCharLeafEnt)) | |||
| 1015 | #define FC_CHAR_LEAF_HASH_SIZE257 257 | |||
| 1016 | ||||
| 1017 | typedef struct _FcCharSetEnt FcCharSetEnt; | |||
| 1018 | ||||
| 1019 | struct _FcCharSetEnt { | |||
| 1020 | FcCharSetEnt *next; | |||
| 1021 | FcChar32 hash; | |||
| 1022 | FcCharSet set; | |||
| 1023 | }; | |||
| 1024 | ||||
| 1025 | typedef struct _FcCharSetOrigEnt FcCharSetOrigEnt; | |||
| 1026 | ||||
| 1027 | struct _FcCharSetOrigEnt { | |||
| 1028 | FcCharSetOrigEnt *next; | |||
| 1029 | const FcCharSet *orig; | |||
| 1030 | const FcCharSet *frozen; | |||
| 1031 | }; | |||
| 1032 | ||||
| 1033 | #define FC_CHAR_SET_HASH_SIZE67 67 | |||
| 1034 | ||||
| 1035 | struct _FcCharSetFreezer { | |||
| 1036 | FcCharLeafEnt *leaf_hash_table[FC_CHAR_LEAF_HASH_SIZE257]; | |||
| 1037 | FcCharLeafEnt **leaf_blocks; | |||
| 1038 | int leaf_block_count; | |||
| 1039 | FcCharSetEnt *set_hash_table[FC_CHAR_SET_HASH_SIZE67]; | |||
| 1040 | FcCharSetOrigEnt *orig_hash_table[FC_CHAR_SET_HASH_SIZE67]; | |||
| 1041 | FcCharLeafEnt *current_block; | |||
| 1042 | int leaf_remain; | |||
| 1043 | int leaves_seen; | |||
| 1044 | int charsets_seen; | |||
| 1045 | int leaves_allocated; | |||
| 1046 | int charsets_allocated; | |||
| 1047 | }; | |||
| 1048 | ||||
| 1049 | static FcCharLeafEnt * | |||
| 1050 | FcCharLeafEntCreate (FcCharSetFreezer *freezer) | |||
| 1051 | { | |||
| 1052 | if (!freezer->leaf_remain) | |||
| 1053 | { | |||
| 1054 | FcCharLeafEnt **newBlocks; | |||
| 1055 | ||||
| 1056 | freezer->leaf_block_count++; | |||
| 1057 | newBlocks = realloc (freezer->leaf_blocks, freezer->leaf_block_count * sizeof (FcCharLeafEnt *)); | |||
| 1058 | if (!newBlocks) | |||
| 1059 | return 0; | |||
| 1060 | freezer->leaf_blocks = newBlocks; | |||
| 1061 | freezer->current_block = freezer->leaf_blocks[freezer->leaf_block_count-1] = malloc (FC_CHAR_LEAF_BLOCK(4096 / sizeof (FcCharLeafEnt)) * sizeof (FcCharLeafEnt)); | |||
| 1062 | if (!freezer->current_block) | |||
| 1063 | return 0; | |||
| 1064 | freezer->leaf_remain = FC_CHAR_LEAF_BLOCK(4096 / sizeof (FcCharLeafEnt)); | |||
| 1065 | } | |||
| 1066 | freezer->leaf_remain--; | |||
| 1067 | freezer->leaves_allocated++; | |||
| 1068 | return freezer->current_block++; | |||
| 1069 | } | |||
| 1070 | ||||
| 1071 | static FcChar32 | |||
| 1072 | FcCharLeafHash (FcCharLeaf *leaf) | |||
| 1073 | { | |||
| 1074 | FcChar32 hash = 0; | |||
| 1075 | int i; | |||
| 1076 | ||||
| 1077 | for (i = 0; i < 256/32; i++) | |||
| 1078 | hash = ((hash << 1) | (hash >> 31)) ^ leaf->map[i]; | |||
| 1079 | return hash; | |||
| 1080 | } | |||
| 1081 | ||||
| 1082 | static FcCharLeaf * | |||
| 1083 | FcCharSetFreezeLeaf (FcCharSetFreezer *freezer, FcCharLeaf *leaf) | |||
| 1084 | { | |||
| 1085 | FcChar32 hash = FcCharLeafHash (leaf); | |||
| 1086 | FcCharLeafEnt **bucket = &freezer->leaf_hash_table[hash % FC_CHAR_LEAF_HASH_SIZE257]; | |||
| 1087 | FcCharLeafEnt *ent; | |||
| 1088 | ||||
| 1089 | for (ent = *bucket; ent; ent = ent->next) | |||
| 1090 | { | |||
| 1091 | if (ent->hash == hash && !memcmp (&ent->leaf, leaf, sizeof (FcCharLeaf))) | |||
| 1092 | return &ent->leaf; | |||
| 1093 | } | |||
| 1094 | ||||
| 1095 | ent = FcCharLeafEntCreate(freezer); | |||
| 1096 | if (!ent) | |||
| 1097 | return 0; | |||
| 1098 | ent->leaf = *leaf; | |||
| 1099 | ent->hash = hash; | |||
| 1100 | ent->next = *bucket; | |||
| 1101 | *bucket = ent; | |||
| 1102 | return &ent->leaf; | |||
| 1103 | } | |||
| 1104 | ||||
| 1105 | static FcChar32 | |||
| 1106 | FcCharSetHash (FcCharSet *fcs) | |||
| 1107 | { | |||
| 1108 | FcChar32 hash = 0; | |||
| 1109 | int i; | |||
| 1110 | ||||
| 1111 | /* hash in leaves */ | |||
| 1112 | for (i = 0; i < fcs->num; i++) | |||
| 1113 | hash = ((hash << 1) | (hash >> 31)) ^ FcCharLeafHash (FcCharSetLeaf(fcs,i)(((FcCharLeaf *) ((intptr_t) (((intptr_t *) ((intptr_t) (fcs) + ((fcs)->leaves_offset)))) + (((intptr_t *) ((intptr_t) ( fcs) + ((fcs)->leaves_offset)))[i]))))); | |||
| 1114 | /* hash in numbers */ | |||
| 1115 | for (i = 0; i < fcs->num; i++) | |||
| 1116 | hash = ((hash << 1) | (hash >> 31)) ^ *FcCharSetNumbers(fcs)((FcChar16 *) ((intptr_t) (fcs) + ((fcs)->numbers_offset)) ); | |||
| 1117 | return hash; | |||
| 1118 | } | |||
| 1119 | ||||
| 1120 | static FcBool | |||
| 1121 | FcCharSetFreezeOrig (FcCharSetFreezer *freezer, const FcCharSet *orig, const FcCharSet *frozen) | |||
| 1122 | { | |||
| 1123 | FcCharSetOrigEnt **bucket = &freezer->orig_hash_table[((uintptr_t) orig) & FC_CHAR_SET_HASH_SIZE67]; | |||
| 1124 | FcCharSetOrigEnt *ent; | |||
| 1125 | ||||
| 1126 | ent = malloc (sizeof (FcCharSetOrigEnt)); | |||
| 1127 | if (!ent) | |||
| 1128 | return FcFalse0; | |||
| 1129 | ent->orig = orig; | |||
| 1130 | ent->frozen = frozen; | |||
| 1131 | ent->next = *bucket; | |||
| 1132 | *bucket = ent; | |||
| 1133 | return FcTrue1; | |||
| 1134 | } | |||
| 1135 | ||||
| 1136 | static FcCharSet * | |||
| 1137 | FcCharSetFreezeBase (FcCharSetFreezer *freezer, FcCharSet *fcs) | |||
| 1138 | { | |||
| 1139 | FcChar32 hash = FcCharSetHash (fcs); | |||
| 1140 | FcCharSetEnt **bucket = &freezer->set_hash_table[hash % FC_CHAR_SET_HASH_SIZE67]; | |||
| 1141 | FcCharSetEnt *ent; | |||
| 1142 | int size; | |||
| 1143 | int i; | |||
| 1144 | ||||
| 1145 | for (ent = *bucket; ent; ent = ent->next) | |||
| 1146 | { | |||
| 1147 | if (ent->hash == hash && | |||
| 1148 | ent->set.num == fcs->num && | |||
| 1149 | !memcmp (FcCharSetNumbers(&ent->set)((FcChar16 *) ((intptr_t) (&ent->set) + ((&ent-> set)->numbers_offset))), | |||
| 1150 | FcCharSetNumbers(fcs)((FcChar16 *) ((intptr_t) (fcs) + ((fcs)->numbers_offset)) ), | |||
| 1151 | fcs->num * sizeof (FcChar16))) | |||
| 1152 | { | |||
| 1153 | FcBool ok = FcTrue1; | |||
| 1154 | int i; | |||
| 1155 | ||||
| 1156 | for (i = 0; i < fcs->num; i++) | |||
| 1157 | if (FcCharSetLeaf(&ent->set, i)(((FcCharLeaf *) ((intptr_t) (((intptr_t *) ((intptr_t) (& ent->set) + ((&ent->set)->leaves_offset)))) + (( (intptr_t *) ((intptr_t) (&ent->set) + ((&ent-> set)->leaves_offset)))[i])))) != FcCharSetLeaf(fcs, i)(((FcCharLeaf *) ((intptr_t) (((intptr_t *) ((intptr_t) (fcs) + ((fcs)->leaves_offset)))) + (((intptr_t *) ((intptr_t) ( fcs) + ((fcs)->leaves_offset)))[i]))))) | |||
| 1158 | ok = FcFalse0; | |||
| 1159 | if (ok) | |||
| 1160 | return &ent->set; | |||
| 1161 | } | |||
| 1162 | } | |||
| 1163 | ||||
| 1164 | size = (sizeof (FcCharSetEnt) + | |||
| 1165 | fcs->num * sizeof (FcCharLeaf *) + | |||
| 1166 | fcs->num * sizeof (FcChar16)); | |||
| 1167 | ent = malloc (size); | |||
| 1168 | if (!ent) | |||
| 1169 | return 0; | |||
| 1170 | ||||
| 1171 | freezer->charsets_allocated++; | |||
| 1172 | ||||
| 1173 | FcRefSetConst (&ent->set.ref); | |||
| 1174 | ent->set.num = fcs->num; | |||
| 1175 | if (fcs->num) | |||
| 1176 | { | |||
| 1177 | intptr_t *ent_leaves; | |||
| 1178 | ||||
| 1179 | ent->set.leaves_offset = sizeof (ent->set); | |||
| 1180 | ent->set.numbers_offset = (ent->set.leaves_offset + | |||
| 1181 | fcs->num * sizeof (intptr_t)); | |||
| 1182 | ||||
| 1183 | ent_leaves = FcCharSetLeaves (&ent->set)((intptr_t *) ((intptr_t) (&ent->set) + ((&ent-> set)->leaves_offset))); | |||
| 1184 | for (i = 0; i < fcs->num; i++) | |||
| 1185 | ent_leaves[i] = FcPtrToOffset (ent_leaves,((intptr_t) ((((FcCharLeaf *) ((intptr_t) (((intptr_t *) ((intptr_t ) (fcs) + ((fcs)->leaves_offset)))) + (((intptr_t *) ((intptr_t ) (fcs) + ((fcs)->leaves_offset)))[i]))))) - (intptr_t) (ent_leaves )) | |||
| 1186 | FcCharSetLeaf (fcs, i))((intptr_t) ((((FcCharLeaf *) ((intptr_t) (((intptr_t *) ((intptr_t ) (fcs) + ((fcs)->leaves_offset)))) + (((intptr_t *) ((intptr_t ) (fcs) + ((fcs)->leaves_offset)))[i]))))) - (intptr_t) (ent_leaves )); | |||
| 1187 | memcpy (FcCharSetNumbers (&ent->set),__builtin___memcpy_chk (((FcChar16 *) ((intptr_t) (&ent-> set) + ((&ent->set)->numbers_offset))), ((FcChar16 * ) ((intptr_t) (fcs) + ((fcs)->numbers_offset))), fcs->num * sizeof (FcChar16), __builtin_object_size (((FcChar16 *) (( intptr_t) (&ent->set) + ((&ent->set)->numbers_offset ))), 0)) | |||
| 1188 | FcCharSetNumbers (fcs),__builtin___memcpy_chk (((FcChar16 *) ((intptr_t) (&ent-> set) + ((&ent->set)->numbers_offset))), ((FcChar16 * ) ((intptr_t) (fcs) + ((fcs)->numbers_offset))), fcs->num * sizeof (FcChar16), __builtin_object_size (((FcChar16 *) (( intptr_t) (&ent->set) + ((&ent->set)->numbers_offset ))), 0)) | |||
| 1189 | fcs->num * sizeof (FcChar16))__builtin___memcpy_chk (((FcChar16 *) ((intptr_t) (&ent-> set) + ((&ent->set)->numbers_offset))), ((FcChar16 * ) ((intptr_t) (fcs) + ((fcs)->numbers_offset))), fcs->num * sizeof (FcChar16), __builtin_object_size (((FcChar16 *) (( intptr_t) (&ent->set) + ((&ent->set)->numbers_offset ))), 0)); | |||
| 1190 | } | |||
| 1191 | else | |||
| 1192 | { | |||
| 1193 | ent->set.leaves_offset = 0; | |||
| 1194 | ent->set.numbers_offset = 0; | |||
| 1195 | } | |||
| 1196 | ||||
| 1197 | ent->hash = hash; | |||
| 1198 | ent->next = *bucket; | |||
| 1199 | *bucket = ent; | |||
| 1200 | ||||
| 1201 | return &ent->set; | |||
| 1202 | } | |||
| 1203 | ||||
| 1204 | static const FcCharSet * | |||
| 1205 | FcCharSetFindFrozen (FcCharSetFreezer *freezer, const FcCharSet *orig) | |||
| 1206 | { | |||
| 1207 | FcCharSetOrigEnt **bucket = &freezer->orig_hash_table[((uintptr_t) orig) & FC_CHAR_SET_HASH_SIZE67]; | |||
| 1208 | FcCharSetOrigEnt *ent; | |||
| 1209 | ||||
| 1210 | for (ent = *bucket; ent; ent = ent->next) | |||
| 1211 | if (ent->orig == orig) | |||
| 1212 | return ent->frozen; | |||
| 1213 | return NULL((void*)0); | |||
| 1214 | } | |||
| 1215 | ||||
| 1216 | const FcCharSet * | |||
| 1217 | FcCharSetFreeze (FcCharSetFreezer *freezer, const FcCharSet *fcs) | |||
| 1218 | { | |||
| 1219 | FcCharSet *b; | |||
| 1220 | const FcCharSet *n = 0; | |||
| 1221 | FcCharLeaf *l; | |||
| 1222 | int i; | |||
| 1223 | ||||
| 1224 | b = FcCharSetCreate (); | |||
| 1225 | if (!b) | |||
| 1226 | goto bail0; | |||
| 1227 | for (i = 0; i < fcs->num; i++) | |||
| 1228 | { | |||
| 1229 | l = FcCharSetFreezeLeaf (freezer, FcCharSetLeaf(fcs, i)(((FcCharLeaf *) ((intptr_t) (((intptr_t *) ((intptr_t) (fcs) + ((fcs)->leaves_offset)))) + (((intptr_t *) ((intptr_t) ( fcs) + ((fcs)->leaves_offset)))[i]))))); | |||
| 1230 | if (!l) | |||
| 1231 | goto bail1; | |||
| 1232 | if (!FcCharSetInsertLeaf (b, FcCharSetNumbers(fcs)((FcChar16 *) ((intptr_t) (fcs) + ((fcs)->numbers_offset)) )[i] << 8, l)) | |||
| 1233 | goto bail1; | |||
| 1234 | } | |||
| 1235 | n = FcCharSetFreezeBase (freezer, b); | |||
| 1236 | if (!FcCharSetFreezeOrig (freezer, fcs, n)) | |||
| 1237 | { | |||
| 1238 | n = NULL((void*)0); | |||
| 1239 | goto bail1; | |||
| 1240 | } | |||
| 1241 | freezer->charsets_seen++; | |||
| 1242 | freezer->leaves_seen += fcs->num; | |||
| 1243 | bail1: | |||
| 1244 | if (b->num) | |||
| 1245 | free (FcCharSetLeaves (b)((intptr_t *) ((intptr_t) (b) + ((b)->leaves_offset)))); | |||
| 1246 | if (b->num) | |||
| 1247 | free (FcCharSetNumbers (b)((FcChar16 *) ((intptr_t) (b) + ((b)->numbers_offset)))); | |||
| 1248 | free (b); | |||
| 1249 | bail0: | |||
| 1250 | return n; | |||
| 1251 | } | |||
| 1252 | ||||
| 1253 | FcCharSetFreezer * | |||
| 1254 | FcCharSetFreezerCreate (void) | |||
| 1255 | { | |||
| 1256 | FcCharSetFreezer *freezer; | |||
| 1257 | ||||
| 1258 | freezer = calloc (1, sizeof (FcCharSetFreezer)); | |||
| 1259 | return freezer; | |||
| 1260 | } | |||
| 1261 | ||||
| 1262 | void | |||
| 1263 | FcCharSetFreezerDestroy (FcCharSetFreezer *freezer) | |||
| 1264 | { | |||
| 1265 | int i; | |||
| 1266 | ||||
| 1267 | if (FcDebug()(FcDebugVal) & FC_DBG_CACHE16) | |||
| 1268 | { | |||
| 1269 | printf ("\ncharsets %d -> %d leaves %d -> %d\n", | |||
| 1270 | freezer->charsets_seen, freezer->charsets_allocated, | |||
| 1271 | freezer->leaves_seen, freezer->leaves_allocated); | |||
| 1272 | } | |||
| 1273 | for (i = 0; i < FC_CHAR_SET_HASH_SIZE67; i++) | |||
| 1274 | { | |||
| 1275 | FcCharSetEnt *ent, *next; | |||
| 1276 | for (ent = freezer->set_hash_table[i]; ent; ent = next) | |||
| 1277 | { | |||
| 1278 | next = ent->next; | |||
| 1279 | free (ent); | |||
| 1280 | } | |||
| 1281 | } | |||
| 1282 | ||||
| 1283 | for (i = 0; i < FC_CHAR_SET_HASH_SIZE67; i++) | |||
| 1284 | { | |||
| 1285 | FcCharSetOrigEnt *ent, *next; | |||
| 1286 | for (ent = freezer->orig_hash_table[i]; ent; ent = next) | |||
| 1287 | { | |||
| 1288 | next = ent->next; | |||
| 1289 | free (ent); | |||
| 1290 | } | |||
| 1291 | } | |||
| 1292 | ||||
| 1293 | for (i = 0; i < freezer->leaf_block_count; i++) | |||
| 1294 | free (freezer->leaf_blocks[i]); | |||
| 1295 | ||||
| 1296 | free (freezer->leaf_blocks); | |||
| 1297 | free (freezer); | |||
| 1298 | } | |||
| 1299 | ||||
| 1300 | FcBool | |||
| 1301 | FcCharSetSerializeAlloc (FcSerialize *serialize, const FcCharSet *cs) | |||
| 1302 | { | |||
| 1303 | intptr_t *leaves; | |||
| 1304 | FcChar16 *numbers; | |||
| 1305 | int i; | |||
| 1306 | ||||
| 1307 | if (!FcRefIsConst (&cs->ref)) | |||
| ||||
| 1308 | { | |||
| 1309 | if (!serialize->cs_freezer) | |||
| 1310 | { | |||
| 1311 | serialize->cs_freezer = FcCharSetFreezerCreate (); | |||
| 1312 | if (!serialize->cs_freezer) | |||
| 1313 | return FcFalse0; | |||
| 1314 | } | |||
| 1315 | if (FcCharSetFindFrozen (serialize->cs_freezer, cs)) | |||
| 1316 | return FcTrue1; | |||
| 1317 | ||||
| 1318 | cs = FcCharSetFreeze (serialize->cs_freezer, cs); | |||
| 1319 | } | |||
| 1320 | ||||
| 1321 | leaves = FcCharSetLeaves (cs)((intptr_t *) ((intptr_t) (cs) + ((cs)->leaves_offset))); | |||
| 1322 | numbers = FcCharSetNumbers (cs)((FcChar16 *) ((intptr_t) (cs) + ((cs)->numbers_offset))); | |||
| 1323 | ||||
| 1324 | if (!FcSerializeAlloc (serialize, cs, sizeof (FcCharSet))) | |||
| 1325 | return FcFalse0; | |||
| 1326 | if (!FcSerializeAlloc (serialize, leaves, cs->num * sizeof (intptr_t))) | |||
| 1327 | return FcFalse0; | |||
| 1328 | if (!FcSerializeAlloc (serialize, numbers, cs->num * sizeof (FcChar16))) | |||
| 1329 | return FcFalse0; | |||
| 1330 | for (i = 0; i < cs->num; i++) | |||
| 1331 | if (!FcSerializeAlloc (serialize, FcCharSetLeaf(cs, i)(((FcCharLeaf *) ((intptr_t) (((intptr_t *) ((intptr_t) (cs) + ((cs)->leaves_offset)))) + (((intptr_t *) ((intptr_t) (cs ) + ((cs)->leaves_offset)))[i])))), | |||
| 1332 | sizeof (FcCharLeaf))) | |||
| 1333 | return FcFalse0; | |||
| 1334 | return FcTrue1; | |||
| 1335 | } | |||
| 1336 | ||||
| 1337 | FcCharSet * | |||
| 1338 | FcCharSetSerialize(FcSerialize *serialize, const FcCharSet *cs) | |||
| 1339 | { | |||
| 1340 | FcCharSet *cs_serialized; | |||
| 1341 | intptr_t *leaves, *leaves_serialized; | |||
| 1342 | FcChar16 *numbers, *numbers_serialized; | |||
| 1343 | FcCharLeaf *leaf, *leaf_serialized; | |||
| 1344 | int i; | |||
| 1345 | ||||
| 1346 | if (!FcRefIsConst (&cs->ref) && serialize->cs_freezer) | |||
| 1347 | { | |||
| 1348 | cs = FcCharSetFindFrozen (serialize->cs_freezer, cs); | |||
| 1349 | if (!cs) | |||
| 1350 | return NULL((void*)0); | |||
| 1351 | } | |||
| 1352 | ||||
| 1353 | cs_serialized = FcSerializePtr (serialize, cs); | |||
| 1354 | if (!cs_serialized) | |||
| 1355 | return NULL((void*)0); | |||
| 1356 | ||||
| 1357 | FcRefSetConst (&cs_serialized->ref); | |||
| 1358 | cs_serialized->num = cs->num; | |||
| 1359 | ||||
| 1360 | if (cs->num) | |||
| 1361 | { | |||
| 1362 | leaves = FcCharSetLeaves (cs)((intptr_t *) ((intptr_t) (cs) + ((cs)->leaves_offset))); | |||
| 1363 | leaves_serialized = FcSerializePtr (serialize, leaves); | |||
| 1364 | if (!leaves_serialized) | |||
| 1365 | return NULL((void*)0); | |||
| 1366 | ||||
| 1367 | cs_serialized->leaves_offset = FcPtrToOffset (cs_serialized,((intptr_t) (leaves_serialized) - (intptr_t) (cs_serialized)) | |||
| 1368 | leaves_serialized)((intptr_t) (leaves_serialized) - (intptr_t) (cs_serialized)); | |||
| 1369 | ||||
| 1370 | numbers = FcCharSetNumbers (cs)((FcChar16 *) ((intptr_t) (cs) + ((cs)->numbers_offset))); | |||
| 1371 | numbers_serialized = FcSerializePtr (serialize, numbers); | |||
| 1372 | if (!numbers) | |||
| 1373 | return NULL((void*)0); | |||
| 1374 | ||||
| 1375 | cs_serialized->numbers_offset = FcPtrToOffset (cs_serialized,((intptr_t) (numbers_serialized) - (intptr_t) (cs_serialized) ) | |||
| 1376 | numbers_serialized)((intptr_t) (numbers_serialized) - (intptr_t) (cs_serialized) ); | |||
| 1377 | ||||
| 1378 | for (i = 0; i < cs->num; i++) | |||
| 1379 | { | |||
| 1380 | leaf = FcCharSetLeaf (cs, i)(((FcCharLeaf *) ((intptr_t) (((intptr_t *) ((intptr_t) (cs) + ((cs)->leaves_offset)))) + (((intptr_t *) ((intptr_t) (cs ) + ((cs)->leaves_offset)))[i])))); | |||
| 1381 | leaf_serialized = FcSerializePtr (serialize, leaf); | |||
| 1382 | if (!leaf_serialized) | |||
| 1383 | return NULL((void*)0); | |||
| 1384 | *leaf_serialized = *leaf; | |||
| 1385 | leaves_serialized[i] = FcPtrToOffset (leaves_serialized,((intptr_t) (leaf_serialized) - (intptr_t) (leaves_serialized )) | |||
| 1386 | leaf_serialized)((intptr_t) (leaf_serialized) - (intptr_t) (leaves_serialized )); | |||
| 1387 | numbers_serialized[i] = numbers[i]; | |||
| 1388 | } | |||
| 1389 | } | |||
| 1390 | else | |||
| 1391 | { | |||
| 1392 | cs_serialized->leaves_offset = 0; | |||
| 1393 | cs_serialized->numbers_offset = 0; | |||
| 1394 | } | |||
| 1395 | ||||
| 1396 | return cs_serialized; | |||
| 1397 | } | |||
| 1398 | #define __fccharset__ | |||
| 1399 | #include "fcaliastail.h" | |||
| 1400 | #undef __fccharset__ |