/******************************************************************************
*                                                                             *
*        Code from Item 29 ("Reference Counting") of MORE EFFECTIVE C++       *
*                                                                             *
*                               Scott Meyers                                  *   
*                                                                             *
*                             November 15, 1997                               *
*                                                                             *
*            Copyright 1996 (c) Addison-Wesley Publishing Company             *
*       You are free to use this code for non-commercial purposes only.       *
*                                                                             *
* This page contains the code for the classes and class templates making up   *
* the Reference Counting Item of MORE EFFECTIVE C++.  To use this code,       *
* either copy this page and paste it into a C++ source file or save the       *
* entire page as text into a C++ source file.  Don't save the HTML source     *
* and expect that to compile :-)                                              *
*                                                                             *
* Each class or template in this file follows a block comment that shows the  *
* corresponding pages in the book.  This page also contains a main function   *
* that performs a VERY limited test of the code in this file.  You can        *
* compile the code in this file as a stand-alone program, and you should get  *
* this output:                                                                *
*                                                                             *
*     String with no changes.                                                 *
*     String with    changes.                                                 *
*     10                                                                      *
*     -1                                                                      *
*                                                                             *
* The code here reflects all changes made to date in response to bug reports  *
* from readers of the book.  (To see a complete list of known bugs in MORE    *
* EFFECTIVE C++, as well as whether they've been fixed yet, visit the         *
* More Effective C++ Errata List.)  If you find any additional bugs, please   *
* send them to me.                                                            *
******************************************************************************/
#include <iostream.h>    // The iostream facilities are not used in the classes
                         // in this file, but they are used in the code that 
                         // tests the classes.

#include <string.h>      // This includes the C string functions, e.g.,
                         // strlen, strcpy, etc.  They are used in the
                         // implementation of class String::StringValue.

// The following is for compilers that don't support bool.  Comment these
// lines out if your compilers do support bool.  For details on this emulation
// of bool, see More Effective C++, pp. 3-4.
typedef int bool;
const bool false = 0;
const bool true = 1;

/******************************************************************************
*                       Class RCObject (from pp. 204-205)                     *
******************************************************************************/
class RCObject {                       // base class for reference-
public:                                // counted objects
  void addReference();
  void removeReference();
  void markUnshareable();
  bool isShareable() const;
  bool isShared() const;

protected:
  RCObject();
  RCObject(const RCObject& rhs);
  RCObject& operator=(const RCObject& rhs);
  virtual ~RCObject() = 0;

private:
  int refCount;
  bool shareable;
};

RCObject::RCObject()
: refCount(0), shareable(true) {}

RCObject::RCObject(const RCObject&)
: refCount(0), shareable(true) {}

RCObject& RCObject::operator=(const RCObject&)
{
  return *this;
}  

RCObject::~RCObject() {}

void RCObject::addReference() 
{
  ++refCount;
}

void RCObject::removeReference()
{
  if (--refCount == 0) delete this;
}

void RCObject::markUnshareable()
{
  shareable = false;
}

bool RCObject::isShareable() const
{
  return shareable;
}

bool RCObject::isShared() const
{
  return refCount > 1;
}  


/******************************************************************************
*                 Template Class RCPtr (from pp. 203, 206)                    *
******************************************************************************/
template<class T>                      // template class for smart
class RCPtr {                          // pointers-to-T objects; T
public:                                // must support the RCObject interface
  RCPtr(T* realPtr = 0);
  RCPtr(const RCPtr& rhs);
  ~RCPtr();
  RCPtr& operator=(const RCPtr& rhs);                     
  T* operator->() const;
  T& operator*() const;

private:
  T *pointee;
  void init();
};

template<class T>
void RCPtr<T>::init()
{
  if (pointee == 0) return;
  
  if (pointee->isShareable() == false) {
    pointee = new T(*pointee);
  }
  
  pointee->addReference();
}

template<class T>
RCPtr<T>::RCPtr(T* realPtr)
: pointee(realPtr)
{
  init();
}

template<class T>
RCPtr<T>::RCPtr(const RCPtr& rhs)
: pointee(rhs.pointee)
{ 
  init();
}

template<class T>
RCPtr<T>::~RCPtr()
{
  if (pointee) pointee->removeReference();
}

template<class T>
RCPtr<T>& RCPtr<T>::operator=(const RCPtr& rhs)
{
  if (pointee != rhs.pointee) {                   
    if (pointee) pointee->removeReference();                

    pointee = rhs.pointee;
    init(); 
  }
  
  return *this;
}

template<class T>
T* RCPtr<T>::operator->() const 
{
  return pointee;
}

template<class T>
T& RCPtr<T>::operator*() const
{
  return *pointee;
}


/******************************************************************************
*           Classes String and StringValue (from pp. 204, 206-207)            *
******************************************************************************/
class String {                          // class to be used by
public:                                 // application developers
  String(const char *value = "");

  char operator[](int index) const;       
  char& operator[](int index);

private:
  // class representing string values
  struct StringValue: public RCObject {
    char *data;
    
    StringValue(const char *initValue);
    StringValue(const StringValue& rhs);
    void init(const char *initValue);
    ~StringValue();
  };

  RCPtr<StringValue> value;                       

  // This function is not in the book, but it's convenient for testing the
  // class -- see below.
  friend ostream& operator<<(ostream& stream, const String& string);
};

void String::StringValue::init(const char *initValue)
{
  data = new char[strlen(initValue) + 1];
  strcpy(data, initValue);
}

