#ifndef already_included_string_hh
#define already_included_string_hh
#include "io.hh"
class string;
/* This class is a proxy to String_Internal, which
* holds the actual array of chars that makes up the
* string.
*
* The reason it is a proxy is so that operations
* like passing a string as an argument and returning
* a string are efficient operations.
*
* The string class does reference counting for
* collection for the String_Internal class.
*/
final class string : public Writer
{
private:
class String_Internal
{
friend bool strings_equal(const string& a, const string& b);
friend bool strings_equal(const char* a, const string& b);
friend bool strings_equal(const string& a, const char* b);
friend Writer& operator << (Writer& w, const string& s);
private:
friend class string;
const int ARRAY_SIZE = 1000;
const int MAX_LENGTH = 1000-1; // because the last char must be '\0'
int ref_count;
int length;
char array[ARRAY_SIZE]; // GUARANTEED: array[length] == 0
String_Internal() {
ref_count = 1;
length = 0;
array[0] = 0;
}
};
String_Internal* ptr;
void worker_current_down() {
ptr->ref_count--;
if (ptr->ref_count == 0) {
delete ptr;
ptr = null;
}
}
void worker_new_up(const string& s) {
ptr = s.ptr;
ptr->ref_count++;
}
void worker_mutator_clone() {
if (ptr->ref_count > 1) {
ptr->ref_count--;
String_Internal* old_ptr = ptr;
ptr = new String_Internal();
ptr->length = my_strncpy(ptr->array,old_ptr->array,
String_Internal::ARRAY_SIZE);
}
}
/* The advantage of this function over the standard
* C library strncpy is that this one returns the
* number of characters copied.
*/
static int my_strncpy(char* to, const char* from, int mem_size);
public:
/* STANDARD FOUR BASIC OPERATIONS: */
string()
{
ptr = new String_Internal();
}
string(const string& s)
{
worker_new_up(s);
}
string& operator = (const string& s)
{
worker_current_down();
worker_new_up(s);
return *this;
}
~string()
{
worker_current_down();
}
/* END STANDARD FOUR! */
/* Needed so you can write:
string s = "hello";
*/
string(const char* s)
{
ptr = new String_Internal();
ptr->length = my_strncpy(ptr->array,s,String_Internal::ARRAY_SIZE);
}
/* Needed so you can write:
string s;
s = "hello";
*/
string& operator = (const char* s)
{
worker_current_down();
ptr = new String_Internal();
ptr->length = my_strncpy(ptr->array,s,String_Internal::ARRAY_SIZE);
return *this;
}
// /* More efficient way of adding strings
// * than: string s = "abc";
// * s = s + "def";
// *
// * is: string s = "abc";
// * s += "def";
// */
// string& operator += (const string s)
// {
// worker_mutator_clone();
// ptr->length += my_strncpy(ptr->array + ptr->length,
// s.ptr->array,String_Internal::ARRAY_SIZE);
// return *this;
// }
// /* Useful when you don't want
// * to create an anonymous string:
// *
// * eg: send_message("Hello there, " + name);
// */
// friend string operator + (const string& a, const string& b)
// {
// string x;
// x = a;
// x += b;
// return x;
// }
/*
* The ONLY way to compare strings. Do not use != or ==
* The strings_equal function is also overloaded for char*'s
* it is easy to remember.
*/
friend bool strings_equal(const string& a, const string& b)
{
return (strings_equal(a.ptr->array,b.ptr->array));
}
friend bool strings_equal(const string& a, const char* b)
{
return (strings_equal(a.ptr->array,b));
}
friend bool strings_equal(const char* a, const string& b)
{
return (strings_equal(a,b.ptr->array));
}
/*
* For printing a string to output:
*
* Eg: cout << s << endl;
*/
friend Writer& operator << (Writer& w, const string& s);
/*
* For accessing legacy char* functions:
*/
char* char_star(char* s, int mem_size) const;
/*
* Fulfilling the contract of Writer:
*/
Writer& operator << (char ch);
Writer& operator << (int i);
Writer& operator << (double d);
Writer& operator << (const char* s);
/*
* Misc workers.
*/
string quoted() const;
string reversed() const;
string capitalised() const;
string substring(int start, int stop) const;
/*
* Accessing the string as an array of chars.
*/
void set_char_at(int index, char ch);
char get_char_at(int index) const;
/*
* Your friend.
*/
int get_length() const;
private:
static int number_of_errors;
};
#endif /* already_included_string_hh */
| Back |