Source: Segment.hh


Annotated List
Files
Globals
Hierarchy
Index
// Segment - weak Vector
// Copyright (C) 1998,1999 Colin McCormack,
// see LICENSE (MD5 f5220f8f599e5e926f37cf32efe3ab68) for terms
// 	$Id: Segment_hh.html,v 1.1.1.1 2000/04/09 01:07:51 skeptopotamus Exp $	

#ifndef SEGMENT_HH
#define SEGMENT_HH

#include <string.h>
//#include <qvmm.h>
#include <assert.h>

template <class T>
class TupleBase;

/** Segment<T> templated class for weak @see Vector

    A Segment<T> is a pair (T *start, length) designed to implement a
    weak Vector<T> (that is, one which doesn't manage its own storage)

    Segment may be constructed from a length, an explicit (start,len) pair,
    or another Segment

    Segment may only be constructed by a derived type.

    Segment performs no content manipulation in its operation,
    nor bounds checking, but defines the predicate segEncloses
    for that purpose in a derived type.
*/
template <class T>
class Segment
{
protected:
    /** start of segment (or (T*)0)
     */
    T *start;

    /** length of segment (or 0)
     */
    int len;

    /** explicitly set the segment's value
     */
    void set(T* t, int size=0);

public:
    //////////////////////////////////////////////
    // Simple Constructors

    /** default constructor - NULL segment
     */
    Segment()
        : start((T*)0), len(0) {}

    /** construct a singleton Segment
     */
    Segment(T &thing)
        : start(&thing), len(1) {}

    /** construct a Segment conforming to a @see TupleBase
     */
    Segment(TupleBase<T> &t)
        : start(t.content()), len(t.Length()) {}

    /** construct a Segment conforming to a @see TupleBase
     */
    Segment(TupleBase<T> *t)
        : start(t->content()), len(t->Length()) {}

    //////////////////////////////////////////////
    // Storage operators

    /** allocate an array of T's
     */
    static T *alloc(int nelem, void *allocator = (void*)0);

    /** Deallocate storage pointed at by Segment
     */
    void dealloc();

    //////////////////////////////////////////////
    // Constructors
#if 0
    // allocate a new Segment of a given size (possibly NULL)
    Segment(int _len, void *allocator = (void*)0)
        : start((T*)((_len > 0)? alloc(_len, allocator) :(T*)0)), len(_len)
        {
            assert(len >= 0);
        }
#endif

    /** construct a Segment from an address/len pair
     */
    Segment(T *_start, int _len)
        : start(_start), len(_len) {
        assert(len >= 0);
    }
    
    /** Copy Constructor: construct a prefix sub-Segment of another Segment
     */
    Segment(const Segment<T> &seg, int _len = 0, int offset = 0)
        : start(seg.start + offset),
          len(seg.len - _len) {
        assert((len >= 0) && seg.segEncloses(*this));
    }
    
#if 0
    Segment<T> operator=(T *location) {		// Segment assignment
        start = location;
        len = 0;
        return *this;
    }

    Segment<T> operator=(Segment<T> *location) {	// Segment assignment
        start = location->start;
        len = location->len;
        return *this;
    }
#endif

    /** Segment assignment
     */
    Segment<T> operator=(const Segment<T> &location) {	// Segment assignment
        start = location.start;
        len = location.len;
        return *this;
    }

    //////////////////////////////////////////////
    // Limit mutators

    /** advance lower edge of Segment by amount
     */
    Segment *operator+=(int advance) {
        start += advance;
        len -= advance;
        return len?this:(Segment*)0;
    }

    /** advance lower edge of Segment by 1
     */
    Segment *operator++(int) {
        return (*this) += 1;
    }
    
public:
    
    virtual ~Segment() {}

    /** find occurrence in Segment
     */
    int search(const T* what, int whatlen, int offset = 0) const;

