[comp.lang.c++] Overloading [] to read and write to a bit array

heintze.peewee.enet.dec.com (Sieg Heintze) (07/03/90)

Can someone provide an example of overloading the [] operator to read as well 
as write to a bit array?

There is a problem with writing to the bit array because your inclined to 
write a function of type &bit.  Of course this doesn't work.  

Actually, what I really want is to access my VGA video memory with the [] 
operater.  This would actually be a two dimensional array of 4 bit entities 
(nibbles).  Currrently, we have to do some pretty low level stuff everytime we 
have to access this video memory.   If C++ truly is OOP, we should be able to 
hide these ugly idiosynchrousies (sp?) inside the [] operator.

							Sieg

heintze@genral.enet.dec.com
Digital Equipment Corporation
1110 Chapel Hills Drive  CXN2-2/35
Colorado Springs, CO 80920-3995
719-260-2184

niklas@appli.se (Niklas Hallqvist) (07/04/90)

In <13053@shlump.nac.dec.com> Sieg Heintze writes:
>Can someone provide an example of overloading the [] operator to read as well 
>as write to a bit array?

The trick is to implement Bit as a memory pointer and a bit offset and
define "operator=" and "operator int()" on that class, then have BitArray
"operator[]" return a Bit.

The following code implements this scheme and works if compiled with G++ 1.37.1
under NCR Tower32 650 Sys V.3.  The code have some questions commented-in,
please mail if you have answers to them (or post if you think it's of public
interest).

// Example of Bit handling in memory buffers by Niklas Hallqvist 900704
// This program compiled and worked under G++ 1.37.1
#include <std.h>
#include <stream.h>

class Bit {
public:
  Bit(const int&, const int);	// Is const int& what I mean?
  Bit(const Bit&);
  Bit& operator=(const int);
  operator int();
private:
  int& word;
  int offset;
};

Bit::Bit(const int &wrd, const int offs) : word(wrd), offset(offs)
{ }

Bit::Bit(const Bit& value) : word(value.word), offset(value.offset)
{ }

Bit& Bit::operator=(const int value)
{
  word &= ~(1 << offset);
  word |= ((value & 1) << offset);
  return *this;
}

int Bit::operator int()
{ return (word >> offset) & 1; }

class BitArray {
public:
  BitArray(const int);
  ~BitArray();
  Bit operator[](const int);
  void print_internal_representation(void);
protected:
  const int length;
  const int size;
  int* const buffer;
};

const int bits_per_int = 8 * sizeof(int);

BitArray::BitArray(const int sz) :
size(sz),
length((size + bits_per_int - 1) / bits_per_int),
buffer(new int[length])
{
  for(int i = 0; i < length; i++) // Should this zeroing be necessary? My new
    buffer[i] = 0;		  // doesn't seem to return zeroed memory!
}

BitArray::~BitArray()
{ delete buffer; }		// Should this read: delete [length] buffer?

// When does this Bit get destroyed?  We need it to live until we've used it
// in the expression where the operator gets called.
Bit BitArray::operator[](const int index)
{ return Bit(buffer[index / bits_per_int], index % bits_per_int); }

void BitArray::print_internal_representation(void)
{
  for(int i = 0; i < length; i++)
    cout << buffer[i] << ' ';
  cout << '\n';
}

int main(void)
{
  const int max = 12;
  BitArray a(max);
  int i;
  a.print_internal_representation();
  for(i = 0; i < max; i += 2) {
    a[i] = 1;
    a.print_internal_representation();
  }
  for(i = 0; i < max; i ++)
    cout << i << " " << a[i] << "\n";
  return 0;
}  

And here is a script of a session using this program (called bit):

$ bit
0 
1 
5 
21 
85 
341 
1365 
0 1
1 0
2 1
3 0
4 1
5 0
6 1
7 0
8 1
9 0
10 1
11 0
$

Please mail if you see two signatures below!

---
Niklas Hallqvist	Phone: +46-(0)31-19 14 85
Applitron Datasystem	Fax:   +46-(0)31-19 80 89
N. Gubberogatan 30	Email: niklas@appli.se
S-416 63  GOTEBORG	       sunic!chalmers!appli!niklas
Sweden

jimad@microsoft.UUCP (Jim ADCOCK) (07/05/90)

In article <13053@shlump.nac.dec.com> heintze.peewee.enet.dec.com (Sieg Heintze) writes:
>Actually, what I really want is to access my VGA video memory with the [] 
>operater.  This would actually be a two dimensional array of 4 bit entities 
>(nibbles).  Currrently, we have to do some pretty low level stuff everytime we 
>have to access this video memory.   If C++ truly is OOP, we should be able to 
>hide these ugly idiosynchrousies (sp?) inside the [] operator.

Below find an example of one [slightly hack] way to use operator[] on
nibbles. I assume you can take the below example of using a generalized
reference class and expand it to handle 2d arrays.

extern "C"
{
#include "stdio.h"
}

// the following example of nibble arrays assumes pointers are 32-bit quantities// -- far or flat model pointers, for example, and that the high order bit of
// the pointers aren't actually being used [ true on most computers ]

// if your talking nibbles to external hardware, beware packing order -- the
// below has a 50/50 chance of not being the order you want [but that's easy to
// fix]

class NIBLREF
{
public:
	unsigned long nibladdr;
	NIBLREF(const NIBLREF& n) : nibladdr(n.nibladdr) {}
	NIBLREF(unsigned long n) : nibladdr(n) {}
	// i assumed to be a valid nibble without checking
	NIBLREF& operator=(const int i) 
	{ 
		unsigned char& c = *(unsigned char*)(nibladdr>>1);
		if (nibladdr & 1)
		{
			c &= 0x0F;
			c |= i << 4;
		}
		else
		{
			c &= 0xF0;
			c |= i;
		}
		return *this;
	}
	operator int() 
	{
		unsigned char& c = *(unsigned char*)(nibladdr>>1);
		return (nibladdr & 1) ?
			(c >> 4)
		:
			(c & 0x0F);
	}
};

class NIBLARY
{
public:
	const unsigned char* p;
	NIBLARY(int i) : p(new unsigned char[i]) {}
	~NIBLARY() { delete (void*)p; }
	NIBLREF operator[](int i) { return (((unsigned long)p)<<1) + i; }
};

main()
{
	NIBLARY n1(100);
	NIBLARY n2(100);

	int i;
	for (i=0; i<100; ++i)
		n1[i] = i % 10;

	for (i=0; i<100; ++i)
		n2[i] = n1[i];

	for (i=0; i<100; ++i)
		printf("%d\n", (int)n2[i]);
}

jimad@microsoft.UUCP (Jim ADCOCK) (07/06/90)

In article <55655@microsoft.UUCP> jimad@microsoft.UUCP (Jim ADCOCK) writes:
>	NIBLARY(int i) : p(new unsigned char[i]) {}
should be:
>	NIBLARY(int i) : p(new unsigned char[(i+1)>>1]) {}
of course, *sigh*

roger@procase.UUCP (Roger H. Scott) (07/11/90)

In article <13053@shlump.nac.dec.com> heintze.peewee.enet.dec.com (Sieg Heintze) writes:
>Can someone provide an example of overloading the [] operator to read as well 
>as write to a bit array?
This topic (effectively) was discussed fairly thoroughly several months ago.
I have a fairly nifty solution to this, but I'd rather not type it in again
unless you can't find the original.