Platon Technologies
not logged in Login Registration
EnglishSlovak
open source software development celebrating 10 years of open source development! Saturday, April 20, 2024

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/
Copyright © 2002-2006 Platon Group
Site powered by Metafox CMS
Go to Top