libcsdbg  1.28
C++ exception (and generic) stack trace debug library
dictionary.cpp
Go to the documentation of this file.
1 #include "../include/dictionary.hpp"
2 #include "../include/util.hpp"
3 
10 namespace csdbg {
11 
24 dictionary::dictionary(const i8 *nm, const i8 *path, bool mode)
25 try:
26 chain<string>(),
27 m_name(NULL),
28 m_mode(mode)
29 {
30  if ( unlikely(nm == NULL) )
31  throw exception("invalid argument: nm (=%p)", nm);
32 
33  if ( likely(path != NULL) )
34  load_file(path);
35 
36  m_name = new i8[strlen(nm) + 1];
37  strcpy(m_name, nm);
38 }
39 
40 catch (...) {
41  clear();
42 }
43 
44 
53 try:
54 chain<string>(src),
55 m_name(NULL),
56 m_mode(src.m_mode)
57 {
58  m_name = new i8[strlen(src.m_name) + 1];
59  strcpy(m_name, src.m_name);
60 }
61 
62 catch (...) {
63  clear();
64  m_name = NULL;
65 }
66 
67 
72 {
73  delete[] m_name;
74  m_name = NULL;
75 }
76 
77 
86 {
87  return new dictionary(*this);
88 }
89 
90 
96 inline const i8* dictionary::name() const
97 {
98  return m_name;
99 }
100 
101 
107 inline bool dictionary::mode() const
108 {
109  return m_mode;
110 }
111 
112 
124 {
125  if ( unlikely(nm == NULL) )
126  throw exception("invalid argument: nm (=%p)", nm);
127 
128  u32 len = strlen(nm);
129  if (len > strlen(m_name)) {
130  delete[] m_name;
131  m_name = NULL;
132  m_name = new i8[len + 1];
133  }
134 
135  strcpy(m_name, nm);
136  return *this;
137 }
138 
139 
148 {
149  m_mode = mode;
150  return *this;
151 }
152 
153 
164 {
165  if ( unlikely(this == &rval) )
166  return *this;
167 
168  /* Copy words */
170  m_mode = rval.m_mode;
171  return set_name(rval.m_name);
172 }
173 
174 
194 {
195  __D_ASSERT(path != NULL);
196  if ( unlikely(path == NULL) )
197  return *this;
198 
199  /* Stat the dictionary file path and make some preliminary checks */
200  fileinfo_t inf;
201  i32 retval = stat(path, &inf);
202  if ( unlikely(errno == ENOENT) )
203  throw exception("file '%s' does not exist", path);
204 
205  else if ( unlikely(retval < 0) )
206  throw exception(
207  "failed to stat path '%s' (errno %d - %s)",
208  path,
209  errno,
210  strerror(errno)
211  );
212 
213  else if ( unlikely(!util::is_regular(inf)) )
214  throw exception("'%s' is not a regular file", path);
215 
216  else if ( unlikely(!util::is_readable(inf)) )
217  throw exception("file '%s' is not readable", path);
218 
219  i32 sz = inf.st_size;
220  if ( unlikely(sz == 0) ) {
221  util::dbg_warn("dictionary file '%s' is empty", path);
222  return *this;
223  }
224 
225  /* Open the file */
226  i32 fd;
227  do {
228  fd = open(path, O_RDONLY);
229  }
230  while ( unlikely(fd < 0 && errno == EINTR) );
231 
232  if ( unlikely(fd < 0) )
233  throw exception(
234  "failed to open file '%s' (errno %d - %s)",
235  path,
236  errno,
237  strerror(errno)
238  );
239 
240  /* Memory map the file */
241  void *mmap_base = mmap(NULL, sz, PROT_READ, MAP_SHARED, fd, 0);
242  if ( unlikely(mmap_base == MAP_FAILED) ) {
243  close(fd);
244  throw exception(
245  "failed to memory map file '%s' (errno %d - %s)",
246  path,
247  errno,
248  strerror(errno)
249  );
250  }
251 
252  string *word = NULL;
253  i32 cnt = 0;
254 
255  /* If an exception occurs, unmap/close the file, clean up and rethrow it */
256  try {
257  i32 bytes = sz;
258  i8 *offset, *cur;
259  offset = cur = static_cast<i8*> (mmap_base);
260 
261  /* Load the dictionary words */
262  while ( likely(bytes-- > 0) )
263  if ( unlikely(*cur == '\n') ) {
264  if ( likely(cur != offset) ) {
265  word = new string("%.*s", cur - offset, offset);
266  word->trim();
267 
268  if ( unlikely(word->length() == 0) )
269  delete word;
270 
271  else {
272  cnt++;
273  add(word);
274  }
275 
276  word = NULL;
277  }
278 
279  offset = ++cur;
280  }
281  else
282  ++cur;
283  }
284 
285  catch (...) {
286  delete word;
287  munmap(mmap_base, sz);
288  close(fd);
289  throw;
290  }
291 
292  munmap(mmap_base, sz);
293  close(fd);
294 
295 #if CSDBG_DBG_LEVEL & CSDBG_DBGL_INFO
296  if ( likely(cnt > 0) )
298  "file '%s' (%d word%s) loaded on dictionary %s",
299  path,
300  cnt,
301  (cnt != 1) ? "s" : "",
302  m_name
303  );
304 
305  else
306  util::dbg_info("dictionary file '%s' is empty", path);
307 #endif
308 
309  return *this;
310 }
311 
312 
324 const string* dictionary::lookup(const string &exp, bool icase) const
325 {
326  for (u32 i = 0; likely(i < m_size); i++) {
327  string *word = at(i);
328  if ( likely(!m_mode) ) {
329  if ( unlikely(exp.cmp(*word, icase) == 0) )
330  return word;
331  }
332 
333  else if ( unlikely(exp.match(*word, icase)) )
334  return word;
335  }
336 
337  return NULL;
338 }
339 
340 }
341 
virtual dictionary * clone() const
Object virtual copy constructor.
Definition: dictionary.cpp:85
virtual string & trim(i32=0)
Remove leading and/or trailing whitespace characters.
Definition: string.cpp:529
dictionary(const i8 *, const i8 *=NULL, bool=false)
Object constructor.
Definition: dictionary.cpp:24
virtual string * at(u32) const
u32 m_size
Node count.
Definition: chain.hpp:43
Lightweight, templated, doubly-linked list (using XOR linking)
Definition: chain.hpp:33
bool m_mode
Lookup mode.
Definition: dictionary.hpp:40
A named collection of words (for syntax highlighters)
Definition: dictionary.hpp:32
virtual bool mode() const
Get the lookup mode.
Definition: dictionary.cpp:107
char i8
8-bit signed integer
Definition: config.hpp:72
struct stat fileinfo_t
File metadata.
Definition: config.hpp:112
#define likely(expr)
Offer a hint (positive) to the pipeline branch predictor.
Definition: config.hpp:344
static void dbg_warn(const i8 *,...)
Print a warning debug message on the standard error stream.
Definition: util.cpp:703
i8 * m_name
Dictionary name.
Definition: dictionary.hpp:38
virtual const i8 * name() const
Get the dictionary name.
Definition: dictionary.cpp:96
static bool is_readable(const fileinfo_t &)
Check if the process has read access to a file.
Definition: util.cpp:445
virtual i32 cmp(const string &, bool=false) const
Compare to another string.
Definition: string.cpp:470
virtual ~dictionary()
Object destructor.
Definition: dictionary.cpp:71
virtual dictionary & set_name(const i8 *)
Set the name.
Definition: dictionary.cpp:123
virtual dictionary & operator=(const dictionary &)
Assignment operator.
Definition: dictionary.cpp:163
virtual chain & add(string *)
virtual dictionary & load_file(const i8 *)
Load words from a dictionary file.
Definition: dictionary.cpp:193
Lightweight string buffer class (for ISO-8859-1 text)
Definition: string.hpp:36
virtual bool match(const string &, bool=false) const
Match against a POSIX extended regular expression.
Definition: string.cpp:490
unsigned int u32
32-bit unsigned integer
Definition: config.hpp:102
virtual chain & operator=(const chain &)
Assignment operator.
Definition: chain.hpp:296
int i32
32-bit signed integer
Definition: config.hpp:82
static bool is_regular(const fileinfo_t &)
Check if a file is a regular one.
Definition: util.cpp:419
virtual u32 length() const
Get the character count.
Definition: string.cpp:222
This class is a throwable with a textual description of an error.
Definition: exception.hpp:26
#define unlikely(expr)
Offer a hint (negative) to the pipeline branch predictor.
Definition: config.hpp:349
static void dbg_info(const i8 *,...)
Print an informational debug message on the standard error stream.
Definition: util.cpp:680
virtual dictionary & set_mode(bool)
Set the lookup mode.
Definition: dictionary.cpp:147
virtual const string * lookup(const string &, bool=false) const
Dictionary lookup.
Definition: dictionary.cpp:324
#define __D_ASSERT(x)
Assertion macro.
Definition: config.hpp:268