[pygobject] cache refactoring: Break sequence cache up for array vs list
- From: Simon Feltman <sfeltman src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pygobject] cache refactoring: Break sequence cache up for array vs list
- Date: Mon, 3 Feb 2014 13:55:25 +0000 (UTC)
commit c48ddacf4479d2cf80beb9c614cdce2a61599b3b
Author: Simon Feltman <sfeltman src gnome org>
Date: Fri Oct 11 21:30:45 2013 -0700
cache refactoring: Break sequence cache up for array vs list
Add new arg cache type specialized for arrays. This cleans up the basic
sequence cache type which does not need length and size related info. Remove
fixed length checks from GList and GSList from_py marshaling because these
will always be -1.
https://bugzilla.gnome.org/show_bug.cgi?id=709700
gi/pygi-cache.c | 160 ++++++++++++++++++++++++++++++++++----------
gi/pygi-cache.h | 16 ++++-
gi/pygi-invoke.c | 4 +-
gi/pygi-marshal-cleanup.c | 28 ++++----
gi/pygi-marshal-from-py.c | 37 +++-------
gi/pygi-marshal-to-py.c | 23 ++++---
6 files changed, 177 insertions(+), 91 deletions(-)
---
diff --git a/gi/pygi-cache.c b/gi/pygi-cache.c
index 9793ffe..a8468cc 100644
--- a/gi/pygi-cache.c
+++ b/gi/pygi-cache.c
@@ -160,6 +160,15 @@ _sequence_cache_free_func (PyGISequenceCache *cache)
}
static void
+_array_cache_free_func (PyGIArgGArray *cache)
+{
+ if (cache != NULL) {
+ _pygi_arg_cache_free (((PyGISequenceCache *)cache)->item_cache);
+ g_slice_free (PyGIArgGArray, cache);
+ }
+}
+
+static void
_callback_cache_free_func (PyGICallbackCache *cache)
{
if (cache != NULL) {
@@ -206,27 +215,26 @@ _interface_cache_new (GIInterfaceInfo *iface_info)
return ic;
}
-static PyGISequenceCache *
-_sequence_cache_new (GITypeInfo *type_info,
- GIDirection direction,
- GITransfer transfer,
- gssize child_offset)
+gboolean
+pygi_arg_sequence_setup (PyGISequenceCache *sc,
+ GITypeInfo *type_info,
+ GIArgInfo *arg_info, /* may be NULL for return arguments */
+ GITransfer transfer,
+ PyGIDirection direction)
{
- PyGISequenceCache *sc;
GITypeInfo *item_type_info;
GITransfer item_transfer;
- sc = g_slice_new0 (PyGISequenceCache);
- ( (PyGIArgCache *)sc)->destroy_notify = (GDestroyNotify)_sequence_cache_free_func;
-
- sc->is_zero_terminated = g_type_info_is_zero_terminated (type_info);
- sc->fixed_size = g_type_info_get_array_fixed_size (type_info);
- sc->len_arg_index = g_type_info_get_array_length (type_info);
- if (sc->len_arg_index >= 0)
- sc->len_arg_index += child_offset;
+ if (!pygi_arg_base_setup ((PyGIArgCache *)sc,
+ type_info,
+ arg_info,
+ transfer,
+ direction)) {
+ return FALSE;
+ }
+ sc->arg_cache.destroy_notify = (GDestroyNotify)_sequence_cache_free_func;
item_type_info = g_type_info_get_param_type (type_info, 0);
-
item_transfer =
transfer == GI_TRANSFER_CONTAINER ? GI_TRANSFER_NOTHING : transfer;
@@ -237,17 +245,89 @@ _sequence_cache_new (GITypeInfo *type_info,
0, 0,
NULL);
+ g_base_info_unref ( (GIBaseInfo *)item_type_info);
+
if (sc->item_cache == NULL) {
- _pygi_arg_cache_free ( (PyGIArgCache *)sc);
- return NULL;
+ return FALSE;
}
+ return TRUE;
+}
+
+static gboolean
+pygi_arg_garray_setup (PyGIArgGArray *sc,
+ GITypeInfo *type_info,
+ GIArgInfo *arg_info, /* may be NULL for return arguments */
+ GITransfer transfer,
+ PyGIDirection direction,
+ gssize child_offset)
+{
+ GITypeInfo *item_type_info;
+
+ if (!pygi_arg_sequence_setup ((PyGISequenceCache *)sc,
+ type_info,
+ arg_info,
+ transfer,
+ direction)) {
+ return FALSE;
+ }
+
+ ((PyGIArgCache *)sc)->destroy_notify = (GDestroyNotify)_array_cache_free_func;
+ sc->is_zero_terminated = g_type_info_is_zero_terminated (type_info);
+ sc->fixed_size = g_type_info_get_array_fixed_size (type_info);
+ sc->len_arg_index = g_type_info_get_array_length (type_info);
+ if (sc->len_arg_index >= 0)
+ sc->len_arg_index += child_offset;
+
+ item_type_info = g_type_info_get_param_type (type_info, 0);
sc->item_size = _pygi_g_type_info_size (item_type_info);
g_base_info_unref ( (GIBaseInfo *)item_type_info);
+ return TRUE;
+}
+
+static PyGISequenceCache *
+pygi_arg_sequence_new (GITypeInfo *type_info,
+ GIArgInfo *arg_info,
+ GITransfer transfer,
+ PyGIDirection direction)
+{
+ PyGISequenceCache *sc = g_slice_new0 (PyGISequenceCache);
+ if (sc == NULL)
+ return NULL;
+
+ if (!pygi_arg_sequence_setup (sc, type_info, arg_info, transfer, direction)) {
+ _pygi_arg_cache_free ( (PyGIArgCache *)sc);
+ return NULL;
+ }
+
return sc;
}
+static PyGIArgGArray *
+_arg_array_cache_new (GITypeInfo *type_info,
+ GIArgInfo *arg_info,
+ GITransfer transfer,
+ PyGIDirection direction,
+ gssize child_offset)
+{
+ PyGIArgGArray *array_cache = g_slice_new0 (PyGIArgGArray);
+ if (array_cache == NULL)
+ return NULL;
+
+ if (!pygi_arg_garray_setup (array_cache,
+ type_info,
+ arg_info,
+ transfer,
+ direction,
+ child_offset)) {
+ _pygi_arg_cache_free ( (PyGIArgCache *)array_cache);
+ return NULL;
+ }
+
+ return array_cache;
+}
+
static PyGICallbackCache *
_callback_cache_new (GIArgInfo *arg_info,
GIInterfaceInfo *iface_info,
@@ -284,7 +364,7 @@ _arg_cache_array_len_arg_setup (PyGIArgCache *arg_cache,
gssize arg_index,
gssize *py_arg_index)
{
- PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache;
+ PyGIArgGArray *seq_cache = (PyGIArgGArray *)arg_cache;
if (seq_cache->len_arg_index >= 0) {
PyGIArgCache *child_cache = NULL;
@@ -357,7 +437,7 @@ _arg_cache_from_py_array_setup (PyGIArgCache *arg_cache,
PyGIDirection direction,
gssize arg_index)
{
- PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache;
+ PyGIArgGArray *seq_cache = (PyGIArgGArray *)arg_cache;
seq_cache->array_type = g_type_info_get_array_type (type_info);
arg_cache->from_py_marshaller = _pygi_marshal_from_py_array;
arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_array;
@@ -372,7 +452,7 @@ _arg_cache_to_py_array_setup (PyGIArgCache *arg_cache,
PyGIDirection direction,
gssize arg_index)
{
- PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache;
+ PyGIArgGArray *seq_cache = (PyGIArgGArray *)arg_cache;
seq_cache->array_type = g_type_info_get_array_type (type_info);
arg_cache->to_py_marshaller = _pygi_marshal_to_py_array;
arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_array;
@@ -706,11 +786,12 @@ _arg_cache_new (GITypeInfo *type_info,
case GI_TYPE_TAG_ARRAY:
{
- PyGISequenceCache *seq_cache =
- _sequence_cache_new (type_info,
- direction,
- transfer,
- child_offset);
+ PyGIArgGArray *seq_cache =
+ _arg_array_cache_new (type_info,
+ arg_info,
+ transfer,
+ direction,
+ child_offset);
arg_cache = (PyGIArgCache *)seq_cache;
if (arg_cache == NULL)
@@ -738,15 +819,17 @@ _arg_cache_new (GITypeInfo *type_info,
c_arg_index,
&py_arg_index);
- break;
+ arg_cache->py_arg_index = py_arg_index;
+ arg_cache->c_arg_index = c_arg_index;
+ return arg_cache;
}
case GI_TYPE_TAG_GLIST:
{
PyGISequenceCache *seq_cache =
- _sequence_cache_new (type_info,
- direction,
- transfer,
- child_offset);
+ pygi_arg_sequence_new (type_info,
+ arg_info,
+ transfer,
+ direction);
arg_cache = (PyGIArgCache *)seq_cache;
if (arg_cache == NULL)
@@ -758,16 +841,17 @@ _arg_cache_new (GITypeInfo *type_info,
if (direction & PYGI_DIRECTION_TO_PYTHON)
_arg_cache_to_py_glist_setup (arg_cache, transfer);
-
- break;
+ arg_cache->py_arg_index = py_arg_index;
+ arg_cache->c_arg_index = c_arg_index;
+ return arg_cache;
}
case GI_TYPE_TAG_GSLIST:
{
PyGISequenceCache *seq_cache =
- _sequence_cache_new (type_info,
- direction,
- transfer,
- child_offset);
+ pygi_arg_sequence_new (type_info,
+ arg_info,
+ transfer,
+ direction);
arg_cache = (PyGIArgCache *)seq_cache;
if (arg_cache == NULL)
@@ -779,7 +863,9 @@ _arg_cache_new (GITypeInfo *type_info,
if (direction & PYGI_DIRECTION_TO_PYTHON)
_arg_cache_to_py_gslist_setup (arg_cache, transfer);
- break;
+ arg_cache->py_arg_index = py_arg_index;
+ arg_cache->c_arg_index = c_arg_index;
+ return arg_cache;
}
case GI_TYPE_TAG_GHASH:
arg_cache = pygi_arg_hash_table_new_from_info (type_info, arg_info, transfer, direction);
diff --git a/gi/pygi-cache.h b/gi/pygi-cache.h
index 82e2519..0629646 100644
--- a/gi/pygi-cache.h
+++ b/gi/pygi-cache.h
@@ -132,13 +132,18 @@ struct _PyGIArgCache
typedef struct _PyGISequenceCache
{
PyGIArgCache arg_cache;
+ PyGIArgCache *item_cache;
+} PyGISequenceCache;
+
+typedef struct _PyGIArgGArray
+{
+ PyGISequenceCache seq_cache;
gssize fixed_size;
gssize len_arg_index;
gboolean is_zero_terminated;
gsize item_size;
GIArrayType array_type;
- PyGIArgCache *item_cache;
-} PyGISequenceCache;
+} PyGIArgGArray;
typedef struct _PyGIInterfaceCache
{
@@ -211,6 +216,13 @@ pygi_arg_interface_setup (PyGIInterfaceCache *iface_cache,
PyGIDirection direction,
GIInterfaceInfo *iface_info);
+gboolean
+pygi_arg_sequence_setup (PyGISequenceCache *sc,
+ GITypeInfo *type_info,
+ GIArgInfo *arg_info, /* may be NULL for return arguments */
+ GITransfer transfer,
+ PyGIDirection direction);
+
PyGIArgCache * _arg_cache_alloc (void);
PyGIArgCache * _arg_cache_new (GITypeInfo *type_info,
GIArgInfo *arg_info,
diff --git a/gi/pygi-invoke.c b/gi/pygi-invoke.c
index 675b0ef..151c9e5 100644
--- a/gi/pygi-invoke.c
+++ b/gi/pygi-invoke.c
@@ -422,9 +422,9 @@ static gboolean _caller_alloc (PyGIInvokeState *state,
state->args[arg_count]->v_pointer = g_malloc0 (size);
}
} else if (arg_cache->type_tag == GI_TYPE_TAG_ARRAY) {
- PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache;
+ PyGIArgGArray *array_cache = (PyGIArgGArray *)arg_cache;
- state->out_args[out_count].v_pointer = g_array_new (TRUE, TRUE, seq_cache->item_size);
+ state->out_args[out_count].v_pointer = g_array_new (TRUE, TRUE, array_cache->item_size);
state->args[arg_count] = &state->out_args[out_count];
} else {
return FALSE;
diff --git a/gi/pygi-marshal-cleanup.c b/gi/pygi-marshal-cleanup.c
index 0bf08a9..52d7bb3 100644
--- a/gi/pygi-marshal-cleanup.c
+++ b/gi/pygi-marshal-cleanup.c
@@ -297,24 +297,24 @@ _pygi_marshal_cleanup_to_py_interface_struct_foreign (PyGIInvokeState *state,
static GArray*
_wrap_c_array (PyGIInvokeState *state,
- PyGISequenceCache *sequence_cache,
+ PyGIArgGArray *array_cache,
gpointer data)
{
GArray *array_;
gsize len = 0;
- if (sequence_cache->fixed_size >= 0) {
- len = sequence_cache->fixed_size;
- } else if (sequence_cache->is_zero_terminated) {
+ if (array_cache->fixed_size >= 0) {
+ len = array_cache->fixed_size;
+ } else if (array_cache->is_zero_terminated) {
len = g_strv_length ((gchar **)data);
- } else if (sequence_cache->len_arg_index >= 0) {
- GIArgument *len_arg = state->args[sequence_cache->len_arg_index];
+ } else if (array_cache->len_arg_index >= 0) {
+ GIArgument *len_arg = state->args[array_cache->len_arg_index];
len = len_arg->v_long;
}
array_ = g_array_new (FALSE,
FALSE,
- sequence_cache->item_size);
+ array_cache->item_size);
if (array_ == NULL)
return NULL;
@@ -337,8 +337,9 @@ _pygi_marshal_cleanup_from_py_array (PyGIInvokeState *state,
GArray *array_ = NULL;
GPtrArray *ptr_array_ = NULL;
PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache;
+ PyGIArgGArray *array_cache = (PyGIArgGArray *)arg_cache;
- if (sequence_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY) {
+ if (array_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY) {
ptr_array_ = (GPtrArray *) data;
} else {
array_ = (GArray *) data;
@@ -363,7 +364,7 @@ _pygi_marshal_cleanup_from_py_array (PyGIInvokeState *state,
item = g_array_index (array_, gpointer, i);
/* case 3: C array or GArray with simple types or structs */
else {
- item = array_->data + i * sequence_cache->item_size;
+ item = array_->data + i * array_cache->item_size;
/* special-case hack: GValue array items do not get slice
* allocated in _pygi_marshal_from_py_array(), so we must
* not try to deallocate it as a slice and thus
@@ -381,7 +382,7 @@ _pygi_marshal_cleanup_from_py_array (PyGIInvokeState *state,
}
/* Only free the array when we didn't transfer ownership */
- if (sequence_cache->array_type == GI_ARRAY_TYPE_C) {
+ if (array_cache->array_type == GI_ARRAY_TYPE_C) {
/* always free the GArray wrapper created in from_py marshaling and
* passed back as cleanup_data
*/
@@ -407,16 +408,17 @@ _pygi_marshal_cleanup_to_py_array (PyGIInvokeState *state,
GArray *array_ = NULL;
GPtrArray *ptr_array_ = NULL;
PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache;
+ PyGIArgGArray *array_cache = (PyGIArgGArray *)arg_cache;
/* If this isn't a garray create one to help process variable sized
array elements */
- if (sequence_cache->array_type == GI_ARRAY_TYPE_C) {
- array_ = _wrap_c_array (state, sequence_cache, data);
+ if (array_cache->array_type == GI_ARRAY_TYPE_C) {
+ array_ = _wrap_c_array (state, array_cache, data);
if (array_ == NULL)
return;
- } else if (sequence_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY) {
+ } else if (array_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY) {
ptr_array_ = (GPtrArray *) data;
} else {
array_ = (GArray *) data;
diff --git a/gi/pygi-marshal-from-py.c b/gi/pygi-marshal-from-py.c
index b143727..3867c23 100644
--- a/gi/pygi-marshal-from-py.c
+++ b/gi/pygi-marshal-from-py.c
@@ -258,6 +258,7 @@ _pygi_marshal_from_py_array (PyGIInvokeState *state,
gboolean is_ptr_array;
GArray *array_ = NULL;
PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache;
+ PyGIArgGArray *array_cache = (PyGIArgGArray *)arg_cache;
if (py_arg == Py_None) {
@@ -275,20 +276,20 @@ _pygi_marshal_from_py_array (PyGIInvokeState *state,
if (length < 0)
return FALSE;
- if (sequence_cache->fixed_size >= 0 &&
- sequence_cache->fixed_size != length) {
+ if (array_cache->fixed_size >= 0 &&
+ array_cache->fixed_size != length) {
PyErr_Format (PyExc_ValueError, "Must contain %zd items, not %zd",
- sequence_cache->fixed_size, length);
+ array_cache->fixed_size, length);
return FALSE;
}
- item_size = sequence_cache->item_size;
- is_ptr_array = (sequence_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY);
+ item_size = array_cache->item_size;
+ is_ptr_array = (array_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY);
if (is_ptr_array) {
array_ = (GArray *)g_ptr_array_sized_new (length);
} else {
- array_ = g_array_sized_new (sequence_cache->is_zero_terminated,
+ array_ = g_array_sized_new (array_cache->is_zero_terminated,
TRUE,
item_size,
length);
@@ -303,7 +304,7 @@ _pygi_marshal_from_py_array (PyGIInvokeState *state,
PYGLIB_PyBytes_Check (py_arg)) {
memcpy(array_->data, PYGLIB_PyBytes_AsString (py_arg), length);
array_->len = length;
- if (sequence_cache->is_zero_terminated) {
+ if (array_cache->is_zero_terminated) {
/* If array_ has been created with zero_termination, space for the
* terminator is properly allocated, so we're not off-by-one here. */
array_->data[length] = '\0';
@@ -433,10 +434,10 @@ err:
}
array_success:
- if (sequence_cache->len_arg_index >= 0) {
+ if (array_cache->len_arg_index >= 0) {
/* we have an child arg to handle */
PyGIArgCache *child_cache =
- _pygi_callable_cache_get_arg (callable_cache, sequence_cache->len_arg_index);
+ _pygi_callable_cache_get_arg (callable_cache, array_cache->len_arg_index);
if (child_cache->direction == PYGI_DIRECTION_BIDIRECTIONAL) {
gint *len_arg = (gint *)state->in_args[child_cache->c_arg_index].v_pointer;
@@ -459,7 +460,7 @@ array_success:
}
}
- if (sequence_cache->array_type == GI_ARRAY_TYPE_C) {
+ if (array_cache->array_type == GI_ARRAY_TYPE_C) {
/* In the case of GI_ARRAY_C, we give the data directly as the argument
* but keep the array_ wrapper as cleanup data so we don't have to find
* it's length again.
@@ -523,14 +524,6 @@ _pygi_marshal_from_py_glist (PyGIInvokeState *state,
if (length < 0)
return FALSE;
- if (sequence_cache->fixed_size >= 0 &&
- sequence_cache->fixed_size != length) {
- PyErr_Format (PyExc_ValueError, "Must contain %zd items, not %zd",
- sequence_cache->fixed_size, length);
-
- return FALSE;
- }
-
from_py_marshaller = sequence_cache->item_cache->from_py_marshaller;
for (i = 0; i < length; i++) {
GIArgument item = {0};
@@ -607,14 +600,6 @@ _pygi_marshal_from_py_gslist (PyGIInvokeState *state,
if (length < 0)
return FALSE;
- if (sequence_cache->fixed_size >= 0 &&
- sequence_cache->fixed_size != length) {
- PyErr_Format (PyExc_ValueError, "Must contain %zd items, not %zd",
- sequence_cache->fixed_size, length);
-
- return FALSE;
- }
-
from_py_marshaller = sequence_cache->item_cache->from_py_marshaller;
for (i = 0; i < length; i++) {
GIArgument item = {0};
diff --git a/gi/pygi-marshal-to-py.c b/gi/pygi-marshal-to-py.c
index 292f962..e3d5475 100644
--- a/gi/pygi-marshal-to-py.c
+++ b/gi/pygi-marshal-to-py.c
@@ -121,18 +121,19 @@ _pygi_marshal_to_py_array (PyGIInvokeState *state,
GArray *array_;
PyObject *py_obj = NULL;
PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache;
+ PyGIArgGArray *array_cache = (PyGIArgGArray *)arg_cache;
gsize processed_items = 0;
/* GArrays make it easier to iterate over arrays
* with different element sizes but requires that
* we allocate a GArray if the argument was a C array
*/
- if (seq_cache->array_type == GI_ARRAY_TYPE_C) {
+ if (array_cache->array_type == GI_ARRAY_TYPE_C) {
gsize len;
- if (seq_cache->fixed_size >= 0) {
+ if (array_cache->fixed_size >= 0) {
g_assert(arg->v_pointer != NULL);
- len = seq_cache->fixed_size;
- } else if (seq_cache->is_zero_terminated) {
+ len = array_cache->fixed_size;
+ } else if (array_cache->is_zero_terminated) {
if (arg->v_pointer == NULL) {
len = 0;
} else if (seq_cache->item_cache->type_tag == GI_TYPE_TAG_UINT8) {
@@ -141,9 +142,9 @@ _pygi_marshal_to_py_array (PyGIInvokeState *state,
len = g_strv_length ((gchar **)arg->v_pointer);
}
} else {
- GIArgument *len_arg = state->args[seq_cache->len_arg_index];
+ GIArgument *len_arg = state->args[array_cache->len_arg_index];
PyGIArgCache *arg_cache = _pygi_callable_cache_get_arg (callable_cache,
- seq_cache->len_arg_index);
+ array_cache->len_arg_index);
if (!gi_argument_to_gsize (len_arg, &len, arg_cache->type_tag)) {
return NULL;
@@ -152,7 +153,7 @@ _pygi_marshal_to_py_array (PyGIInvokeState *state,
array_ = g_array_new (FALSE,
FALSE,
- seq_cache->item_size);
+ array_cache->item_size);
if (array_ == NULL) {
PyErr_NoMemory ();
@@ -204,7 +205,7 @@ _pygi_marshal_to_py_array (PyGIInvokeState *state,
* and move on, letting the per-item marshaler deal with the
* various transfer modes and ref counts (e.g. g_variant_ref_sink).
*/
- if (seq_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY) {
+ if (array_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY) {
item_arg.v_pointer = g_ptr_array_index ( ( GPtrArray *)array_, i);
} else if (item_arg_cache->is_pointer) {
@@ -243,7 +244,7 @@ _pygi_marshal_to_py_array (PyGIInvokeState *state,
if (py_item == NULL) {
Py_CLEAR (py_obj);
- if (seq_cache->array_type == GI_ARRAY_TYPE_C)
+ if (array_cache->array_type == GI_ARRAY_TYPE_C)
g_array_unref (array_);
goto err;
@@ -254,13 +255,13 @@ _pygi_marshal_to_py_array (PyGIInvokeState *state,
}
}
- if (seq_cache->array_type == GI_ARRAY_TYPE_C)
+ if (array_cache->array_type == GI_ARRAY_TYPE_C)
g_array_free (array_, FALSE);
return py_obj;
err:
- if (seq_cache->array_type == GI_ARRAY_TYPE_C) {
+ if (array_cache->array_type == GI_ARRAY_TYPE_C) {
g_array_free (array_, arg_cache->transfer == GI_TRANSFER_EVERYTHING);
} else {
/* clean up unprocessed items */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]