oops, I shifted the wrong value.
[swfdec.git] / swfdec / swfdec_constant_pool.c
blob9a14312829a473b0b39c1728ef6a8b6880ef0971
1 /* Swfdec
2 * Copyright (C) 2007-2008 Benjamin Otte <otte@gnome.org>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301 USA
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
24 #include "swfdec_constant_pool.h"
25 #include "swfdec_as_strings.h"
26 #include "swfdec_bits.h"
27 #include "swfdec_debug.h"
29 struct _SwfdecConstantPool {
30 SwfdecAsContext * context; /* context we are attached to or NULL */
31 SwfdecBuffer * buffer; /* the buffer the strings were read from */
32 guint refcount; /* reference count */
33 guint n_strings; /* number of strings */
34 char * strings[1]; /* n_strings strings */
37 /**
38 * swfdec_constant_pool_new:
39 * @context: a context to attach strings to or %NULL
40 * @buffer: buffer to read constant pool from
41 * @version: the Flash version to use when reading the strings
43 * Creates a new constant pool from the given @buffer. If the buffer is in the
44 * wrong format, %NULL is returned. If a @context was given, the strings are
45 * added to the context. This means the strings in the pool will be
46 * garbage-collected already. When using a non-%NULL @context, the pool does
47 * will not add a reference to the context. It is your responsibility to hold a
48 * reference to the context while you use the pool.
50 * Returns: a new constant pool or %NULL
51 **/
52 SwfdecConstantPool *
53 swfdec_constant_pool_new (SwfdecAsContext *context, SwfdecBuffer *buffer, guint version)
55 guint i, n;
56 gsize size;
57 SwfdecBits bits;
58 SwfdecConstantPool *pool;
60 g_return_val_if_fail (context == NULL || SWFDEC_IS_AS_CONTEXT (context), NULL);
61 g_return_val_if_fail (buffer != NULL, NULL);
63 /* try to find the pool in the context's cache */
64 if (context) {
65 pool = g_hash_table_lookup (context->constant_pools, buffer->data);
66 if (pool)
67 return swfdec_constant_pool_ref (pool);
70 swfdec_bits_init (&bits, buffer);
72 n = swfdec_bits_get_u16 (&bits);
74 size = sizeof (SwfdecConstantPool) + (MAX (1, n) - 1) * sizeof (char *);
75 pool = g_slice_alloc0 (size);
76 pool->n_strings = n;
77 for (i = 0; i < n && swfdec_bits_left (&bits); i++) {
78 pool->strings[i] = swfdec_bits_get_string (&bits, version);
79 if (pool->strings[i] == NULL) {
80 SWFDEC_ERROR ("constant pool index %u invalid, using empty string instead.", i);
81 pool->strings[i] = context ? (char *) SWFDEC_AS_STR_EMPTY : g_strdup ("");
82 } else if (context) {
83 pool->strings[i] = (char *) swfdec_as_context_give_string (context, pool->strings[i]);
86 if (swfdec_bits_left (&bits)) {
87 SWFDEC_WARNING ("constant pool didn't consume whole buffer (%u bytes leftover)", swfdec_bits_left (&bits) / 8);
89 pool->buffer = swfdec_buffer_ref (buffer);
90 pool->refcount = 1;
91 /* put pool into the context's cache */
92 if (context) {
93 pool->context = context;
94 g_hash_table_insert (context->constant_pools, buffer->data, pool);
96 return pool;
99 /**
100 * swfdec_constant_pool_ref:
101 * @pool: a constant pool
103 * Increases the constant pool's reference by one.
105 * Returns: the passed in @pool.
107 SwfdecConstantPool *
108 swfdec_constant_pool_ref (SwfdecConstantPool *pool)
110 g_return_val_if_fail (SWFDEC_IS_CONSTANT_POOL (pool), NULL);
112 pool->refcount++;
114 return pool;
118 * swfdec_constant_pool_unref:
119 * @pool: the pool to unref
121 * Removes a reference from the pool. If no more references are left, the pool
122 * will be freed.
124 void
125 swfdec_constant_pool_unref (SwfdecConstantPool *pool)
127 g_return_if_fail (SWFDEC_IS_CONSTANT_POOL (pool));
128 g_return_if_fail (pool->refcount > 0);
130 pool->refcount--;
131 if (pool->refcount)
132 return;
134 if (pool->context) {
135 g_hash_table_remove (pool->context->constant_pools, pool->buffer->data);
136 } else {
137 guint i;
138 for (i = 0; i < pool->n_strings; i++) {
139 g_free (pool->strings[i]);
142 swfdec_buffer_unref (pool->buffer);
143 g_slice_free1 (sizeof (SwfdecConstantPool) + (MAX (1, pool->n_strings) - 1) * sizeof (char *), pool);
147 * swfdec_constant_pool_size:
148 * @pool: a pool
150 * Queries the number of strings in this pool.
152 * Returns: The number of strings in this @pool
154 guint
155 swfdec_constant_pool_size (SwfdecConstantPool *pool)
157 g_return_val_if_fail (SWFDEC_IS_CONSTANT_POOL (pool), 0);
159 return pool->n_strings;
163 * swfdec_constant_pool_get:
164 * @pool: a pool
165 * @i: index of the string to get
167 * Gets the requested string from the pool. The index must not excess the
168 * number of elements in the pool. If the constant pool was created with a
169 * context attached, the returned string will be garbage-collected already.
171 * Returns: the string at position @i
173 const char *
174 swfdec_constant_pool_get (SwfdecConstantPool *pool, guint i)
176 g_return_val_if_fail (SWFDEC_IS_CONSTANT_POOL (pool), NULL);
177 g_return_val_if_fail (i < pool->n_strings, NULL);
179 return pool->strings[i];
183 * swfdec_constant_pool_get_buffer:
184 * @pool: a constant pool
186 * Gets the buffer the pool was created from
188 * Returns: the buffer this pool was created from.
190 SwfdecBuffer *
191 swfdec_constant_pool_get_buffer (SwfdecConstantPool *pool)
193 g_return_val_if_fail (SWFDEC_IS_CONSTANT_POOL (pool), NULL);
195 return pool->buffer;