00001 // idep_tokitr.c 00002 #include "idep_tokeniter.h" 00003 00004 #include <ctype.h> // isspace() 00005 #include <memory.h> // memcpy() 00006 #include <iostream> 00007 #include <cassert> 00008 00009 // -*-*-*- static functions -*-*-*- 00010 00011 enum { START_SIZE = 1, GROW_FACTOR = 2 }; 00012 00013 const char NEWLINE_CHAR = '\n'; 00014 const char NULL_CHAR = '\0'; 00015 00016 // -*-*-*- idep_TokenIter_i -*-*-*- 00017 00018 struct idep_TokenIter_i { 00019 std::istream& d_in; 00020 char *d_buf_p; 00021 int d_size; 00022 int d_length; 00023 int d_newlineFlag; 00024 00025 idep_TokenIter_i(std::istream& in); 00026 ~idep_TokenIter_i(); 00027 void grow(); 00028 void addChar(char ch); 00029 void advance(); 00030 }; 00031 00032 idep_TokenIter_i::idep_TokenIter_i(std::istream& in) 00033 : d_in(in) 00034 , d_buf_p(new char[START_SIZE]) 00035 , d_size(START_SIZE) 00036 , d_length(0) 00037 , d_newlineFlag(0) 00038 { 00039 assert(d_buf_p); 00040 } 00041 00042 idep_TokenIter_i::~idep_TokenIter_i() 00043 { 00044 delete d_buf_p; 00045 } 00046 00047 void idep_TokenIter_i::grow() 00048 { 00049 int newSize = d_size * GROW_FACTOR; 00050 char *tmp = d_buf_p; 00051 d_buf_p = new char[newSize]; 00052 assert(d_buf_p); 00053 memcpy(d_buf_p, tmp, d_size); 00054 d_size = newSize; 00055 delete [] tmp; 00056 } 00057 00058 void idep_TokenIter_i::addChar(char ch) 00059 { 00060 if (d_length >= d_size) { 00061 grow(); 00062 } 00063 assert(d_length < d_size); 00064 d_buf_p[d_length++] = ch; 00065 } 00066 00067 // -*-*-*- idep_TokenIter -*-*-*- 00068 00069 idep_TokenIter::idep_TokenIter(std::istream& in) 00070 : d_this(new idep_TokenIter_i(in)) 00071 { 00072 ++*this; // load first occurrence 00073 } 00074 00075 idep_TokenIter::~idep_TokenIter() 00076 { 00077 delete d_this; 00078 } 00079 00080 void idep_TokenIter::operator++() 00081 { 00082 assert(*this); 00083 00084 d_this->d_length = 0; 00085 00086 if (d_this->d_newlineFlag) { // left over newline 00087 d_this->d_newlineFlag = 0; 00088 d_this->addChar(NEWLINE_CHAR); 00089 } 00090 else { 00091 char c; 00092 while (d_this->d_in && !d_this->d_in.get(c).eof()) { 00093 if (d_this->d_length > 0) { // "word" in progress 00094 if (isspace(c)) { 00095 if (NEWLINE_CHAR == c) { 00096 d_this->d_newlineFlag = 1; // note newline for later 00097 } 00098 break; // end of "word" in any case 00099 } 00100 d_this->addChar(c); // start of "word" 00101 } 00102 else { // nothing found yet 00103 if (isspace(c)) { 00104 if (NEWLINE_CHAR == c) { 00105 d_this->addChar(NEWLINE_CHAR); 00106 break; // found a newline 00107 } 00108 continue; // found an ordinary space 00109 } 00110 d_this->addChar(c); // add character to "word" 00111 } 00112 } 00113 } 00114 00115 if (d_this->d_length > 0) { 00116 d_this->addChar(NULL_CHAR); // always append a null char 00117 } 00118 else { 00119 d_this->d_length = -1; // or make iterator invalid 00120 } 00121 } 00122 00123 00124 idep_TokenIter::operator const void *() const 00125 { 00126 return d_this->d_length >= 0 ? this : 0; 00127 } 00128 00129 const char *idep_TokenIter::operator()() const 00130 { 00131 return d_this->d_buf_p; 00132 } 00133 00134
1.3.9.1