String::StringValue::StringValue(const char *initValue)
{ 
  init(initValue);
}

String::StringValue::StringValue(const StringValue& rhs)
{
  init(rhs.data);
}

String::StringValue::~StringValue()
{
  delete [] data;
}


String::String(const char *initValue)
: value(new StringValue(initValue)) {}

char String::operator[](int index) const
{
  return value->data[index];
}

char& String::operator[](int index)
{ 
  if (value->isShared()) {      
    value = new StringValue(value->data);
  }

  value->markUnshareable();

  return value->data[index];
}

ostream& operator<<(ostream& stream, const String& string)
{
  return stream << string.value->data;
}


/******************************************************************************
*                  Template Class RCIPtr (from pp. 209-210)                   *
*                                                                             *
* The code for RCIPtr that appeared in the first three printings of More      *
* Effective C++ had bugs.  (For details, see the More Effective C++ errata,   *
* which is available at http://www.aw.com/cp/mec++.html or via anonymous FTP  *
* from ftp.aw.com in the directory cp/mec++.)  The bugs are fixed in the      *
* code below.  Each line of code that was added or modified (compared to what *
* appeared in the first three printings of the book) is flagged.  If you have *
* the fourth or later printings of More Effective C++, you can ignore these   *
* comments, as the corrected code already appears in your book.               *
******************************************************************************/
template<class T>
class RCIPtr {
public:
  RCIPtr(T* realPtr = 0);
  RCIPtr(const RCIPtr& rhs);
  ~RCIPtr();
  RCIPtr& operator=(const RCIPtr& rhs);
  T* operator->();                           // added
  const T* operator->() const;               // modified
  T& operator*();                            // added
  const T& operator*() const;                // modified

private:
  struct CountHolder: public RCObject {
    ~CountHolder() { delete pointee; }
    T *pointee;
  };
  
  CountHolder *counter;

  void init();
  void makeCopy();                           // added
};

template<class T>
void RCIPtr<T>::init()                       // modified (the test of count
{                                            // against 0 was unnecessary
                                             // and thus removed)
  if (counter->isShareable() == false) {
    T *oldValue = counter->pointee;          // added 
    counter = new CountHolder;
    counter->pointee = new T(*oldValue);     // modified
  }

  counter->addReference();
}

template<class T>
RCIPtr<T>::RCIPtr(T* realPtr)
: counter(new CountHolder)
{ 
  counter->pointee = realPtr;
  init();
}

template<class T>
RCIPtr<T>::RCIPtr(const RCIPtr& rhs)
: counter(rhs.counter)
{
  init();
}

template<class T>
RCIPtr<T>::~RCIPtr()
{
  counter->removeReference();                // modified
}

template<class T>
RCIPtr<T>& RCIPtr<T>::operator=(const RCIPtr& rhs)
{
  if (counter != rhs.counter) {                   
    counter->removeReference();              // modified
    counter = rhs.counter;
    init();
  }
  
  return *this;
}

template<class T>
T* RCIPtr<T>::operator->()                     // this whole function is added
{
  makeCopy();
  return counter->pointee;
}

template<class T>
const T* RCIPtr<T>::operator->() const         // modified
{
  return counter->pointee;
}

template<class T>
T& RCIPtr<T>::operator*()                      // this whole function is added
{
  makeCopy();
  return *(counter->pointee);
}

template<class T>
const T& RCIPtr<T>::operator*() const          // modified
{
  return *(counter->pointee);
}

template<class T>                              // This whole function is added.
void RCIPtr<T>::makeCopy()                     // Note that there is no need to
{                                              // test to see if counter->pointee
  if (counter->isShared()) {                   // is null, because this function
    T *oldValue = counter->pointee;            // is called only from 
    counter->removeReference();                // dereferencing operators
    counter = new CountHolder;
    counter->pointee = new T(*oldValue);
    counter->addReference();
  }
}


/******************************************************************************
*                          Class Widget (from p. 210)                         *
*                                                                             *
* This class is the same as that in the book, but I've added an               *
* implementation so that RCIPtr can be tested.                                *
******************************************************************************/
class Widget {
public:
  Widget(int size): value(size) {}
  Widget(const Widget& rhs): value(rhs.value) {}
  ~Widget() {}

  Widget& operator=(const Widget& rhs) { value = rhs.value;  return *this; }

  void doThis() { value = -1; }
  int showThat() const { return value; }
  
private:
  int value;
};


/******************************************************************************
*                         Class RCWidget (from p. 210)                        *
******************************************************************************/
class RCWidget {
public:
  RCWidget(int size)
  : value(new Widget(size)) {}

  void doThis() { value->doThis(); }

  int showThat() const { return value->showThat(); }

private:
  RCIPtr<Widget> value;
};


/******************************************************************************
* Functions to perform VERY simple test of the above.                         *
******************************************************************************/  
void testRCPtr()
{
  String s1 = "String with no changes.";
  String s2(s1);
  
  s2[12] = s2[13] = ' ';
  
  cout << s1 << '\n';      // prints "String with no changes."
  cout << s2 << '\n';      // prints "String with    changes."
}

void testRCIPtr()
{
  RCWidget w1(10);
  RCWidget w2(w1);

  w2.doThis();
  
  cout << w1.showThat() << '\n';       // prints 10
  cout << w2.showThat() << '\n';       // prints -1
}

int main()
{
  testRCPtr();
  testRCIPtr();

  return 0;
}