1 /*
2  * Copyright © 2006 Keith Packard
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and its
5  * documentation for any purpose is hereby granted without fee, provided that
6  * the above copyright notice appear in all copies and that both that copyright
7  * notice and this permission notice appear in supporting documentation, and
8  * that the name of the copyright holders not be used in advertising or
9  * publicity pertaining to distribution of the software without specific,
10  * written prior permission.  The copyright holders make no representations
11  * about the suitability of this software for any purpose.  It is provided "as
12  * is" without express or implied warranty.
13  *
14  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20  * OF THIS SOFTWARE.
21  */
22 
23 #include "fcint.h"
24 
25 intptr_t
FcAlignSize(intptr_t size)26 FcAlignSize (intptr_t size)
27 {
28     intptr_t	rem = size % sizeof (FcAlign);
29     if (rem)
30 	size += sizeof (FcAlign) - rem;
31     return size;
32 }
33 
34 /*
35  * Serialization helper object -- allocate space in the
36  * yet-to-be-created linear array for a serialized font set
37  */
38 
39 FcSerialize *
FcSerializeCreate(void)40 FcSerializeCreate (void)
41 {
42     FcSerialize	*serialize;
43 
44     serialize = malloc (sizeof (FcSerialize));
45     if (!serialize)
46 	return NULL;
47     serialize->size = 0;
48     serialize->linear = NULL;
49     serialize->cs_freezer = NULL;
50     memset (serialize->buckets, '\0', sizeof (serialize->buckets));
51     return serialize;
52 }
53 
54 void
FcSerializeDestroy(FcSerialize * serialize)55 FcSerializeDestroy (FcSerialize *serialize)
56 {
57     uintptr_t	bucket;
58 
59     for (bucket = 0; bucket < FC_SERIALIZE_HASH_SIZE; bucket++)
60     {
61 	FcSerializeBucket   *buck, *next;
62 
63 	for (buck = serialize->buckets[bucket]; buck; buck = next) {
64 	    next = buck->next;
65 	    free (buck);
66 	}
67     }
68     if (serialize->cs_freezer)
69 	FcCharSetFreezerDestroy (serialize->cs_freezer);
70     free (serialize);
71 }
72 
73 /*
74  * Allocate space for an object in the serialized array. Keep track
75  * of where the object is placed and only allocate one copy of each object
76  */
77 
78 FcBool
FcSerializeAlloc(FcSerialize * serialize,const void * object,int size)79 FcSerializeAlloc (FcSerialize *serialize, const void *object, int size)
80 {
81     uintptr_t	bucket = ((uintptr_t) object) % FC_SERIALIZE_HASH_SIZE;
82     FcSerializeBucket  *buck;
83 
84     for (buck = serialize->buckets[bucket]; buck; buck = buck->next)
85 	if (buck->object == object)
86 	    return FcTrue;
87     buck = malloc (sizeof (FcSerializeBucket));
88     if (!buck)
89 	return FcFalse;
90     buck->object = object;
91     buck->offset = serialize->size;
92     buck->next = serialize->buckets[bucket];
93     serialize->buckets[bucket] = buck;
94     serialize->size += FcAlignSize (size);
95     return FcTrue;
96 }
97 
98 /*
99  * Reserve space in the serialization array
100  */
101 intptr_t
FcSerializeReserve(FcSerialize * serialize,int size)102 FcSerializeReserve (FcSerialize *serialize, int size)
103 {
104     intptr_t	offset = serialize->size;
105     serialize->size += FcAlignSize (size);
106     return offset;
107 }
108 
109 /*
110  * Given an object, return the offset in the serialized array where
111  * the serialized copy of the object is stored
112  */
113 intptr_t
FcSerializeOffset(FcSerialize * serialize,const void * object)114 FcSerializeOffset (FcSerialize *serialize, const void *object)
115 {
116     uintptr_t	bucket = ((uintptr_t) object) % FC_SERIALIZE_HASH_SIZE;
117     FcSerializeBucket  *buck;
118 
119     for (buck = serialize->buckets[bucket]; buck; buck = buck->next)
120 	if (buck->object == object)
121 	    return buck->offset;
122     return 0;
123 }
124 
125 /*
126  * Given a cache and an object, return a pointer to where
127  * the serialized copy of the object is stored
128  */
129 void *
FcSerializePtr(FcSerialize * serialize,const void * object)130 FcSerializePtr (FcSerialize *serialize, const void *object)
131 {
132     intptr_t	offset = FcSerializeOffset (serialize, object);
133 
134     if (!offset)
135 	return NULL;
136     return (void *) ((char *) serialize->linear + offset);
137 }
138 
139 FcBool
FcStrSerializeAlloc(FcSerialize * serialize,const FcChar8 * str)140 FcStrSerializeAlloc (FcSerialize *serialize, const FcChar8 *str)
141 {
142     return FcSerializeAlloc (serialize, str, strlen ((const char *) str) + 1);
143 }
144 
145 FcChar8 *
FcStrSerialize(FcSerialize * serialize,const FcChar8 * str)146 FcStrSerialize (FcSerialize *serialize, const FcChar8 *str)
147 {
148     FcChar8 *str_serialize = FcSerializePtr (serialize, str);
149     if (!str_serialize)
150 	return NULL;
151     strcpy ((char *) str_serialize, (const char *) str);
152     return str_serialize;
153 }
154 #include "fcaliastail.h"
155 #undef __fcserialize__
156