8.2 Example

The following is a snippet from the implementation of bit arrays (bitarray.cc). Look at e. g. mozart/contrib/gdbm/gdbm.cc for an exampl of a non-system extension.

#define BITS_PER_INT (sizeof(int) * 8)
 
class BitArraypublic OZ_Extension {
private:
  int lowerBoundupperBound;
  int *array;
  ...
public:
  virtual 
  int getIdV() { return OZ_E_BITARRAY; }
 
  virtual 
  OZ_Term printV(int depth = 10) { return oz_atom("<BitArray>"); }
 
  virtual 
  OZ_Term typeV() { return oz_atom("bitArray"); }
 
  virtual 
  OZ_Term printLongV(int depth = 10, int offset = 0) {
    return  
      OZ_mkTupleC("#",4,
                  OZ_atom("bit array: "), OZ_int(upperBound - lowerBound - 1),
                  OZ_atom(" bits at "),   OZ_int((int)this));
  }
 
  virtual OZ_Return getFeatureV(OZ_Term,OZ_Term&);
  virtual OZ_Return putFeatureV(OZ_Term,OZ_Term );
 
  virtual OZ_Extension *gCollectV(void);
  virtual OZ_Extension *sCloneV(void);
  virtual void sCloneRecurseV(void) {}
  virtual void gCollectRecurseV(void) {}
 
  ...
  BitArray(int lowerint upper): OZ_Extension() {
    ...
  }
  BitArray(const BitArray *b): OZ_Extension() {
    ...
  }
  Bool checkBounds(int i) {
    return lowerBound <= i && i <= upperBound;
  }
  ...
  void set(int);
  ...
};
 
inline 
Bool oz_isBitArray(TaggedRef term) {
  return oz_isExtension(term) &&
    tagged2Extension(term)->getIdV() == OZ_E_BITARRAY;
}
 
inline 
BitArray *tagged2BitArray(TaggedRef term) {
  Assert(oz_isBitArray(term));
  return (BitArray *) tagged2Extension(term);
}
 
OZ_Extension *BitArray::gCollectV(void) {
  BitArray *ret = new BitArray(this);
  return ret;
}
 
OZ_Extension *BitArray::sCloneV(void) {
  BitArray *ret = new BitArray(this);
  return ret;
}
 
void BitArray::set(int i) {
  Assert(checkBounds(i));
  int relative = i - lowerBound;
  array[relative / BITS_PER_INT] |= 1 << (relative % BITS_PER_INT);
}
 
#define oz_declareBitArray(ARG,VAR)             \
BitArray *VAR;                                  \
{                                               \
  OZ_declareDetTerm(ARG,_VAR);                  \
  if (!OZ_isBitArray(oz_deref(_VAR))) {         \
    return OZ_typeError(ARG,"BitArray");        \
  } else {                                      \
    VAR = tagged2BitArray(OZ_deref(_VAR));      \
  }                                             \
}
 
OZ_BI_define(BIbitArray_new,2,1)
{
  OZ_declareInt(0,l);
  OZ_declareInt(1,h);
  if (l <= h)
    OZ_RETURN(OZ_extension(new BitArray(l, h)));
  else 
    return OZ_raise(E_ERROR,E_KERNEL,"BitArray.new",2,OZ_in(0),OZ_in(1));
OZ_BI_end 
 
OZ_BI_define(BIbitArray_is,1,1)
{
  OZ_declareDetTerm(0,x);
  OZ_RETURN_BOOL(oz_isBitArray(oz_deref(x)));
OZ_BI_end 
 
OZ_BI_define(BIbitArray_set,2,0)
{
  OZ_declareBitArray(0,b);
  OZ_declareInt(1,i);
  if (b->checkBounds(i)) {
    b->set(i);
    return PROCEED;
  } else 
    return OZ_raise(E_ERROR,E_KERNEL,"BitArray.index",2,OZ_in(0),OZ_in(1));
OZ_BI_end 
 
OZ_Return BitArray::getFeatureV(OZ_Term f,OZ_Termv)
{
  if (!OZ_isInt(f)) { oz_typeError(1,"int"); }
  int i = OZ_intToC(f);
  if (checkBounds(i)) {
    v = test(i)? OZ_true(): OZ_false();
    return PROCEED;
  } else {
    return OZ_raise(E_ERROR,E_KERNEL,"BitArray.index",2,
                    OZ_extension(this),f);
  }
}
 
OZ_Return BitArray::putFeatureV(OZ_Term f,OZ_Term v)
{
  if (!OZ_isInt(f)) { oz_typeError(1,"int"); }
  int i = OZ_intToC(f);
  if (!checkBounds(i)) {
    return oz_raise(E_ERROR,E_KERNEL,"BitArray.index",2,
                    OZ_extension(this),f);
  }
  if (OZ_isVariable(v)) { OZ_suspendOn(v); }
  v = oz_deref(v);
  if (v==OZ_true()) set(i);
  else if (v==OZ_false()) clear(i);
  else { return OZ_typeError(2,"bool"); }
  return PROCEED;
}


Michael Mehl, Tobias Müller, Christian Schulte and Ralf Scheidhauer
Version 1.4.0 (20080702)