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.
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
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 */
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
53 swfdec_constant_pool_new (SwfdecAsContext
*context
, SwfdecBuffer
*buffer
, guint version
)
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 */
65 pool
= g_hash_table_lookup (context
->constant_pools
, buffer
->data
);
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
);
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 ("");
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
);
91 /* put pool into the context's cache */
93 pool
->context
= context
;
94 g_hash_table_insert (context
->constant_pools
, buffer
->data
, pool
);
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.
108 swfdec_constant_pool_ref (SwfdecConstantPool
*pool
)
110 g_return_val_if_fail (SWFDEC_IS_CONSTANT_POOL (pool
), NULL
);
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
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);
135 g_hash_table_remove (pool
->context
->constant_pools
, pool
->buffer
->data
);
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:
150 * Queries the number of strings in this pool.
152 * Returns: The number of strings in this @pool
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:
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
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.
191 swfdec_constant_pool_get_buffer (SwfdecConstantPool
*pool
)
193 g_return_val_if_fail (SWFDEC_IS_CONSTANT_POOL (pool
), NULL
);