1/*
2 * fontconfig/src/fclist.c
3 *
4 * Copyright © 2000 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
27#include "fcobjshash.h"
28
29#include <string.h>
30
31/* The 1000 is to leave some room for future added internal objects, such
32 * that caches from newer fontconfig can still be used with older fontconfig
33 * without getting confused. */
34static fc_atomic_int_t next_id = FC_MAX_BASE_OBJECT + FC_EXT_OBJ_INDEX;
35struct FcObjectOtherTypeInfo {
36    struct FcObjectOtherTypeInfo *next;
37    FcObjectType object;
38    FcObject id;
39} *other_types;
40
41void
42FcObjectFini (void)
43{
44    struct FcObjectOtherTypeInfo *ots, *ot;
45
46retry:
47    ots = fc_atomic_ptr_get (&other_types);
48    if (!ots)
49	return;
50    if (!fc_atomic_ptr_cmpexch (&other_types, ots, NULL))
51	goto retry;
52
53    while (ots)
54    {
55	ot = ots->next;
56	if (ots->object.object)
57	    free (ots->object.object);
58	free (ots);
59	ots = ot;
60    }
61}
62
63static FcObjectType *
64_FcObjectLookupOtherTypeByName (const char *str, FcObject *id)
65{
66    struct FcObjectOtherTypeInfo *ots, *ot;
67
68retry:
69    ots = fc_atomic_ptr_get (&other_types);
70
71    for (ot = ots; ot; ot = ot->next)
72	if (0 == strcmp (ot->object.object, str))
73	    break;
74
75    if (!ot)
76    {
77	ot = malloc (sizeof (*ot));
78	if (!ot)
79	    return NULL;
80
81	ot->object.object = (char *) FcStrdup (str);
82	ot->object.type = FcTypeUnknown;
83	ot->id = fc_atomic_int_add (next_id, +1);
84	if (ot->id < (FC_MAX_BASE_OBJECT + FC_EXT_OBJ_INDEX))
85	{
86	    fprintf (stderr, "Fontconfig error: No object ID to assign\n");
87	    abort ();
88	}
89	ot->next = ots;
90
91	if (!fc_atomic_ptr_cmpexch (&other_types, ots, ot)) {
92	    if (ot->object.object)
93		free (ot->object.object);
94	    free (ot);
95	    goto retry;
96	}
97    }
98
99    if (id)
100      *id = ot->id;
101
102    return &ot->object;
103}
104
105FcObject
106FcObjectLookupBuiltinIdByName (const char *str)
107{
108    const struct FcObjectTypeInfo *o = FcObjectTypeLookup (str, strlen (str));
109
110    if (o)
111	return o->id;
112
113    return 0;
114}
115
116FcObject
117FcObjectLookupIdByName (const char *str)
118{
119    const struct FcObjectTypeInfo *o = FcObjectTypeLookup (str, strlen (str));
120    FcObject id;
121    if (o)
122	return o->id;
123
124    if (_FcObjectLookupOtherTypeByName (str, &id))
125	return id;
126
127    return 0;
128}
129
130const char *
131FcObjectLookupOtherNameById (FcObject id)
132{
133    struct FcObjectOtherTypeInfo *ot;
134
135    for (ot = fc_atomic_ptr_get (&other_types); ot; ot = ot->next)
136	if (ot->id == id)
137	    return ot->object.object;
138
139    return NULL;
140}
141
142const FcObjectType *
143FcObjectLookupOtherTypeByName (const char *str)
144{
145    return _FcObjectLookupOtherTypeByName (str, NULL);
146}
147
148FcPrivate const FcObjectType *
149FcObjectLookupOtherTypeById (FcObject id)
150{
151    struct FcObjectOtherTypeInfo *ot;
152
153    for (ot = fc_atomic_ptr_get (&other_types); ot; ot = ot->next)
154	if (ot->id == id)
155	    return &ot->object;
156
157    return NULL;
158}
159
160
161#include "fcaliastail.h"
162#undef __fcobjs__
163