1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
|
// Strings.
#ifndef _CL_STRING_H
#define _CL_STRING_H
#include "cl_object.h"
#include "cl_io.h"
#include "cl_abort.h"
#include <string.h>
// General, reference counted and garbage collected strings.
struct cl_heap_string : public cl_heap {
private:
unsigned long length; // length (in characters)
char data[1]; // the characters, plus a '\0' at the end
// Standard allocation disabled.
void* operator new (size_t size) { (void)size; cl_abort(); return NULL; }
// Standard deallocation disabled.
void operator delete (void* ptr) { (void)ptr; cl_abort(); }
// No default constructor.
cl_heap_string ();
private:
// Friend declarations. They are for the compiler. Just ignore them.
friend class cl_string;
friend cl_heap_string* cl_make_heap_string (unsigned long len);
friend cl_heap_string* cl_make_heap_string (const char * s);
friend cl_heap_string* cl_make_heap_string (const char * ptr, unsigned long len);
friend cl_string operator+ (const cl_string& str1, const cl_string& str2);
friend cl_string operator+ (const char* str1, const cl_string& str2);
friend cl_string operator+ (const cl_string& str1, const char* str2);
};
struct cl_string : public cl_gcpointer {
public:
// Conversion to simple string.
// NOTE! The resulting pointer is valid only as long as the string
// is live, i.e. you must keep the string in a variable until you
// are done with the pointer to the characters.
const char * asciz () const
{
return &((cl_heap_string*)pointer)->data[0];
}
// Return the length (number of characters).
unsigned long length () const
{
return ((cl_heap_string*)pointer)->length;
}
// Return a specific character.
char operator[] (unsigned long i) const
{
if (!(i < length())) cl_abort(); // Range check.
return ((cl_heap_string*)pointer)->data[i];
}
// New ANSI C++ compilers also want the following.
char operator[] (unsigned int i) const
{ return operator[]((unsigned long)i); }
char operator[] (long i) const
{ return operator[]((unsigned long)i); }
char operator[] (int i) const
{ return operator[]((unsigned long)i); }
// Constructors.
cl_string ();
cl_string (const cl_string&);
cl_string (const char * s);
cl_string (const char * ptr, unsigned long len);
// Assignment operators.
cl_string& operator= (const cl_string&);
cl_string& operator= (const char *);
// Private pointer manipulations.
operator cl_heap_string* () const;
cl_string (cl_heap_string* str) { pointer = str; }
cl_string (cl_private_thing p) : cl_gcpointer (p) {}
};
CL_DEFINE_COPY_CONSTRUCTOR2(cl_string,cl_gcpointer)
CL_DEFINE_ASSIGNMENT_OPERATOR(cl_string,cl_string)
inline cl_string::cl_string (const char * s)
{
pointer = cl_make_heap_string(s);
}
inline cl_string& cl_string::operator= (const char * s)
{
cl_heap_string* tmp = cl_make_heap_string(s);
cl_dec_refcount(*this);
pointer = tmp;
return *this;
}
// Length.
inline unsigned long strlen (const cl_string& str)
{
return str.length();
}
// Conversion to `const char *'.
inline const char * asciz (const char * s) { return s; }
inline const char * asciz (const cl_string& s) { return s.asciz(); }
// Comparison.
inline bool equal (const cl_string& str1, const cl_string& str2)
{
return str1.length() == str2.length()
&& !strcmp(str1.asciz(), str2.asciz());
}
inline bool equal (const char * str1, const cl_string& str2)
{
return !strcmp(str1, str2.asciz());
}
inline bool equal (const cl_string& str1, const char * str2)
{
return !strcmp(str1.asciz(), str2);
}
// Private pointer manipulations. Never throw away a `struct cl_heap_string *'!
inline cl_string::operator cl_heap_string* () const
{
cl_heap_string* hpointer = (cl_heap_string*)pointer;
cl_inc_refcount(*this);
return hpointer;
}
inline cl_string::cl_string ()
{
extern cl_string cl_null_string;
pointer = (cl_heap_string*) cl_null_string;
}
CL_REQUIRE(cl_st_null)
// Hash code.
extern unsigned long hashcode (const cl_string& str);
// Output.
extern void fprint (cl_ostream stream, const cl_string& str);
CL_DEFINE_PRINT_OPERATOR(cl_string)
// Input.
#ifdef CL_IO_IOSTREAM
// Reads a line. Up to delim. The delimiter character is not placed in the
// resulting string. The delimiter character is kept in the input stream.
// If EOF is encountered, the stream's eofbit is set.
extern cl_string cl_fget (cl_istream stream, char delim = '\n');
// Reads a line. Up to delim. The delimiter character is not placed in the
// resulting string. The delimiter character is extracted from the input stream.
// If EOF is encountered, the stream's eofbit is set.
extern cl_string cl_fgetline (cl_istream stream, char delim = '\n');
// Like above, but only up to n-1 characters. If n-1 characters were read
// before the delimiter character was seen, the stream's failbit is set.
extern cl_string cl_fget (cl_istream stream, int n, char delim = '\n');
extern cl_string cl_fgetline (cl_istream stream, int n, char delim = '\n');
// Skips whitespace and then reads a non-whitespace string.
// If stream.width() is greater than 0, at most stream.width()-1 non-whitespace
// characters are read. When done, stream.width(0) is called.
// If EOF is encountered, the stream's eofbit is set.
extern cl_istream operator>> (cl_istream stream, cl_string& str);
#endif
// Debugging support.
#ifdef CL_DEBUG
extern int cl_string_debug_module;
static void* cl_string_debug_dummy[] = { &cl_string_debug_dummy,
&cl_string_debug_module
};
#endif
#endif /* _CL_STRING_H */
|