delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1997/03/10/12:32:33

From: Shawn Hargreaves <Shawn AT talula DOT demon DOT co DOT uk>
Newsgroups: comp.os.msdos.djgpp
Subject: 'Smart' far pointers in C++
Date: Mon, 10 Mar 1997 14:27:31 +0000
Organization: None
Distribution: world
Message-ID: <1vA+sDATpBJzEwIJ@talula.demon.co.uk>
NNTP-Posting-Host: talula.demon.co.uk
MIME-Version: 1.0
Lines: 295
To: djgpp AT delorie DOT com
DJ-Gateway: from newsgroup comp.os.msdos.djgpp

It just occured to me that in C++ it would be possible to write a wrapper
class for the routines in <sys/farptr.h>, that makes them behave very much
like normal C pointers. So I tried it, and it does indeed work!

I've implemented three classes, a farptrb, farptrw, and farptrl. They use
the _farns*() functions, so you must use _farsetsel() to load the
appropriate selector into %fs.

With these classes you can use normal array syntax to dereference far
pointers, do pointer arithmetic, and can use most of the standard
arithmetic and comparison operators, both on the pointers themselves and
on the locations they point to. I'm sure I've missed a lot of operators
that should be overloaded, though: improvements are very welcome...

Example of drawing random pixels to the VGA screen:

   farptrb ptr(0xA0000);

   _farsetsel(_dos_ds);

   for (int y=0; y<200; y++)
      for (int x=0; x<320; x++)
         ptr[x+y*320] = rand();


Here's the code. Don't worry about the complexity of returning a reference
class from the overloaded [] operator: it produces _horrible_ code when
compiled without optimisation, but disappears entirely when you add -O.


#include <sys/farptr.h>


#define DECLARE_FARPTR(name, refname, type, suffix, size)               \
                                                                        \
                                                                        \