    /** find occurrence in Segment
     */
    int search(const T &what, int offset = 0) const {
        return search(&what, 1, offset);
    }

    /** find occurrence in Segment
     */
    int search(const T *what, int offset = 0) const {
        return search(what, T::findNull(what), offset);
    }

    /** find occurrence in Segment
     */
    int search(const Segment<T> &what, int offset = 0) const {
        return search(what.content(), what.Length(), offset);
    }

    /** find occurrence in Segment
     */
    int search(const Segment<T>* what, int offset = 0) const {
        return search(what->content(), what->Length(), offset);
    }


    //////////////////////////////////////////////
    // Element accessors

    /** Segment array accessor
     */
    T &operator[](int offset) const {
        assert(offset >= 0);
        return start[offset];
    }

    /** return in-bounds const element
     */
    const T &const_element(int index) const {
        assert((index >= 0) && (index < len));
        return start[index];
    }

    /** return in-bounds const element
     */
    T &element(int index) const {
        assert((index >= 0) && (index < len));
        return start[index];
    }

    /** Segment length
     */
    int Length() const {
        return (start) ?len: 0;
    }

    /** Segment content
     */
    T* content() const {
        return start;
    }

    /** Segment to basetype conversion
     */
    operator T* () const {
        return start;
    }
    
    ////////////////////////////////////////
    // convenience accessors
    
    /** pointer to start of Segment
     */
    T *segFirst() const {
        return start;
    }

    /** ref to first in Segment
     */
    const T &first() const {
        return *start;
    }

    /** pointer to end of Segment
     */
    T *segLast() const {
        return start + len - 1;
    }

    /** ref to last in Segment
     */
    const T &last() const {
        return start[len - 1];
    }

    //////////////////////////////////////////////
    //	predicates
    
    /** Predicate: Segment encloses a given range
     */
    bool segEncloses(const T * const _start, int _len) const {
        assert(_len > 0);
        return (_start >= start) && ((_start + _len) <= (start + len));
    }

    /** Predicate: Segment encloses another segment
     */
    bool segEncloses(Segment<T> const &seg) const {
        return segEncloses(seg.start, seg.len);
    }
    
    /** return the offset of T *t in content
     */
    int in(T *t, int tlen = 0) const {
        if (segEncloses(t, tlen)) {
            return t - start;
        } else {
            return -1;
        }
    }

    /** predicate:  Segment is empty
     */
    bool empty() const {
        return !start || (len <= 0);
    }

    /** predicate:  Segment is empty
     */
    operator bool () const {
        return empty();
    }

    //////////////////////////////////////////////
    // comparison operators
    static int cmp(const T *l, const T *r);
    int order(const Segment<T> &that) const;
    bool operator==(const Segment<T> &d) const {
        return (this == &d) || (order(d) == 0);
    }
    bool operator!=(const Segment<T> &d) const {
        return (this != &d) && (order(d) != 0);
    }
    bool operator>=(const Segment<T> &d) const {
        return (order(d) >= 0);
    }
    bool operator>(const Segment<T> &d) const {
        return (this != &d) && (order(d) > 0);
    }
    bool operator<=(const Segment<T> &d) const {
        return (this != &d) && (order(d) <= 0);
    }
    bool operator< (const Segment<T> &d) const {
        return (this != &d) && (order(d) < 0);
    }
    
    //////////////////////////////////////////////
    // element ordering operations

    /** qsort Segment contents
     */
    Segment<T> *qsort();

    /** reverse Vector
     */
    Segment<T> *reverse();

    /** bsearch sorted Vector
     */
    bool tsearch(const T &key, int &idx) const;

    ////////////////////////////////////
    // set operations on Segment

    /** Predicate: is an element a member of the set?
     */
    bool isMember(const T &d) {
        int junk;
        return tsearch(d, junk);
    }
    
protected:
    //////////////////////////////////////////////
    // accessory operators

