presage  0.9
presage.cpp
Go to the documentation of this file.
1 
2 /******************************************************
3  * Presage, an extensible predictive text entry system
4  * ---------------------------------------------------
5  *
6  * Copyright (C) 2008 Matteo Vescovi <matteo.vescovi@yahoo.co.uk>
7 
8  This program is free software; you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation; either version 2 of the License, or
11  (at your option) any later version.
12 
13  This program is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License along
19  with this program; if not, write to the Free Software Foundation, Inc.,
20  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21  *
22  **********(*)*/
23 
24 
25 #include "presage.h"
26 
27 #include "core/profileManager.h"
28 #include "core/predictorRegistry.h"
30 #include "core/selector.h"
32 
34  throw (PresageException)
35 {
36  profileManager = new ProfileManager();
37  configuration = profileManager->get_configuration();
38  predictorRegistry = new PredictorRegistry(configuration);
39  contextTracker = new ContextTracker(configuration, predictorRegistry, callback);
40  predictorActivator = new PredictorActivator(configuration, predictorRegistry, contextTracker);
41  selector = new Selector(configuration, contextTracker);
42 }
43 
44 Presage::Presage (PresageCallback* callback, const std::string config_filename)
45  throw (PresageException)
46 {
47  profileManager = new ProfileManager(config_filename);
48  configuration = profileManager->get_configuration();
49  predictorRegistry = new PredictorRegistry(configuration);
50  contextTracker = new ContextTracker(configuration, predictorRegistry, callback);
51  predictorActivator = new PredictorActivator(configuration, predictorRegistry, contextTracker);
52  selector = new Selector(configuration, contextTracker);
53 }
54 
56 {
57  delete selector;
58  delete predictorActivator;
59  delete contextTracker;
60  delete predictorRegistry;
61  delete profileManager;
62 }
63 
64 std::vector<std::string> Presage::predict ()
65  throw (PresageException)
66 {
67  std::vector<std::string> result;
68 
69  unsigned int multiplier = 1;
70  Prediction prediction = predictorActivator->predict(multiplier++, 0);
71  result = selector->select(prediction);
72 
73  Prediction previous_prediction = prediction;
74  while ((result.size() < (selector->get_suggestions()))
75  && (prediction = predictorActivator->predict(multiplier++, 0)).size() > previous_prediction.size()) {
76  // while the number of predicted tokens is lower than desired,
77  // search harder (i.e. higher multiplier) for a prediction of
78  // sufficient size (i.e. that satisfies selector), as long as
79  // the result of current prediction is greater than the
80  // previous prediction (i.e. we are finding new tokens).
81  result = selector->select(prediction);
82  previous_prediction = prediction;
83  }
84 
86 
87  return result;
88 }
89 
90 std::multimap<double, std::string> Presage::predict (std::vector<std::string> filter)
91  throw (PresageException)
92 {
93  std::multimap<double, std::string> result;
94 
95  std::vector<std::string> selection;
96  const char** internal_filter = 0;
97  if(filter.size()>0)
98  {
99  // convert filter to internal representation - currently a null
100  // terminated const char**
101  internal_filter = new const char*[filter.size() + 1];
102  for (std::vector<std::string>::size_type i = 0; i < filter.size(); i++) {
103  internal_filter[i] = filter[i].c_str();
104  }
105  internal_filter[filter.size()] = 0;
106  }
107 
108  unsigned int multiplier = 1;
109  Prediction prediction = predictorActivator->predict(multiplier++, internal_filter);
110  selection = selector->select(prediction);
111 
112  Prediction previous_prediction = prediction;
113  while ((selection.size() < (selector->get_suggestions()))
114  && (prediction = predictorActivator->predict(multiplier++, internal_filter)).size() > previous_prediction.size()) {
115  // while the number of predicted tokens is lower than desired,
116  // search harder (i.e. higher multiplier) for a prediction of
117  // sufficient size (i.e. that satisfies selector), as long as
118  // the selection of current prediction is greater than the
119  // previous prediction (i.e. we are finding new tokens).
120  selection = selector->select(prediction);
121  previous_prediction = prediction;
122  }
123 
124  delete[] internal_filter;
125 
126  for (std::vector<std::string>::const_iterator it = selection.begin();
127  it != selection.end();
128  it++) {
129  std::pair<const double, std::string> p(prediction.getSuggestion(*it).getProbability(),
130  (*it));
131  result.insert(p);
132  }
133 
134  contextTracker->update();
135 
136  return result;
137 }
138 
140  throw (PresageException)
141 {
142  return const_cast<PresageCallback*>(contextTracker->callback(callback));
143 }
144 
145 std::string Presage::completion (const std::string str)
146  throw (PresageException)
147 {
148  // There are two types of completions: normal and erasing.
149  // normal_completion = prefix + remainder
150  // erasing_completion = eraser + prefix + remainder
151  //
152  // or, given that token = prefix + remainder
153  // normal_completion = token
154  // erasing_completion = eraser + token
155  //
156  // where eraser = ^H+ (one or more backspace characters)
157  //
158  // offset to first non ^H character in completion (^H are inserted
159  // by abbreviation expansion predictor to erase abbreviation from
160  // stream)
161  //
162  std::string result;
163 
164  std::string::size_type offset = str.find_first_not_of('\b');
165  if (offset == 0) {
166  // normal completion,
167  // ensure that current prefix is a substring of completion
168  // token and set result
169  //
170  if (contextTracker->isCompletionValid(str)) {
171  std::string prefix = contextTracker->getPrefix();
172  result = str.substr(prefix.size());
173  } else {
174  std::string message = "[Presage] Error: token '";
175  message += str;
176  message += "' does not match prefix: ";
177  message += contextTracker->getPrefix();
179  }
180  } else {
181  // erasing completion,
182  // pass it to tracker in its entirety
183  //
184  result = str;
185  }
186 
187  // if (append_trailing_space_is_on()) // TODO: make this configurable
188  result += ' ';
189 
190  return result;
191 }
192 
193 std::string Presage::context () const
194  throw (PresageException)
195 {
196  return contextTracker->getPastStream();
197 }
198 
200  throw (PresageException)
201 {
202  return contextTracker->contextChange();
203 }
204 
205 std::string Presage::prefix () const
206  throw (PresageException)
207 {
208  return contextTracker->getPrefix();
209 }
210 
211 std::string Presage::config (const std::string variable) const
212  throw (PresageException)
213 {
214  return configuration->find (variable)->get_value ();
215 }
216 
217 void Presage::config (const std::string variable, const std::string value) const
218  throw (PresageException)
219 {
220  configuration->find (variable)->set_value (value);
221 }
222 
223 void Presage::save_config () const
224  throw (PresageException)
225 {
227 }
228 
229 
230 
231 struct _presage {
234 };
235 
237 {
238 public:
240  void* past_arg,
242  void* future_arg)
243  : m_get_past_stream_cb (past),
244  m_get_past_stream_cb_arg (past_arg),
245  m_get_future_stream_cb (future),
246  m_get_future_stream_cb_arg (future_arg)
247  { }
248 
249  virtual ~CPresageCallback() { }
250 
251  std::string get_past_stream() const {
253  }
254 
255  std::string get_future_stream() const {
257  }
258 
259 private:
264 };
265 
266 #define presage_exception_handler(CODE) \
267  try \
268  { \
269  CODE; \
270  } \
271  catch (PresageException& ex) \
272  { \
273  return ex.code (); \
274  } \
275  return PRESAGE_OK;
276 
277 #define presage_exception_handler_with_result(CODE) \
278  try \
279  { \
280  CODE; \
281  } \
282  catch (PresageException& ex) \
283  { \
284  (*result) = 0; \
285  return ex.code (); \
286  } \
287  return PRESAGE_OK;
288 
289 static char* alloc_c_str (const std::string& str)
290 {
291  char* result_c_str = (char*) malloc (str.size() + 1);
292  if (result_c_str)
293  strcpy (result_c_str, str.c_str());
294  return result_c_str;
295 }
296 
298  void* past_stream_cb_arg,
299  _presage_callback_get_future_stream future_stream_cb,
300  void* future_stream_cb_arg,
301  presage_t* result)
302 {
304  (
305  (*result) = (presage_t) malloc (sizeof (_presage));
306  if (*result != NULL)
307  {
308  (*result)->presage_callback_object = new CPresageCallback (past_stream_cb,
309  past_stream_cb_arg,
310  future_stream_cb,
311  future_stream_cb_arg);
312  (*result)->presage_object = new Presage ((*result)->presage_callback_object);
313  }
314 
315  );
316 }
317 
319  void* past_stream_cb_arg,
320  _presage_callback_get_future_stream future_stream_cb,
321  void* future_stream_cb_arg,
322  const char* config,
323  presage_t* result)
324 {
326  (
327  (*result) = (presage_t) malloc (sizeof (_presage));
328  if (*result != NULL)
329  {
330 
331  (*result)->presage_callback_object = new CPresageCallback (past_stream_cb,
332  past_stream_cb_arg,
333  future_stream_cb,
334  future_stream_cb_arg);
335  (*result)->presage_object = new Presage ((*result)->presage_callback_object, config);
336  }
337  );
338 }
339 
341 {
342  if (prsg)
343  {
344  delete prsg->presage_object;
345  delete prsg->presage_callback_object;
346 
347  free (prsg);
348  }
349 }
350 
351 void presage_free_string (char* str)
352 {
353  free (str);
354 }
355 
356 void presage_free_string_array (char** strs)
357 {
358  if (strs) {
359  for (size_t t = 0; strs[t] != 0; t++) {
360  free (strs[t]);
361  }
362  free (strs);
363  }
364 }
365 
367 {
369  (
370  std::vector<std::string> prediction = prsg->presage_object->predict();
371 
372  size_t prediction_c_str_size = prediction.size() + 1;
373  char** prediction_c_str = (char**) malloc (prediction_c_str_size * sizeof(char*));
374  if (prediction_c_str != NULL)
375  {
376  memset (prediction_c_str, 0, prediction_c_str_size * sizeof(char*));
377 
378  size_t i = 0;
379  while (i < prediction_c_str_size - 1) {
380  prediction_c_str[i] = (char*) malloc (prediction[i].size() + 1);
381  if (prediction_c_str[i] != NULL)
382  strcpy (prediction_c_str[i], prediction[i].c_str());
383  i++;
384  }
385  prediction_c_str[i] = 0;
386  }
387 
388  *result = prediction_c_str;
389  );
390 }
391 
392 presage_error_code_t presage_completion (presage_t prsg, const char* token, char** result)
393 {
395  (
396  *result = alloc_c_str (prsg->presage_object->completion (token));
397  );
398 }
399 
401 {
403  (
404  *result = alloc_c_str (prsg->presage_object->context ());
405  );
406 }
407 
409 {
411  (
412  *result = prsg->presage_object->context_change ();
413  );
414 }
415 
417 {
419  (
420  *result = alloc_c_str (prsg->presage_object->prefix ());
421  );
422 }
423 
424 presage_error_code_t presage_config (presage_t prsg, const char* variable, char** result)
425 {
427  (
428  *result = alloc_c_str (prsg->presage_object->config (variable));
429  );
430 }
431 
432 presage_error_code_t presage_config_set (presage_t prsg, const char* variable, const char* value)
433 {
435  (
436  prsg->presage_object->config (variable, value)
437  );
438 }
439 
441 {
443  (
444  prsg->presage_object->save_config ()
445  );
446 }
PredictorRegistry * predictorRegistry
Definition: presage.h:234
Prediction predict(unsigned int multiplier, const char **filter)
presage_error_code_t
Selector * selector
Definition: presage.h:237
void presage_free(presage_t prsg)
Definition: presage.cpp:340
presage_error_code_t presage_save_config(presage_t prsg)
Definition: presage.cpp:440
presage_error_code_t presage_prefix(presage_t prsg, char **result)
Definition: presage.cpp:416
presage_error_code_t presage_predict(presage_t prsg, char ***result)
Definition: presage.cpp:366
std::vector< std::string > predict()
Obtain a prediction.
Definition: presage.cpp:64
bool context_change() const
Returns true if a context change occured.
Definition: presage.cpp:199
PresageCallback * callback(PresageCallback *callback)
Callback getter/setter.
Definition: presage.cpp:139
void * m_get_future_stream_cb_arg
Definition: presage.cpp:263
presage_error_code_t presage_config(presage_t prsg, const char *variable, char **result)
Definition: presage.cpp:424
Presage(PresageCallback *callback)
Definition: presage.cpp:33
Presage * presage_object
Definition: presage.cpp:233
PresageCallback * presage_callback_object
Definition: presage.cpp:232
#define presage_exception_handler_with_result(CODE)
Definition: presage.cpp:277
void presage_free_string_array(char **strs)
Definition: presage.cpp:356
static char * alloc_c_str(const std::string &str)
Definition: presage.cpp:289
#define presage_exception_handler(CODE)
Definition: presage.cpp:266
Suggestion getSuggestion(int=0) const
Definition: prediction.cpp:73
presage_error_code_t presage_context(presage_t prsg, char **result)
Definition: presage.cpp:400
PredictorActivator * predictorActivator
Definition: presage.h:236
size_t size() const
Definition: prediction.cpp:68
presage_error_code_t presage_context_change(presage_t prsg, int *result)
Definition: presage.cpp:408
ContextTracker * contextTracker
Definition: presage.h:235
std::string config
Definition: presageDemo.cpp:70
std::string config(const std::string variable) const
Gets the value of specified configuration variable.
Definition: presage.cpp:211
presage_error_code_t presage_new_with_config(_presage_callback_get_past_stream past_stream_cb, void *past_stream_cb_arg, _presage_callback_get_future_stream future_stream_cb, void *future_stream_cb_arg, const char *config, presage_t *result)
Definition: presage.cpp:318
presage_error_code_t presage_config_set(presage_t prsg, const char *variable, const char *value)
Definition: presage.cpp:432
void * m_get_past_stream_cb_arg
Definition: presage.cpp:261
~Presage()
Definition: presage.cpp:55
std::string get_future_stream() const
Definition: presage.cpp:255
void save_config() const
Save current configuration to file.
Definition: presage.cpp:223
presage_error_code_t presage_new(_presage_callback_get_past_stream past_stream_cb, void *past_stream_cb_arg, _presage_callback_get_future_stream future_stream_cb, void *future_stream_cb_arg, presage_t *result)
Definition: presage.cpp:297
std::string prefix() const
Returns the current prefix.
Definition: presage.cpp:205
_presage_callback_get_past_stream m_get_past_stream_cb
Definition: presage.cpp:260
ProfileManager * profileManager
Definition: presage.h:232
const char *(* _presage_callback_get_future_stream)(void *)
Presage, the intelligent predictive text entry platform.
Definition: presage.h:107
CPresageCallback(_presage_callback_get_past_stream past, void *past_arg, _presage_callback_get_future_stream future, void *future_arg)
Definition: presage.cpp:239
std::string getPrefix() const
size_t get_suggestions() const
Definition: selector.cpp:246
std::string context() const
Returns the text entered so far.
Definition: presage.cpp:193
double getProbability() const
Definition: suggestion.cpp:69
void save_profile() const
std::vector< std::string > select(Prediction)
Definition: selector.cpp:55
presage_error_code_t presage_completion(presage_t prsg, const char *token, char **result)
Definition: presage.cpp:392
Tracks user interaction and context.
void presage_free_string(char *str)
Definition: presage.cpp:351
std::string get_past_stream() const
Definition: presage.cpp:251
const char *(* _presage_callback_get_past_stream)(void *)
_presage_callback_get_future_stream m_get_future_stream_cb
Definition: presage.cpp:262
std::string getPastStream() const
std::string completion(std::string str)
Request presage to return the completion string for the given predicted token.
Definition: presage.cpp:145
virtual ~CPresageCallback()
Definition: presage.cpp:249