/* the overloaded [] operator returns this reference class  */          \
class refname                                                           \
{                                                                       \
   friend class name;                                                   \
                                                                        \
public:                                                                 \
   operator type() const {                                              \
      return _farnspeek##suffix(addr);                                  \
   }                                                                    \
                                                                        \
   const refname& operator = (const type x) const {                     \
      _farnspoke##suffix(addr, x);                                      \
      return *this;                                                     \
   }                                                                    \
                                                                        \
   const refname& operator += (const type x) const {                    \
      _farnspoke##suffix(addr, _farnspeek##suffix(addr) + x);           \
      return *this;                                                     \
   }                                                                    \
                                                                        \
   const refname& operator -= (const type x) const {                    \
      _farnspoke##suffix(addr, _farnspeek##suffix(addr) - x);           \
      return *this;                                                     \
   }                                                                    \
                                                                        \
   const refname& operator *= (const type x) const {                    \
      _farnspoke##suffix(addr, _farnspeek##suffix(addr) * x);           \
      return *this;                                                     \
   }                                                                    \
                                                                        \
   const refname& operator /= (const type x) const {                    \
      _farnspoke##suffix(addr, _farnspeek##suffix(addr) / x);           \
      return *this;                                                     \
   }                                                                    \
                                                                        \
   const refname& operator |= (const type x) const {                    \
      _farnspoke##suffix(addr, _farnspeek##suffix(addr) | x);           \
      return *this;                                                     \
   }                                                                    \
                                                                        \
   const refname& operator &= (const type x) const {                    \
      _farnspoke##suffix(addr, _farnspeek##suffix(addr) & x);           \
      return *this;                                                     \
   }                                                                    \
                                                                        \
   const refname& operator ^= (const type x) const {                    \
      _farnspoke##suffix(addr, _farnspeek##suffix(addr) ^ x);           \
      return *this;                                                     \
   }                                                                    \
                                                                        \
   const refname& operator ++ () const {                                \
      _farnspoke##suffix(addr, _farnspeek##suffix(addr) + 1);           \
      return *this;                                                     \
   }                                                                    \
                                                                        \
   const refname& operator -- () const {                                \
      _farnspoke##suffix(addr, _farnspeek##suffix(addr) - 1);           \
      return *this;                                                     \
   }                                                                    \
                                                                        \
   inline friend type operator + (const refname x, const refname y) {   \
      return _farnspeek##suffix(x.addr) + _farnspeek##suffix(y.addr);   \
   }                                                                    \
                                                                        \
   inline friend type operator - (const refname x, const refname y) {   \
      return _farnspeek##suffix(x.addr) - _farnspeek##suffix(y.addr);   \
   }                                                                    \
                                                                        \
   inline friend type operator * (const refname x, const refname y) {   \
      return _farnspeek##suffix(x.addr) * _farnspeek##suffix(y.addr);   \
   }                                                                    \
                                                                        \
   inline friend type operator / (const refname x, const refname y) {   \
      return _farnspeek##suffix(x.addr) / _farnspeek##suffix(y.addr);   \
   }                                                                    \
                                                                        \
   inline friend type operator | (const refname x, const refname y) {   \
      return _farnspeek##suffix(x.addr) | _farnspeek##suffix(y.addr);   \
   }                                                                    \
                                                                        \
   inline friend type operator & (const refname x, const refname y) {   \
      return _farnspeek##suffix(x.addr) & _farnspeek##suffix(y.addr);   \
   }                                                                    \
                                                                        \
   inline friend type operator ^ (const refname x, const refname y) {   \
      return _farnspeek##suffix(x.addr) ^ _farnspeek##suffix(y.addr);   \
   }                                                                    \
                                                                        \
   inline friend type operator + (const refname x, const type y) {      \
      return _farnspeek##suffix(x.addr) + y;                            \
   }                                                                    \
                                                                        \
   inline friend type operator - (const refname x, const type y) {      \
      return _farnspeek##suffix(x.addr) - y;                            \
   }                                                                    \
                                                                        \
   inline friend type operator * (const refname x, const type y) {      \
      return _farnspeek##suffix(x.addr) * y;                            \
   }                                                                    \
                                                                        \
   inline friend type operator / (const refname x, const type y) {      \
      return _farnspeek##suffix(x.addr) / y;                            \
   }                                                                    \
                                                                        \
   inline friend type operator | (const refname x, const type y) {      \
      return _farnspeek##suffix(x.addr) | y;                            \
   }                                                                    \
                                                                        \
   inline friend type operator & (const refname x, const type y) {      \
      return _farnspeek##suffix(x.addr) & y;                            \
   }                                                                    \
                                                                        \
   inline friend type operator ^ (const refname x, const type y) {      \
      return _farnspeek##suffix(x.addr) ^ y;                            \
   }                                                                    \
                                                                        \
   inline friend int operator == (const refname x, const refname y) {   \
      return (_farnspeek##suffix(x.addr) == _farnspeek##suffix(y.addr));\
   }                                                                    \
                                                                        \
   inline friend int operator != (const refname x, const refname y) {   \
      return (_farnspeek##suffix(x.addr) != _farnspeek##suffix(y.addr));\
   }                                                                    \
                                                                        \
   inline friend int operator < (const refname x, const refname y) {    \
      return (_farnspeek##suffix(x.addr) < _farnspeek##suffix(y.addr)); \
   }                                                                    \
                                                                        \
   inline friend int operator > (const refname x, const refname y) {    \
      return (_farnspeek##suffix(x.addr) > _farnspeek##suffix(y.addr)); \
   }                                                                    \
                                                                        \
   inline friend int operator <= (const refname x, const refname y) {   \
      return (_farnspeek##suffix(x.addr) <= _farnspeek##suffix(y.addr));\
   }                                                                    \
                                                                        \
   inline friend int operator >= (const refname x, const refname y) {   \
      return (_farnspeek##suffix(x.addr) >= _farnspeek##suffix(y.addr));\
   }                                                                    \
                                                                        \
   inline friend int operator == (const refname x, const type y) {      \
      return (_farnspeek##suffix(x.addr) == y);                         \
   }                                                                    \
                                                                        \
   inline friend int operator != (const refname x, const type y) {      \
      return (_farnspeek##suffix(x.addr) != y);                         \
   }                                                                    \
                                                                        \
   inline friend int operator < (const refname x, const type y) {       \
      return (_farnspeek##suffix(x.addr) < y);                          \
   }                                                                    \
                                                                        \
   inline friend int operator > (const refname x, const type y) {       \
      return (_farnspeek##suffix(x.addr) > y);                          \
   }                                                                    \
                                                                        \
   inline friend int operator <= (const refname x, const type y) {      \
      return (_farnspeek##suffix(x.addr) <= y);                         \
   }                                                                    \
                                                                        \
   inline friend int operator >= (const refname x, const type y) {      \
      return (_farnspeek##suffix(x.addr) >= y);                         \
   }                                                                    \
                                                                        \
private:                                                                \
   refname(const unsigned long x) { addr = x; }                         \
                                                                        \
   unsigned long addr;                                                  \
};                                                                      \
                                                                        \
                                                                        \
/* the actual pointer class */                                          \
class name                                                              \
{                                                                       \
public:                                                                 \
   name() { addr = 0; }                                                 \
   name(const unsigned long x) { addr = x; }                            \
                                                                        \
   operator unsigned long() { return addr; }                            \
                                                                        \
   name& operator = (const unsigned long x) {                           \
      addr = x;                                                         \
      return *this;                                                     \
   }                                                                    \
                                                                        \
   name& operator += (const unsigned long x) {                          \
      addr += (x * size);                                               \
      return *this;                                                     \
   }                                                                    \
                                                                        \
   name& operator -= (const unsigned long x) {                          \
      addr -= (x * size);                                               \
      return *this;                                                     \
   }                                                                    \
                                                                        \
   name& operator ++ () {                                               \
      addr += size;                                                     \
      return *this;                                                     \
   }                                                                    \
                                                                        \
   name& operator -- () {                                               \
      addr -= size;                                                     \
      return *this;                                                     \
   }                                                                    \
                                                                        \
   inline friend name operator + (const name x, const unsigned long y) {\
      return name(x.addr + (y * size));                                 \
   }                                                                    \
                                                                        \
   inline friend name operator - (const name x, const unsigned long y) {\
      return name(x.addr - (y * size));                                 \
   }                                                                    \
                                                                        \
   inline friend int operator == (const name x, const name y) {         \
      return (x.addr == y.addr);                                        \
   }                                                                    \
                                                                        \
   inline friend int operator != (const name x, const name y) {         \
      return (x.addr != y.addr);                                        \
   }                                                                    \
                                                                        \
   inline friend int operator <  (const name x, const name y) {         \
      return (x.addr <  y.addr);                                        \
   }                                                                    \
                                                                        \
   inline friend int operator >  (const name x, const name y) {         \
      return (x.addr >  y.addr);                                        \
   }                                                                    \
                                                                        \
   inline friend int operator <= (const name x, const name y) {         \
      return (x.addr <= y.addr);                                        \
   }                                                                    \
                                                                        \
   inline friend int operator >= (const name x, const name y) {         \
      return (x.addr >= y.addr);                                        \
   }                                                                    \
                                                                        \
   const refname operator [] (int i) {                                  \
      return refname(addr + (i * size));                                \
   }                                                                    \
                                                                        \
   const refname operator * () {                                        \
      return refname(addr);                                             \
   }                                                                    \
                                                                        \
protected:                                                              \
   unsigned long addr;                                                  \
};


/* build versions of the class for byte, word, and long accesses */
DECLARE_FARPTR(farptrb, _farptrbref, unsigned char,  b, 1)
DECLARE_FARPTR(farptrw, _farptrwref, unsigned short, w, 2)
DECLARE_FARPTR(farptrl, _farptrlref, unsigned long,  l, 4)


#undef DECLARE_FARPTR


- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019