File: [Platon] / libco / libco / co_vector.c (download)
Revision 1.3, Sun Mar 30 10:27:17 2003 UTC (21 years ago) by yenar
Changes since 1.2: +117 -70
lines
adapt to object system changes (flavours, data pointer) [co_super.h, co_tab.c, co_tab.h, co_vector.c, co_vector.h]
|
/***{{{*******************************************************************
* This file is part of libco - object library for C *
* Copyright (c) 2002 *
* Peter Rockai (yenar) <yenar@host.sk> *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 59 Temple Place, Suite 330, *
* Boston, MA 02111-1307 USA *
*******************************************************************}}}***/
/* {{{ file description */
/**
* @file co_vector.c
* @brief Vector object implementation.
**/
/* }}} */
/* {{{ includes */
#include <stdarg.h>
#include <string.h>
#include <search.h>
#include "co_vector.h"
#include "co_util.h"
#include "co_debug.h"
#include "co_conv.h"
/* }}} */
/* {{{ static prototypes */
static co_v co_vector_item_msg (co o, co s, co_id_t a, va_list ap);
static int co_vector_item_cmp (void *, void *);
typedef int (*__cmp_fnc) (const void *, const void *);
/* }}} */
#include "co_vector.cometa"
/* {{{ */
int co_vector_item_cmp (void *_o1, void *_o2)
/// Compare two vector items (for sort).
{
const co_vector_data d1 = _o1;
const co_vector_data d2 = _o2;
co_v_t v1 = d1 -> sortval;
co_v_t v2 = d2 -> sortval;
if (v1 . t != v2 . t) return 0;
switch (v1 . t) {
case co_t_int:
return ((v1 . v . _int) > (v2 . v . _int))
- ((v1 . v . _int) < (v2 . v . _int));
case co_t_long_long_p:
return ((* (v1 . v . _long_long_p)) > (* (v2 . v . _long_long_p)))
- ((* (v1 . v . _long_long_p)) < (* (v2 . v . _long_long_p)));
case co_t_char_p:
return strcoll (v1 . v . _char_p, v2 . v . _char_p);
case co_t_double_p:
return ((* (v1 . v . _double_p)) > (* (v2 . v . _double_p)))
- ((* (v1 . v . _double_p)) < (* (v2 . v . _double_p)));
case co_t_co:
// Err, FIXME?
return strcoll (co_v_format (co_t_co, v1 . v),
co_v_format (co_t_co, v2 . v));
default:
return 0;
}
}
/* }}} */
/* {{{ */
int co_vector_filter_str (co_vector_data d, void *str)
/// Decide if item contains \a str (and pass such ones through filter).
{
if (d -> sortval . t == co_t_char_p) {
return strstr (d -> sortval . v . _char_p, str) ? 1 : 0;
} else return 1;
}
/* }}} */
/* {{{ */
CO_METH (co_vector, init)
/// Constructor for co_vector.
{
co_vector td;
td = new (co_vector_s);
td -> size = td -> items = 0;
td -> data = 0;
td -> flags = CO_VECTOR_AUTODEL;
td -> sortval_arg = 0;
this -> data = td;
cox_pop (td);
CO_RETURN (int, 0);
}
/* }}} */
/* {{{ */
CO_METH (co_vector, item_get, int idx)
/// Get n-th item from vector.
{
CO_METH_INI (co_vector, item_get);
if (td -> data && idx < td -> items)
CO_RETURN (co, td -> data [idx] . o);
else
CO_RETURN (co, 0);
}
/* }}} */
/* {{{ */
CO_METH (co_vector, sort)
/// Sort the vector in ascending order according to co_vector_item_cmp.
{
int i;
CO_METH_INI (co_vector, sort);
if (! td -> items) CO_RETURN (int, 0);
// v -> sortt = CO_M (v -> data [0] . o, sortt_get,
// v -> sortval_arg) . t;
for (i = 0; i < td -> items; i ++) {
M (td -> data [i] . o, sortval,
&(td -> data [i] . sortval), td -> sortval_arg);
}
qsort (td -> data, td -> items, sizeof (co_vector_data_s),
(__cmp_fnc) co_vector_item_cmp);
CO_RETURN (int, 0);
}
/* }}} */
/* {{{ */
CO_METH (co_vector, item_add, co add)
/// Append new item at end of vector.
{
CO_METH_INI (co_vector, item_add);
if (! td -> data || ! td -> size) {
td -> size = 16;
td -> data = new_ar_p (co_vector_data_s, 16);
}
if (td -> items == td -> size) {
td -> size *= 2; // grow array
td -> data = realloc (td -> data, td -> size * sizeof
(co_vector_data_s));
}
td -> data [td -> items] . o = add;
// td -> data [td -> items] . vector = this;
td -> items ++;
CO_RETURN (int, 0);
}
/* }}} */
/* {{{ */
CO_METH (co_vector, item_remove, int j)
/// Remove item from n-th position of vector
/**
* All subsequent items are moved - this means that it isn't best idea to
* empty vector by removing first item while not empty :).
**/
{
int i;
CO_METH_INI (co_vector, item_remove);
for (i = j; i + 1 < td -> items; i ++) {
td -> data [i] = td -> data [i + 1];
}
td -> items --;
CO_RETURN (int, 0);
}
/* }}} */
/* {{{ */
CO_METH (co_vector, filter, co nw, co_vector_filter_f f, void *user)
/// Sort the vector in ascending order according to co_vector_item_cmp.
{
int i;
CO_METH_INI (co_vector, filter);
((co_vector) nw) -> flags &= ~ CO_VECTOR_AUTODEL; // FIXME?
M (nw, reset);
if (! td -> items)
CO_RETURN (int, 0);
for (i = 0; i < td -> items; i ++) {
M (td -> data [i] . o, sortval,
&(td -> data [i] . sortval), td -> sortval_arg);
if (f (td -> data + i, user)) {
M (nw, item_add, td -> data [i] . o);
}
}
CO_RETURN (int, 0);
}
/* }}} */
/* {{{ */
CO_METH (co_vector, default)
/// Sort the vector in ascending order according to co_vector_item_cmp.
{
CO_METH_INI (co_vector, default);
CO_RETURN (int, 0);
}
/* }}} */
/* {{{ */
CO_METH (co_vector_item, init)
/// Constructor for co_vector.
{
co_vector_item td;
td = new (co_vector_item_s);
td -> t = co_t_void;
td -> v . _int = 0;
this -> data = td;
cox_pop (td);
CO_RETURN (int, 0);
}
/* }}} */
/* {{{ */
CO_METH (co_vector_item, bless, co_type t)
{
CO_METH_INI (co_vector_item, bless);
td -> t = t;
switch (t) {
case co_t_int:
td -> v . _int = va_arg (ap, int);
break;
case co_t_char_p:
td -> v . _char_p = va_arg (ap, char *);
break;
case co_t_long_long_p:
td -> v . _long_long_p = va_arg (ap, long long *);
break;
default:
COX_THROW (fixme);
}
// CO_DEBUG (5, "our int value is: %lld", * (vi -> v . long_long_p));
// CO_BLESS_M (vi, co_vector_item);
CO_RETURN (int, 0);
}
/* }}} */
/* {{{ */
CO_METH (co_vector_item, sortval, co_v_t *out)
{
CO_METH_INI (co_vector_item, sortval);
*out = *((co_v_t *)(&(td -> t)));
CO_RETURN (int, 0);
}
/* }}} */
#if 0
/* {{{ */
CO_METH (co_vector, dup)
{
int i;
co_vector nw;
CO_METH_INI (co_vector, dup);
nw = N (co_vector);
for (i = 0; i < td -> items; i ++) {
M (nw, item_add, td -> data [i] . o);
}
nw -> sortval_arg = td -> sortval_arg;
CO_RETURN (co, nw);
}
/* }}} */
/* {{{ */
int co_vector_item_cmp_f (void *_o1, void *_o2)
{
return co_vector_item_cmp (_o1, _o2) > 0;
}
/* }}} */
/* {{{ */
static int ptr_cmp (co_vector_data a, co_vector_data b)
{
return a -> o == b -> o;
}
/* }}} */
/* {{{ */
static co_vr vechar_p (const co o, co_id_t p)
{
const co_vector v = o;
CO_PH_BEGIN;
CO_PH_RET (p, nitems, _int, v -> items);
CO_PH_RET (p, flags, _int, v -> flags);
CO_PH_DEFAULT (p);
}
/* }}} */
/* {{{ */
co_v co_vector_msg (co o, co s, co_id_t a, va_list ap)
/// Handle incoming message for table.
{
co_vector v = o;
co_v rv;
va_list ap2;
__va_copy (ap2, ap);
rv . i = 0xBAD0;
CO_MH_BEGIN;
CO_MH_CASE (a, item_get) {
int idx = va_arg (ap, int);
if (v -> data && idx < v -> items)
rv . o = v -> data [idx] . o;
else
rv . o = 0;
}
CO_MH_CASE (a, item_str_get) {
int idx = va_arg (ap, int);
co _o = v -> data [idx] . o;
rv = CO_M (_o, strval);
}
CO_MH_CASE (a, item_add) vec_item_add (o, va_arg (ap, co));
CO_MH_CASE (a, item_remove) vec_item_remove (o, va_arg (ap, int));
CO_MH_CASE (a, sort) vec_sort (o);
CO_MH_CASE (a, dup) rv . o = vec_dup (o);
CO_MH_CASE (a, filter) {
co v = va_arg (ap, co);
co_vector_filter f = va_arg (ap, co_vector_filter);
void *user = va_arg (ap, void *);
vec_filter (o, v, f, user);
}
CO_MH_CASE (a, bsearch) {
co key = va_arg (ap, co);
co res;
res = bsearch (&key, v -> data, v -> items, sizeof (co),
(__cmp_fnc) co_vector_item_cmp);
rv . i = res ? (((void *)res) -
((void *)(v -> data))) / sizeof (co) : 0;
}
CO_MH_CASE (a, find_ptr) {
co _key = va_arg (ap, co);
co_vector_data_s key, *res;
key . o = _key;
res = lfind (&key, v -> data, v -> items,
sizeof (co_vector_item_s), (__cmp_fnc) ptr_cmp);
rv . i = res ? (res - v -> data) / sizeof (co_vector_item_s) : -1;
}
CO_MH_CASE (a, ffind) {
co key = va_arg (ap, co);
co res;
res = lfind (&key, v -> data, &v -> items, sizeof (co),
(__cmp_fnc) co_vector_item_cmp_f);
rv . i = res ? (((void *)res) -
((void *)(v -> data))) / sizeof (co) : 0;
}
CO_MH_CASE (a, reset) {
if (v -> flags & CO_VECTOR_AUTODEL) {
unsigned i;
for (i = 0; i < v -> items; i ++)
co_del (v -> data [i] . o);
}
v -> items = 0;
}
CO_MH_CASE (a, destroy) {
CO_M (o, reset);
sfree (v -> data);
free (v);
}
CO_MH_UNHANDLED (a);
return rv;
}
/* }}} */
/* {{{ */
co_vector_item co_vector_item_new (co_type t, ...)
{
co_vector_item vi;
va_list ap;
va_start (ap, t);
vi = new (co_vector_item_s);
vi -> t = t;
switch (t) {
case co_t_int: vi -> v . _int = va_arg (ap, int); break;
case co_t_char_p: vi -> v . _char_p = va_arg (ap, char *); break;
case co_t_long_long_p: vi -> v . _long_long_p = va_arg (ap, long long *); break;
default: COX_THROW (fixme);
}
// CO_DEBUG (5, "our int value is: %lld", * (vi -> v . long_long_p));
CO_BLESS_M (vi, co_vector_item);
va_end (ap);
return vi;
}
/* }}} */
/* {{{ */
co_v co_vector_item_msg (co o, co s, co_id_t a, va_list ap)
{
co_vector_item vi = o;
co_v rv;
va_list ap2;
rv . _int = 0xBAD0;
__va_copy (ap2, ap);
(void) s;
CO_MH_BEGIN;
CO_MH_CASE (a, sortval) {
co_v_t *out = va_arg (ap, co_v_t *);
*out = *((co_v_t *)(&(vi -> t)));
}
CO_MH_CASE (a, destroy) {
free (vi);
}
//CO_MH_UNHANDLED (a) {};
CO_MH_END;
return rv;
}
/* }}} */
#endif /* 0 */
Platon Group <platon@platon.org> http://platon.org/
|