    /** argument range modifier
     */
    int endRelative(int where) const {
        // negative where is end-relative
        return (where < 0)? len + where: where;
    }

    /** duplicate a range of basetype
     */
    T *dup(T* to, const T* from, int range);
};

#if 0
// allocate an array of T's
template <class T>
T *Segment<T>::alloc(int nelem, void *allocator)
{
    return (T*)memset(memory->alloc(nelem * sizeof(T), allocator), nelem, sizeof(T));
}

// Deallocate storage pointed at by Segment
template <class T>
void Segment<T>::dealloc()
{
    DEBLOG(cerr << memory << "->Segment<T>::dealloc(" << start << ")\n");
    memory->free(start);	// caller warrants that Segment was alloced by Segment(int)
    start = (T*)0;
    len = 0;
}
#endif

// duplicate a range of basetype
template <class T>
T *Segment<T>::dup(T* to, const T* from, int range)
{
    assert(range >= 0);
    for (int i = 0; i < range; i++) {
        *(to + i) = *(from + i);
    }
    return to;
}

template <class T>
void Segment<T>::set(T* t, int size)
{
    assert(size >= 0);
    start = t;
    len = size;
}

// compare two Segment<T>s (used by Segment::qsort and Segment::tsearch)
// find a needle in this haystack
typedef int (*Cmp)(const void*, const void*);	// qsort comparison operator type
template <class T>
int Segment<T>::cmp(const T *l, const T *r)
{
    return T::order(*l, *r);
}

// qsort Vector contents
template <class T>
Segment<T> *Segment<T>::qsort() {
    if (len) {
        ::qsort(start, len, sizeof(T), (Cmp)cmp);
    }
    //  check();
    return this;
}

// binary search sorted Segment for match
template <class T>
bool Segment<T>::tsearch(const T &key, int &idx) const
{
    if (len) {
        size_t lower = 0;
        size_t upper = len;
        while (lower < upper) {
            idx = (lower + upper) / 2;
            int comparison = cmp(&key, &element(idx));
            if (comparison < 0)
                upper = idx;
            else if (comparison > 0)
                lower = idx + 1;
            else
                return true;
        }
        return false;
    } else {
        idx = 0;
        return false;
    }
}

// reverse Segment
template <class T>
Segment<T> *Segment<T>::reverse()
{
    T tmp;
    // check();
    
    if (len) {
        for (int i = 0; i < len / 2; i++) {
            T::move(&tmp, start + i, 1);
            T::move(start + i, start + len - i - 1, 1);
            T::move(start + len - i - 1, &tmp, 1);
        }
    }
    return this;
}

// find occurrence in vector
template <class T>
int Segment<T>::search(const T* what, int whatlen, int offset) const
{
    // check();
    
    // searching for NULL always fails
    if (empty() || !what || !whatlen)
        return -1;
    
    // null terminated string
    if (whatlen < 0) {
        whatlen = T::findNull(what);
    }
    
    //what->check(whatlen);
    
    // negative where is end-relative
    if ((offset = endRelative(offset)) < 0)
        return -1;
    
    const T *found = NULL;
    if (whatlen == 1) {
        // strength reduction - single item search
        found = T::find(start + offset, *what, len - offset);
    } else {
        // segment search
        found = T::search(start + offset, what, whatlen, len - offset);
    }
    
    if (!found) {
        return -1;
    } else {
        assert(segEncloses(found, whatlen));
        return (found - start);
    }
}

// order - ordering between Segments
template <class T>
int Segment<T>::order (const Segment<T> &that) const
{
    int _cmp;
    for (int i = 0; i < Length() && i < that.Length(); i++) {
        if (!(_cmp = cmp(start + i, that.content() + i)))
            continue;
        else
            return _cmp;
    }
    return Length() - that.Length();
}

#endif

Generated by: colin@sharedtech.dhis.org on Sat Nov 6 11:59:24 199.