Back

1     //------------------------------------------------------------------------------
2     // Module WordList.cpp                                                        //
3     //                                                                            //
4     //    Simple class which encapsulates a (keyword-)word list                   //
5     //                                                                            //
6     //    Copyright (c) 2000-2004 by Lars Haendel                                 //
7     //    Home: http://www.newty.de                                               //
8     //                                                                            //
9     //    This program is free software and can be used under the terms of the    //
10    //    GNU licence. See header-file for further information and disclaimer.    //
11    //                                                                            //
12    //------------------------------------------------------------------------------
13
14
15    #include <stdlib>          //  due to: bsearch() etc.
16    #include <limits>          //          INT_MAX
17    #include <iomanip>         //          setw()
18
19    #include "WordList.h"
20    #include "ErrText.h"       //          TErrText
21    #include "FileUtil.h"      //          SearchKey() ...
22    #include "NameUtil.h"      //          filename utilities
23
24
25    #define RIGHT_MARGIN 16000 // note: feature deactivated
26
27    //-------------------------------------------------------------------------------------
28    // case sensitive comparision function for qsort()
29    int CmpFunc1(const void* _a, const void* _b)
30    {
31       // explicit typecast
32       const char** a = (const char**) _a;
33       const char** b = (const char**) _b;
34
35       // compare case sensitive
36       return strcmp(*a, *b);
37    }
38
39    //-------------------------------------------------------------------------------------
40    // not case sensitive comparision function for qsort()
41    int CmpFunc2(const void* _a, const void* _b)
42    {
43       // explicit typecast
44       const char** a = (const char**) _a;
45       const char** b = (const char**) _b;
46
47       // compare ignoring case
48       return strcmpi(*a, *b);
49    }
50
51
52
53    //----------------------------------------------------------------------------------------------------------------------
54    // constructor
55    TWordList::TWordList()
56    {
57       words = NULL;  // ini
58       _n = 0;
59       randomize();
60    }
61
62
63    //----------------------------------------------------------------------------------------------------------------------
64    // destructor
65    TWordList::~TWordList()
66    {
67       Release();
68    }
69
70
71    //----------------------------------------------------------------------------------------------------------------------
72    // release memory
73    void TWordList::Release()
74    {
75       // release word list memory
76       for(int i=0;i<_n;i++)
77          delete[] words[i];
78       delete[] words;
79
80       words = NULL;     // ini
81       _n = 0;
82    }
83
84
85    //----------------------------------------------------------------------------------------------------------------------
86    // load words from file
87    void TWordList::Load(ifstream& file, const char*const& szKey, const bool& f_CaseSensitive)
88    {
89       Release();                          // release memory
90       if(f_CaseSensitive)                 // initialize pointer to comparison function
91          CmpFunc = &CmpFunc1;                // case sensitive
92       else
93          CmpFunc = &CmpFunc2;                // not case sensitive
94
95
96       streampos curpos = file.tellg();    // store actual stream position
97       try
98       {
99          //----------------------------------------------------------------------------------------------------------------
100         // position to value of key 'szKey'
101         try
102         {
103            SearchKey(file, szKey, INT_MAX, '[');        // search key, but only within current section
104         }
105         catch(int errNo) { throw 0; }
106
107         if(file.get()!='=')                             // if next character is not '=' -> return
108            throw 0;
109
110         if(skipws(file)!=0)                             // remove whitespaces
111            throw ValueMissing;
112
113         if(file.get()!='"')                             // if next character is not '"' -> throw exception
114            throw 1;
115
116
117         //----------------------------------------------------------------------------------------------------------------
118         // determine number of keywords
119         streampos begin = file.tellg();                    // store actual stream position
120
121         // count number of (white-)space seperated strings
122         char c, szTmp[MAX_WORD_LEN];
123         int line, __n = 0;
124         do
125         {
126            c = ReadString(file, szTmp, MAX_WORD_LEN, '"'); // read string, additional delimiter is '"'
127            line = skipws(file);                            // remove all whitespaces
128            __n++;                                          // increment string counter if string is not empty
129         } while(c!='"' && file.peek() !='"' && line<2);    // repeat as long as delimiter was not '"' and there was at most one line feed
130
131         if(szTmp[0]=='\0')                                 // decrement string counter by one if string is empty
132            __n--;                                          // Note: may happen if whitespaces are before terminating quote
133         file.seekg(begin);                                 // restore stream position
134
135
136         //----------------------------------------------------------------------------------------------------------------
137         // allocate memory
138         _n = __n;
139         words = new char*[_n];
140         for(int i=0;i<_n;i++)
141            words[i] = new char[MAX_WORD_LEN];
142
143
144
145         //----------------------------------------------------------------------------------------------------------------
146         // read all (white-)space seperated strings and sort them
147         for(int i=0;i<_n;i++)
148         {
149            ReadString(file, words[i], MAX_WORD_LEN, '"');  // read string, additional delimiter is '"'
150            skipws(file);                                   // remove all whitespaces
151         }
152         char s=file.get();
153         if(s!='"')                                // remove and check the delimiter, must be '"'
154            throw 2;
155
156
157         // sort the keywords in alphabetical order
158         qsort((void*) words, _n, sizeof(char*), CmpFunc);
159
160      }
161      catch(int errNo)
162      {
163         Release();                                         // release memory again
164
165         if(errNo>0)
166         {
167            // compose error text
168            char szText[STS];
169
170            switch(errNo)
171            {
172               case 1  : sprintf(szText, "reading key '%s': Value of key must be enclosed within quotes", GetLastKey()); break;
173               case 2  : sprintf(szText, "reading key '%s': Value of key must be enclosed within quotes", GetLastKey()); break;
174               default : sprintf(szText, "reading key '%s': %s", GetLastKey(), GetLastError(errNo));
175            }
176
177            file.seekg(curpos);                                // restore stream position
178            throw TErrText(szText);                            // propagate exception
179         }
180      }
181
182      file.seekg(curpos);                                   // restore stream position
183   }
184
185
186   //----------------------------------------------------------------------------------------------------------------------
187   // returns true, if <szWord> is in word list
188   bool TWordList::IsInList(const char*const& szWord) const
189   {
190      if(bsearch((const void*) &szWord, (const void*) words, _n, sizeof(char*), CmpFunc))
191         return true;
192
193      return false;     // no match found: return false
194   }
195
196
197   //----------------------------------------------------------------------------------------------------------------------
198   // save words to file
199   void TWordList::Save(ofstream& file, const char*const& szKey, const int& width) const
200   {
201      if(_n==0)                                       // return if word list is empty
202         return;
203
204      file << setw(width) << szKey << " = \"";        // write key
205
206      // write all keywords to file
207      int nChars = 0;
208      for(int i=0;i<_n;i++)
209      {
210         nChars += SizeOfString(words[i]);            // sum up number of characters written in current line so far
211         if(nChars > RIGHT_MARGIN)                    // check right margin and start new line if necessary
212         {
213            nChars = 0;                               // reset
214            file << endl;                             // linefeed
215            file << setw(width) << " " << "    ";     // indent
216         }
217         file << words[i] << " ";
218      }
219      file << "\"" << endl;
220   }
221
222
223   //----------------------------------------------------------------------------------------------------------------------
224   // return random word from list or NULL if list is empty
225   const char* TWordList::GetRandom() const
226   {
227      if(_n>0)
228         return words[random(_n)];
229      else
230         return NULL;
231   }

Top