src/plugins/xdxf/src/engine_xdxf.c

Go to the documentation of this file.
00001 /******************************************************************************
00002 This file is part of mdictionary.
00003 
00004 mdictionary is free software; you can redistribute it and/or modify
00005 it under the terms of the GNU General Public License as published by
00006 the Free Software Foundation; either version 2 of the License, or
00007 (at your option) any later version.
00008 
00009 mdictionary is distributed in the hope that it will be useful, 
00010 but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00012 GNU General Public License for more details.
00013 
00014 You should have received a copy of the GNU General Public License 
00015 along with mdictionary; if not, write to the Free Software
00016 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
00017 
00018 Copyright 2006-2008 ComArch S.A.
00019 ******************************************************************************/
00027 #include <engine_xdxf.h>
00028 
00029 
00035 static gchar* word_translation_cache(XDXFData* data, gchar* word)
00036 {
00037         gnome_vfs_seek(data->cache, GNOME_VFS_SEEK_START, 0);
00038         gchar b[DICT_SEARCHING_WORD_TRAN_BUFF_SIZE + 1];
00039         GnomeVFSFileSize bytes_readed;
00040 
00041         guint word_length = strlen(word);
00042         guint record_length = 0;
00043         guint trans_offset = 0;
00044         guint already = 0;
00045         guint64 readed = 0;
00046         gchar* buffer = NULL;
00047         gchar* trans = NULL;
00048         guint file_size = get_file_size(data->cache);
00049         while(TRUE) {
00050                 gnome_vfs_read( data->cache,
00051                                 b,
00052                                 DICT_SEARCHING_WORD_TRAN_BUFF_SIZE,
00053                                 &bytes_readed );
00054                 guint max_length = (guint)get_max_length(b,bytes_readed);
00055                 readed += max_length;
00056                 buffer = b;
00057                 already = 0;
00058                 gchar* tmp = NULL;
00059                 while(already < max_length) {
00060                         memcpy(&record_length, buffer, sizeof(guint));
00061                         memcpy( &trans_offset,
00062                                 buffer+record_length-2*sizeof(guint),
00063                                 sizeof(guint) );
00064                         buffer[record_length-sizeof(guint)*2] = '\0';
00065                         tmp = g_utf8_casefold(buffer+sizeof(guint), -1);
00066                         if(((record_length - 3*sizeof(guint)) == word_length) &&
00067                            (g_utf8_collate(word,tmp) == 0) )
00068                         {
00069                                 FilePart translation = {0,0};
00070                                 translation.offset = trans_offset;
00071                                 memcpy( &(translation.length),
00072                                         buffer + record_length - sizeof(guint),
00073                                         sizeof(guint) );
00074                                 trans = read_file_part( &translation,
00075                                                         data->xdxf );
00076                                 g_free(tmp); tmp = NULL;
00077                                 break;
00078                         };
00079                         already += record_length;
00080                         buffer += record_length;
00081                         g_free(tmp); tmp = NULL;
00082                 };
00083 
00084                 if( ( bytes_readed < DICT_SEARCHING_WORD_TRAN_BUFF_SIZE ) ||
00085                     ( readed > (file_size - 3) ))
00086                 {
00087                         break;
00088                 };
00089 
00090                 gnome_vfs_seek(
00091                       data->cache,
00092                       GNOME_VFS_SEEK_CURRENT,
00093                      ((gint)max_length) -DICT_SEARCHING_WORD_TRAN_BUFF_SIZE );
00094         }
00095         return trans;
00096 }
00097 
00103 static gchar* word_translation_xdxf(XDXFData* data, gchar* word)
00104 {
00105         gchar* casefold_word = g_utf8_casefold(word, -1);
00106         guint word_length = strlen(casefold_word);
00107         gchar* trans = NULL;
00108         gnome_vfs_seek(data->xdxf, GNOME_VFS_SEEK_START, 0);
00109         GnomeVFSResult vfs_result;
00110         GnomeVFSFileSize bytes_readed = DICT_SEARCHING_WORD_TRAN_BUFF_SIZE;
00111         gchar buffer[DICT_SEARCHING_WORD_TRAN_BUFF_SIZE+1];
00112         guint64 file_size = get_file_size(data->xdxf);
00113 
00114 
00115         XML_Parser parser = XML_ParserCreate(NULL);
00116         if (!parser) {
00117                 g_warning("XDXF/%s->%s() Could not open initialize "
00118                           "XML parser.\n",
00119                           __FILE__,
00120                           __FUNCTION__ );
00121                 /* timer(TIMER_STOP,(gchar*)__FUNCTION__); */
00122                 return NULL;
00123         };
00124 
00125         gchar tmp[DICT_MAX_WORD_LENGTH];
00126         XDXFWordsTransData search_data = {
00127                                            tmp,
00128                                            casefold_word,
00129                                            word_length,
00130                                            0,
00131                                            NULL,
00132                                            FALSE,
00133                                            TRUE,
00134                                            0,
00135                                            &parser,
00136                                            FALSE,
00137                                            data->xdxf
00138                                          };
00139         XML_SetElementHandler( parser,
00140                                search_word_trans_start,
00141                                search_word_trans_end );
00142         XML_SetCharacterDataHandler(parser, search_word_trans_text);
00143         XML_SetUserData(parser, &search_data);
00144 
00145         gdouble last_prog = 0.0;
00146         while(TRUE) {
00147                 vfs_result = gnome_vfs_read( data->xdxf,
00148                                              buffer,
00149                                              DICT_SEARCHING_WORD_TRAN_BUFF_SIZE,
00150                                              &bytes_readed );
00151                 XML_Parse( parser,
00152                            buffer,
00153                            bytes_readed,
00154                            bytes_readed < DICT_SEARCHING_WORD_TRAN_BUFF_SIZE );
00155 
00156                 last_prog = 0.0;
00157                 if(data->cb_progress_word_trans != NULL) {
00158                         GnomeVFSFileSize act_pos;
00159                         gnome_vfs_tell(data->xdxf, &act_pos);
00160                         gdouble progress =
00161                                    ((gdouble)act_pos)/((gdouble)file_size);
00162                         if((( (progress - last_prog)/
00163                                (data->cb_progress_word_trans_seed) ) > 1.0) ||
00164                             (progress >= 1.0))
00165                         {
00166                                 data->
00167                                 cb_progress_word_trans(progress,
00168                                            data->cb_progress_word_trans_data,
00169                                            ENGINE_NO_ERROR );
00170                                 last_prog = progress;
00171                         };
00172                 }
00173 
00174                 if(bytes_readed < DICT_SEARCHING_WORD_TRAN_BUFF_SIZE)
00175                 {
00176                         break;
00177                 };
00178                 if(search_data.cont == FALSE)
00179                 {
00180                         break;
00181                 };
00182         }
00183         XML_ParserFree(parser);
00184         trans = search_data.translation; 
00185         g_free(casefold_word); casefold_word = NULL;
00186         return trans;
00187 }
00188 
00190 void xdxf_engine_search_word_translation(Engine* engine,
00191                                          gchar* word,
00192                                          gpointer user_data)
00193 {
00194         g_debug( "XDXF/%s->%s() called.\n"
00195                  "-->PARAM:engine at adress=%p\n"
00196                  "-->PARAM:word=\'%s\'\n",
00197                  __FILE__,
00198                  __FUNCTION__,
00199                  engine,
00200                  word );
00201         g_assert(engine != NULL);
00202         g_assert(word != NULL);
00203 
00204         /* timer(TIMER_START, (gchar*)__FUNCTION__); */
00205         XDXFData* data = (XDXFData*)(engine->engine_data);
00206         /* if callback is not set, we do not have to search word */
00207         if(data->cb_search_word_trans == NULL) {
00208                 g_warning("XDXF/%s->%s() callback for Word Translation not set."
00209                           " Searching aborted.\n",
00210                           __FILE__,
00211                           __FUNCTION__ );
00212                 /* timer(TIMER_STOP,(gchar*)__FUNCTION__); */
00213                 /* do not call any callback, just exit */
00214                 return;
00215         };
00216 
00217 
00218         gchar* trans;
00219         gchar* casefold_word = g_utf8_casefold(word, -1);
00220         /* is dictionary optimized */
00221         if(data->cache != NULL) {
00222                 trans = word_translation_cache(data, casefold_word);
00223         }
00224         else
00225         {
00226                 trans = word_translation_xdxf(data, casefold_word);
00227         };
00228         g_free(casefold_word); casefold_word = NULL;
00229 
00230         g_debug("XDXF/%s->%s() found for word \'%s\' translation:\n\'%s\'\n",
00231                 __FILE__,
00232                 __FUNCTION__,
00233                 word,
00234                 trans
00235         );
00236         /*timer(TIMER_STOP,(gchar*)__FUNCTION__);
00237         timer(TIMER_START,"callback for returning word's translation START"); */
00238 
00239         /* calling callback for word translation */
00240         gpointer tmp = user_data;
00241         if (NULL == tmp)
00242         {
00243                 tmp = data->cb_search_word_trans_data;
00244         }
00245         
00246         data->cb_search_word_trans( trans,
00247                                     word,
00248                                     tmp,
00249                                     ENGINE_NO_ERROR );
00250         /*timer(TIMER_STOP,"callback for returning word's translation END"); */
00251 
00252         /* free memmory if needed */
00253         if (data->auto_free && (NULL != trans) )
00254         {
00255                 g_free(trans);
00256                 trans = NULL;
00257         }
00258         return;
00259 }
00260 
00262 gboolean xdxf_engine_remove_word(Engine* engine,
00263                              gchar*  word)
00264 {
00265         g_debug("%s -> %s()", __FILE__, __FUNCTION__);
00266         g_debug("Not implemented yet. And wont be.");
00267         return FALSE;
00268 }
00269 
00271 gboolean xdxf_engine_add_word(Engine* engine,
00272                          gchar*  word,
00273                          gchar*  translation) 
00274 {
00275         g_debug("%s -> %s()", __FILE__, __FUNCTION__);
00276         g_debug("Not implemented yet. And wont be.");
00277         return FALSE;
00278 }
00279 
00280 static void search_word_trans_start(void *data,
00281                                     const char *el,
00282                                     const char **attr )
00283 {
00284         XDXFWordsTransData* loc_data = (XDXFWordsTransData*)data;
00285         if( (NULL != loc_data->translation) || !(loc_data->cont) )
00286         {
00287                 return;
00288         };
00289 
00290         if( ('k' == el[0]) && ('\0' == el[1]) )
00291         {
00292                 /* beggining of article key */
00293                 loc_data->one_word = 1;
00294                 loc_data->last_word_length = 0;
00295                 loc_data->last_word[0] = '\0';
00296         }
00297         else if( ('a' == el[0]) && ('r' == el[1]) && ('\0' == el[2]) )
00298         {
00299                 /* begining of article */
00300                 loc_data->last_start =
00301                           XML_GetCurrentByteIndex(*(loc_data->parser));
00302         }
00303 }
00304 
00305 static void search_word_trans_end(void *data, const char *el)
00306 {
00307         XDXFWordsTransData* loc_data = (XDXFWordsTransData*)data;
00308         if( (NULL != loc_data->translation) || (FALSE == loc_data->cont) )
00309         {
00310                 return;
00311         };
00312 
00313         if( ('k' == el[0]) && ('\0' == el[1]) )
00314         {
00315                 /* end of article key */
00316                 loc_data->one_word = 0;
00317                 gchar* tmp = g_utf8_casefold(loc_data->last_word, -1);
00318                 gint com = g_utf8_collate(tmp, loc_data->word);
00319                 g_free(tmp); tmp = NULL;
00320                 if(com != 0)
00321                 {
00322                         /* loc_data->cont = FALSE; */
00323                         /* dictionaries are not alway properly sorted, so for
00324                         searching we should lookd in whole file! */
00325                         return;
00326                 }
00327                 else if( (loc_data->last_word_length == loc_data->word_len) &&
00328                          (0 == com) )
00329                 {
00330                         loc_data->found = TRUE;
00331                 };
00332 
00333                 /* "clearing" buffer for next word - article key */
00334                 loc_data->last_word_length = 0;
00335         }
00336         else if( (TRUE == loc_data->found) && (0 == g_utf8_collate(el,"ar")) )
00337         {
00338                 loc_data->found = FALSE;
00339                 loc_data->cont = FALSE;
00340                 gulong last_stop =
00341                          (gulong)XML_GetCurrentByteIndex(*(loc_data->parser));
00342                 last_stop += strlen("</ar>");
00343                 FilePart fp = { loc_data->last_start,
00344                                 (last_stop - (loc_data->last_start)) };
00345                 loc_data->translation = read_file_part(&fp, loc_data->xdxf);
00346         }
00347 }
00348 
00349 static void search_word_trans_text(void *data, const XML_Char *txt, int len)
00350 {
00351         XDXFWordsTransData* loc_data = (XDXFWordsTransData*)data;
00352         if( (NULL != loc_data->translation ) || (FALSE == loc_data->cont) )
00353         {
00354 
00355                 return;
00356         };
00357 
00358         if(1 == loc_data->one_word)
00359         {
00360                 memcpy( &(loc_data->last_word[loc_data->last_word_length]),
00361                         (gchar*)txt,
00362                         len );
00363                 loc_data->last_word_length += (guint)len;
00364                 loc_data->last_word[loc_data->last_word_length] = '\0';
00365         };
00366 }
00367 
00373 void xdxf_engine_set_progress_seed(Engine* engine, gchar* signal, gdouble seed)
00374 {
00375         g_debug("XDXF/%s->%s() called.\n",__FILE__,__FUNCTION__);
00376         XDXFData* data = (XDXFData*)(engine->engine_data);
00377         if(g_ascii_strcasecmp(signal,ENGINE_PROGRESS_OPTIMIZING_SIGNAL) == 0)
00378         {
00379                 data->cb_progress_caching_seed = seed;
00380                 g_debug( "XDXF/%s->%s() sets new seed=%0.2f for for signal "
00381                          "\"%s\".\n",
00382                          __FILE__,
00383                          __FUNCTION__,
00384                          seed,
00385                          signal );
00386         }
00387         else
00388         {
00389                 g_warning("XDXF/%s->%s() unsupported signal "
00390                           "for progress: %s.\n",
00391                           __FILE__,
00392                           __FUNCTION__,
00393                           signal );
00394         };
00395 }
00396 
00404 gpointer xdxf_engine_set_callbacks(Engine* engine,
00405                              gchar* signal,
00406                              gpointer c_handler,
00407                              gpointer user_data)
00408 {
00409         g_debug("XDXF/%s->%s() called.\n", __FILE__, __FUNCTION__);
00410         g_assert(engine != NULL);
00411         g_assert(signal != NULL);
00412         g_assert(c_handler != NULL);
00413         XDXFData* data = (XDXFData*)(engine->engine_data);
00414 
00415         if(g_ascii_strcasecmp(signal,ENGINE_PROGRESS_OPTIMIZING_SIGNAL) == 0)  {
00416                 gpointer result = data->cb_progress_caching;
00417                 data->cb_progress_caching = c_handler;
00418                 data->cb_progress_caching_data = user_data;
00419                 g_debug("XDXF/%s->%s() sets handler for signal \"%s\".\n",
00420                         __FILE__,
00421                         __FUNCTION__,
00422                         signal );
00423                 g_debug("XDXF/%s->%s() Function at adress =  %d.\n",
00424                         __FILE__,
00425                         __FUNCTION__,
00426                         (guint)c_handler );
00427                 g_debug("XDXF/%s->%s()     Data at adress =  %d.\n",
00428                         __FILE__,
00429                         __FUNCTION__,
00430                         (guint)user_data );
00431                 return result;
00432         }
00433         else if(g_ascii_strcasecmp(signal, ENGINE_WORD_LIST_SIGNAL) == 0)
00434         {
00435                 gpointer result = data->cb_search_word_list;
00436                 data->cb_search_word_list = c_handler;
00437                 data->cb_search_word_list_data = user_data;
00438                 g_debug("XDXF/%s->%s() sets handler for signal \"%s\".\n",
00439                         __FILE__,
00440                         __FUNCTION__,
00441                         signal );
00442                 g_debug("XDXF/%s->%s() Function at adress =  %d.\n",
00443                         __FILE__,
00444                         __FUNCTION__,
00445                         (guint)c_handler );
00446                 g_debug("XDXF/%s->%s()     Data at adress =  %d.\n",
00447                         __FILE__,
00448                         __FUNCTION__,
00449                         (guint)user_data );
00450                 return result;
00451         }
00452         else if(g_ascii_strcasecmp(signal, ENGINE_WORD_TRANSLATION_SIGNAL) == 0)
00453         {
00454                 gpointer result = data->cb_search_word_trans;
00455                 data->cb_search_word_trans = c_handler;
00456                 data->cb_search_word_trans_data = user_data;
00457                 g_debug("XDXF/%s->%s() sets handler for signal \"%s\".\n",
00458                         __FILE__,
00459                         __FUNCTION__,
00460                         signal );
00461                 g_debug("XDXF/%s->%s() Function at adress =  %d.\n",
00462                         __FILE__,
00463                         __FUNCTION__,
00464                         (guint)c_handler );
00465                 g_debug("XDXF/%s->%s()     Data at adress =  %d.\n",
00466                         __FILE__,
00467                         __FUNCTION__,
00468                         (guint)user_data );
00469                 return result;
00470         }
00471         else {
00472                 g_warning("XDXF/%s->%s() unsupported signal: %s.\n",
00473                         __FILE__,
00474                         __FUNCTION__,
00475                         signal );
00476                 return NULL;
00477         }
00478 }
00479 
00483 void xdxf_engine_close(Engine* engine)
00484 {
00485         g_debug("XDXF/%s->%s() called.\n-->PARAM: engine adress=%p\n",
00486                 __FILE__,
00487                 __FUNCTION__,
00488                 engine );
00489 
00490         if(engine == NULL)
00491         {
00492                 g_warning("XDXF/%s->%s() Trying delete not existed engine.\n",
00493                           __FILE__,
00494                           __FUNCTION__ );
00495                 return;
00496         }
00497 
00498         XDXFData* data = (XDXFData*)(engine->engine_data);
00499         if(data->cache != NULL)
00500         {
00501                 gnome_vfs_close(data->cache);
00502         };
00503         if(data->xdxf != NULL)
00504         {
00505                 gnome_vfs_close(data->xdxf);
00506         };
00507 
00508         g_free(data->dict_path);
00509         g_free(data);
00510         g_free(engine);
00511 
00512         g_debug("XDXF/%s->%s() engine at adress=%p is deleted.\n",
00513                  __FILE__,
00514                  __FUNCTION__,
00515                  engine );
00516 }
00517 
00521 gchar* xdxf_engine_error_message(EngineStatus error) 
00522 {
00523         g_debug("XDXF/%s->%s() called.\n",__FILE__,__FUNCTION__);
00524         return "Error - not yet implemented.";
00525 }
00526 
00534 Engine* xdxf_engine_create( gchar* location,
00535                             EngineOptimizationFlag auto_cache,
00536                             cb_progress progress_handler,
00537                             gpointer progress_data,
00538                             gdouble seed)
00539 {
00540         g_debug("XDXF/%s->%s() called.\n"
00541                 "-->PARAM:location=\'%s\'\n"
00542                 "-->PARAM:auto_cache=%d\n",
00543                 __FILE__,
00544                 __FUNCTION__,
00545                 location,
00546                 (guint)auto_cache );
00547 
00548         /* timer(TIMER_START,(gchar*)__FUNCTION__); */
00549         GnomeVFSResult open_result;
00550 
00551         if(!gnome_vfs_initialized ()) {
00552                 gnome_vfs_init ();
00553         };
00554 
00555         gchar* tmp = g_strdup(location);
00556         string_to_path(&tmp);
00557 
00558         Engine* result = (Engine*)g_try_malloc(sizeof(Engine));
00559         result->engine_location = xdxf_engine_location;
00560         result->engine_is_optimized = xdxf_engine_is_optimized;
00561         result->engine_optimize = xdxf_engine_optimize;
00562         result->engine_search_word_list = xdxf_engine_search_word_list;
00563         result->engine_search_word_translation = 
00564                         xdxf_engine_search_word_translation;
00565 
00566         result->engine_close = xdxf_engine_close;
00567         result->engine_status = xdxf_engine_error;
00568         result->engine_status_message = xdxf_engine_error_message;
00569         result->engine_set_callback = xdxf_engine_set_callbacks;
00570         result->engine_set_progress_seed = xdxf_engine_set_progress_seed;
00571         result->engine_set_auto_free = xdxf_engine_set_auto_free;
00572         /* API 0.2 functions: */
00573         result->engine_add_word = xdxf_engine_add_word;
00574         result->engine_remove_word = xdxf_engine_remove_word;
00575 
00576         XDXFData* data = (XDXFData*)g_try_malloc(sizeof(XDXFData));
00577         result->engine_data = (gpointer)data;
00578 
00579         g_debug("XDXF/%s->%s() opening file...\'%s\'.\n",
00580                 __FILE__,
00581                 __FUNCTION__,
00582                 location );
00583         gchar* tmp2 = g_strconcat(tmp,"/dict.xdxf",NULL);
00584         open_result =
00585                 gnome_vfs_open (&(data->xdxf), tmp2, GNOME_VFS_OPEN_READ);
00586         g_free(tmp2); tmp2 = NULL;
00587 
00588         if(open_result != GNOME_VFS_OK)
00589         {
00590                 g_warning("XDXF/%s->%s() opening dictionary file failed"
00591                           " due to reason: %s.\n",
00592                           __FILE__,
00593                           __FUNCTION__,
00594                           gnome_vfs_result_to_string(open_result) );
00595                 result->engine_data = NULL;
00596                 g_free(data);
00597                 g_free(result);
00598                 result = NULL;
00599         }
00600         else
00601         {
00602                 g_debug("XDXF/%s->%s() opening dictionary file successed.\n",
00603                         __FILE__,
00604                         __FUNCTION__ );
00605 
00606                 data->dict_path = g_strdup(tmp);
00607                 data->cache = NULL;
00608                 data->cb_progress_caching = progress_handler;
00609                 data->cb_progress_caching_data = progress_data;
00610                 data->cb_progress_caching_seed = seed;
00611                 data->cb_progress_word_list = NULL;
00612                 data->cb_progress_word_list_data = NULL;
00613                 data->cb_progress_word_list_seed = 0.01;
00614                 data->cb_progress_word_trans = NULL;
00615                 data->cb_progress_word_trans_data = NULL;
00616                 data->cb_progress_word_trans_seed = 0.01;
00617 
00618                 data->cb_search_word_list = NULL;
00619                 data->cb_search_word_list_data = NULL;
00620 
00621                 data->cb_search_word_trans = NULL;
00622                 data->cb_search_word_trans_data = NULL;
00623 
00624                 data->auto_free = FALSE;
00625                 if(auto_cache != ENGINE_NO)
00626                 {
00627                         if(auto_cache == ENGINE_REFRESH)
00628                         {
00629                                 xdxf_engine_optimize(result);
00630                         }
00631                         else if(auto_cache == ENGINE_CREATE)
00632                         {
00633                                 gchar* cache_path = g_strconcat(data->dict_path,
00634                                                                 "/dict.cache",
00635                                                                 NULL );
00636                                 open_result =
00637                                         gnome_vfs_open( &(data->cache),
00638                                                         cache_path,
00639                                                         GNOME_VFS_OPEN_READ );
00640                                 if(open_result != GNOME_VFS_OK) {
00641                                         xdxf_engine_optimize(result);
00642                                 };
00643                                 g_free(cache_path);
00644                                 cache_path = NULL;
00645                         }
00646                 };
00647         }
00648         g_free(tmp); tmp = NULL;
00649 
00650         /* timer(TIMER_STOP,(gchar*)__FUNCTION__); */
00651         g_debug("XDXF/%s->%s() returned Engine at adress=%p\n",
00652                 __FILE__,
00653                 __FUNCTION__,
00654                 result );
00655         return result;
00656 }
00657 
00661 EngineModule engine_global_functions()
00662 {
00663         g_debug("XDXF/%s->%s() called.\n",__FILE__,__FUNCTION__);
00664 
00665         EngineModule result;
00666         result.engine_check             = xdxf_engine_check;
00667         result.engine_description       = xdxf_engine_description;
00668         result.engine_format            = xdxf_engine_format;
00669         result.engine_version           = xdxf_engine_version;
00670         result.engine_create            = xdxf_engine_create;
00671 
00672         g_debug("XDXF/%s->%s() returned EngineModule at adress=%p.\n",
00673                 __FILE__,
00674                 __FUNCTION__,
00675                 &result );
00676         return result;
00677 }
00678 
00679 /* we remove for this moment timers capabilities - but it could be easily
00680    move back again in the future for time consuption measurement.
00681 static double timer(gboolean start, gchar* message)
00682 {
00683         static GArray* stack = NULL;
00684         static gboolean first_run = TRUE;
00685         static struct timeval actual_time;
00686         static struct timeval last_time;
00687         static struct timeval result;
00688         static double seconds = 0.0;
00689         if(first_run) {
00690                 first_run = FALSE;
00691                 stack = g_array_new(TRUE, TRUE, sizeof(struct timeval));
00692         };
00693 
00694         if (start) {
00695                 g_debug("XDXF->%s() start counting time for function '%s()'.\n",
00696                         __FUNCTION__,
00697                         message
00698                        );
00699                 g_array_prepend_val(stack, actual_time);
00700                 gettimeofday(&g_array_index(stack, struct timeval, 0),NULL);
00701                 return -1.0;
00702         }
00703         // we just want to end some timer - print some information about 
00704         // working time;
00705         else {
00706                 gettimeofday(&actual_time,NULL);
00707                 last_time = g_array_index(stack, struct timeval, 0);
00708                 g_array_remove_index(stack, 0);
00709 
00710                 if (actual_time.tv_usec < last_time.tv_usec) {
00711                         int nsec = (last_time.tv_usec - actual_time.tv_usec) / 
00712                                                                   (1000000 + 1);
00713                         last_time.tv_usec -= 1000000 * nsec;
00714                         last_time.tv_sec += nsec;
00715                 }
00716                 if (actual_time.tv_usec - last_time.tv_usec > 1000000) {
00717                         int nsec = (last_time.tv_usec - actual_time.tv_usec) / 
00718                                                                         1000000;
00719                         last_time.tv_usec += 1000000 * nsec;
00720                         last_time.tv_sec -= nsec;
00721                 }
00722                 result.tv_sec = actual_time.tv_sec - last_time.tv_sec;
00723                 result.tv_usec = actual_time.tv_usec - last_time.tv_usec;
00724                 seconds = (((double)(result.tv_usec)) / 1e6) +
00725                                                       ((double)(result.tv_sec));
00726 
00727                 g_debug("XDXF->%s() function \'%s()\' was working for: %g [s] "
00728                         "or %ld [us].\n",
00729                         __FUNCTION__,
00730                         message,
00731                         seconds,
00732                         ((long)(result.tv_sec*1e6)+(result.tv_usec))
00733                        );
00734                 // stack is empty so we delete everything
00735                 if(stack->len == 0)   
00736                 {
00737                         g_array_free(stack, TRUE);
00738                         first_run = TRUE;
00739                 }
00740         }
00741         return seconds;
00742 }
00743 */
00744 
00750 static gchar* read_file_part(FilePart* part, GnomeVFSHandle* file) 
00751 {
00752         g_debug("XDXF/%s->%s() called.\n",__FILE__,__FUNCTION__);
00753         /* timer(TIMER_START,(gchar*)__FUNCTION__); */
00754         gchar* result = NULL;
00755         GnomeVFSResult    f_result;
00756         GnomeVFSFileSize  bytes_read;
00757 
00758         f_result = gnome_vfs_seek(file, GNOME_VFS_SEEK_START, part->offset);
00759         if(f_result != GNOME_VFS_OK)
00760         {
00761                 g_warning("XDXF/%s->%s() failed. Not possible to seek "
00762                           "through file!\n",
00763                           __FILE__,
00764                           __FUNCTION__ );
00765                 /* timer(TIMER_STOP,(gchar*)__FUNCTION__); */
00766                 return result;
00767         };
00768 
00769         result = g_try_malloc((part->length + 1) * sizeof(gchar));
00770         if(result == NULL) {
00771                 g_warning("XDXF/%s->%s() failed. Not possible to allocate "
00772                           "so big memmory chunk!\n",
00773                           __FILE__,
00774                           __FUNCTION__ );
00775                 /* timer(TIMER_STOP,(gchar*)__FUNCTION__); */
00776                 return result;
00777         };
00778 
00779         f_result = gnome_vfs_read (file, result, part->length, &bytes_read);
00780         if((f_result != GNOME_VFS_OK) ||
00781                 (((gulong)bytes_read) != part->length)) {
00782                 g_debug("XDXF/%s->%s() failed. Not possible to read from "
00783                         "file!\n",
00784                         __FILE__,
00785                         __FUNCTION__ );
00786                 /* timer(TIMER_STOP,(gchar*)__FUNCTION__); */
00787                 g_free(result); result = NULL;
00788                 return result;
00789         };
00790         result[part->length] = '\0';
00791 
00792         g_debug("XDXF/%s->%s() returned string=\n\'%s\'.\n",
00793                 __FILE__,
00794                 __FUNCTION__,
00795                 result );
00796 
00797         /* timer(TIMER_STOP,(gchar*)__FUNCTION__); */
00798         return result;
00799 }
00800 
00816 static gchar* string_to_path(gchar** string) {
00817         g_debug("XDXF/%s->%s() called.\n"
00818                 "-->PARAM:string=\'%s\'\n",
00819                 __FILE__,
00820                 __FUNCTION__,
00821                 string[0] );
00822         gchar* arg = string[0];
00823         gchar* new = NULL;
00824 
00825         /* cleaning from leading and trailing whitespaces */
00826         g_strstrip(arg);
00827 
00828         /* add current directory if this is not absolute directory */
00829         if (!g_path_is_absolute(arg))
00830         {
00831                 gchar* tmp = g_get_current_dir();
00832                 new = g_strconcat(tmp,"/",arg,NULL);
00833                 g_free(arg); arg = new; new = NULL;
00834         };
00835 
00836         /* this is not a directory */
00837         if (!g_file_test(arg, G_FILE_TEST_IS_DIR))
00838         {
00839                 /* if this is wrong filepath, string was wrong */
00840                 if (!g_file_test(arg, G_FILE_TEST_IS_REGULAR))
00841                 {
00842                         g_free(arg);
00843                         new = NULL;
00844                 }
00845                 else
00846                 {
00847                         /* if this is a file, remove filename */
00848                         new = g_path_get_dirname (arg);
00849                         g_free(arg);
00850                 }
00851         }
00852         else
00853         {
00854                 /* this is a directory ... */
00855                 /* remove suffix "/" if neded... */
00856                 if (g_str_has_suffix(arg,"/") )
00857                 {
00858                         new = g_path_get_dirname (arg);
00859                         g_free(arg);
00860                 }
00861                 else
00862                 {
00863                         new = arg;
00864                 }
00865         };
00866 
00867         /* now in new should be proper filepath, if not, string was wrong */
00868         if (!g_file_test(new, G_FILE_TEST_IS_DIR))
00869         {
00870                 /* if that directory does not exist, passed string wasn't proper
00871                  */
00872                 g_free(new);
00873                 new = NULL;
00874         };
00875 
00876         /* replace string under passed address */
00877         string[0] = new;
00878         g_debug("XDXF/%s->%s() returned string=\'%s\'\n",
00879                  __FILE__,
00880                  __FUNCTION__,
00881                  string[0] );
00882         return new;
00883 }
00884 
00889 static gboolean is_xdxf_file(gchar* file) {
00890         g_debug("XDXF/%s->%s() called.\n"
00891                 "-->PARAM:file=\'%s\'\n",
00892                 __FILE__,
00893                 __FUNCTION__,
00894                 file );
00895 
00896         gboolean                result = TRUE;
00897         GnomeVFSHandle*         fd     = NULL;
00898         GnomeVFSResult          file_result;
00899         GnomeVFSFileSize        bytes_read;
00900 
00901         if(!gnome_vfs_initialized ())
00902         {
00903                 gnome_vfs_init ();
00904         };
00905 
00906         file_result = gnome_vfs_open (&fd, file, GNOME_VFS_OPEN_READ);
00907         if(file_result != GNOME_VFS_OK)
00908         {
00909                 g_warning("XDXF/%s->%s() Could not open the file.\n",
00910                           __FILE__,
00911                           __FUNCTION__ );
00912                 return FALSE;
00913         };
00914 
00915         XML_Parser p = XML_ParserCreate(NULL);
00916         if (!p)
00917         {
00918                 g_warning("XDXF/%s->%s() Could not open initialize "
00919                           "XML parser.\n",
00920                           __FILE__,
00921                           __FUNCTION__ );
00922                 gnome_vfs_close(fd);
00923                 return FALSE;
00924         };
00925 
00926         XML_SetElementHandler(p, is_xdxf_file_start, is_xdxf_file_end);
00927         XDXFCheckingData user_data = {TRUE, FALSE, 0};
00928         XML_SetUserData(p, &user_data);
00929         gchar buffer[DICT_CACHEING_BUFF_SIZE];
00930 
00931         guint loop_count = 0;
00932         while(TRUE)
00933         {
00934                 file_result = gnome_vfs_read( fd,
00935                                               buffer,
00936                                               DICT_CACHEING_BUFF_SIZE,
00937                                               &bytes_read );
00938                 if  (file_result != GNOME_VFS_OK)
00939                 {
00940                         result = FALSE;
00941                         g_warning("XDXF/%s->%s() Could not read enought from"
00942                                   " file.\n",
00943                                   __FILE__,
00944                                   __FUNCTION__ );
00945                         break;
00946                 };
00947                 if (! XML_Parse( p,
00948                                  buffer,
00949                                  (gulong)bytes_read,
00950                                  ((gulong)bytes_read) < DICT_CACHEING_BUFF_SIZE
00951                 ))
00952                 {
00953                         result = FALSE;
00954                         g_warning("XDXF/%s->%s() Could not parse file.\n",
00955                                   __FILE__,
00956                                   __FUNCTION__ );
00957                         break;
00958                 };
00959                 if (user_data.further == FALSE)
00960                 {
00961                         result = user_data.good;
00962                         g_debug("XDXF/%s->%s() statement: location is "
00963                                 "compatible with this module, is %s\n",
00964                                 __FILE__,
00965                                 __FUNCTION__,
00966                                 PRINT_STATE(result) );
00967                         break;
00968                 };
00969                 if (loop_count > 1)
00970                 {
00971                         result = FALSE;
00972                         g_debug("XDXF/%s->%s() Wrong file format.\n",
00973                                 __FILE__,
00974                                 __FUNCTION__ );
00975                         break;
00976                 };
00977                 loop_count++;
00978         }
00979 
00980         gnome_vfs_close(fd);
00981         XML_ParserFree(p);
00982         g_debug("XDXF/%s->%s() returned bool statement=%s.\n",
00983                 __FILE__,
00984                 __FUNCTION__,
00985                 PRINT_STATE(result));
00986         return result;
00987 }
00988 
00989 static void is_xdxf_file_start(void *data, const char *el, const char **attr) 
00990 {
00991         XDXFCheckingData* user_data = (XDXFCheckingData*)data;
00992         if (user_data->deep == 0) {
00993                 if (g_utf8_collate (el,"xdxf") != 0) {
00994                         user_data->good = FALSE;
00995                 }
00996                 else {
00997                         user_data->good = TRUE;
00998                 }
00999                 user_data->further = FALSE;
01000         }
01001         user_data->deep++;
01002 }
01003 static void is_xdxf_file_end(void *data, const char *el)
01004 { /* clear as far as in this callback is nothing to do */ }
01005 
01010 EngineStatus xdxf_engine_error(Engine* engine) 
01011 {
01012         g_debug("XDXF/%s->%s() called.\n",__FILE__,__FUNCTION__);
01013         XDXFData* data = (XDXFData*)(engine->engine_data);
01014         g_debug("XDXF/%s->%s() returned error code: %d\n",
01015                 __FILE__,
01016                 __FUNCTION__,
01017                (gint)(data->last_error) );
01018         return data->last_error;
01019 }
01020 
01021 static void caching_expat_start(void *data, const char *el, const char **attr) {
01022         XDXFCacheData* loc_data = (XDXFCacheData*)data;
01023         if(g_utf8_collate(el,"ar") == 0)
01024         {
01025                 loc_data->last_start =
01026                                      XML_GetCurrentByteIndex(loc_data->parser);
01027         }
01028         else if(g_utf8_collate(el,"k") == 0)
01029         {
01030                 loc_data->state = 1;
01031         }
01032 }
01033 
01034 static void caching_expat_end(void *data, const char *el) {
01035         XDXFCacheData* loc_data = (XDXFCacheData*)data;
01036         loc_data->last_stop = XML_GetCurrentByteIndex(loc_data->parser);
01037 
01038         static guint record_length;
01039         static guint start;
01040         static guint length;
01041         static guint buffer_length;
01042 
01043         if((g_utf8_collate("k",el) == 0) &&
01044            (loc_data->state == 1))
01045         {
01046                 loc_data->state = 2;
01047         }
01048         else if((g_utf8_collate("ar",el) == 0) &&
01049                 (loc_data->state == 2))
01050         {
01051                 buffer_length = loc_data->buffer_length;
01052                 record_length = sizeof(guint)*3 + loc_data->buffer_length;
01053                 start = loc_data->last_start;
01054                 length = loc_data->last_stop + strlen("</ar>") -
01055                                                       loc_data->last_start;
01056 
01057                 gboolean error_writting = FALSE;
01058                 GnomeVFSFileSize bytes_written;
01059                 GnomeVFSResult vfs_result;
01060 
01061                 vfs_result = gnome_vfs_write(loc_data->cache,
01062                                              &record_length,
01063                                              sizeof(guint),
01064                                              &bytes_written );
01065                 if(vfs_result != GNOME_VFS_OK) error_writting = TRUE;
01066 
01067                 vfs_result = gnome_vfs_write(loc_data->cache,
01068                                              loc_data->buffer,
01069                                              loc_data->buffer_length,
01070                                              &bytes_written );
01071                 if(vfs_result != GNOME_VFS_OK) error_writting = TRUE;
01072 
01073                 vfs_result = gnome_vfs_write(loc_data->cache,
01074                                              &start,
01075                                              sizeof(guint),
01076                                              &bytes_written );
01077                 if(vfs_result != GNOME_VFS_OK) error_writting = TRUE;
01078 
01079                 vfs_result = gnome_vfs_write(loc_data->cache,
01080                                              &length,
01081                                              sizeof(guint),
01082                                              &bytes_written );
01083                 if(vfs_result != GNOME_VFS_OK) error_writting = TRUE;
01084 
01085                 loc_data->buffer[0] = '\0';
01086                 loc_data->buffer_length = 0;
01087                 loc_data->state = 0;
01088         };
01089 }
01090 
01091 static void caching_expat_text(void *data, const XML_Char *txt, int len) {
01092         XDXFCacheData* loc_data = (XDXFCacheData*)data;
01093 
01094         if(loc_data->state == 1)
01095         {
01096                 memcpy( &(loc_data->buffer[loc_data->buffer_length]),
01097                         (gchar*)txt,
01098                         len );
01099                 loc_data->buffer_length += (long)len;
01100                 loc_data->buffer[loc_data->buffer_length] = '\0';
01101         };
01102 }
01103 
01108 static guint64 get_file_size(GnomeVFSHandle* file)
01109 {
01110         guint64 result = 0;
01111         guint64 old_pos = 0;
01112         gnome_vfs_tell(file, &old_pos);
01113 
01114         if( gnome_vfs_seek(file, GNOME_VFS_SEEK_END, 0) != GNOME_VFS_OK)
01115         {
01116                 return 0;
01117         }
01118 
01119         if( gnome_vfs_tell(file, &result) != GNOME_VFS_OK)
01120         {
01121                 result = 0;
01122         }
01123 
01124         gnome_vfs_seek(file, GNOME_VFS_SEEK_START, old_pos);
01125         return result;
01126 }
01127 
01131 void xdxf_engine_optimize(Engine* engine)
01132 {
01133         g_debug("XDXF/%s->%s() called for engine at adress=%p\n",
01134                 __FILE__,
01135                 __FUNCTION__,
01136                 engine );
01137         /* timer(TIMER_START,(gchar*)__FUNCTION__); */
01138 
01139         GnomeVFSResult vfs_result;
01140         XDXFData* data = (XDXFData*)(engine->engine_data);
01141         gchar* cache_path = g_strconcat(data->dict_path,"/dict.cache",NULL);
01142         vfs_result = gnome_vfs_create(&(data->cache),
01143                                       cache_path,
01144                                       GNOME_VFS_OPEN_WRITE,
01145                                       FALSE,
01146                                       0666 );
01147 
01148         if(vfs_result != GNOME_VFS_OK)
01149         {
01150                 data->cache = NULL;
01151                 g_warning("XDXF/%s->%s().Could not create new "
01152                           "cache file: %s.\n",
01153                           __FILE__,
01154                           __FUNCTION__,
01155                           cache_path );
01156         }
01157         else
01158         {
01159                 XDXFCacheData* c_data = 
01160                          (XDXFCacheData*)g_try_malloc(sizeof(XDXFCacheData));
01161                 c_data->parser = XML_ParserCreate(NULL);
01162                 c_data->cache = data->cache;
01163                 c_data->buffer = 
01164                 (gchar*)g_try_malloc(sizeof(gchar)*DICT_CACHEING_BUFF_SIZE);
01165                 c_data->buffer_length = 0;
01166                 c_data->last_start = 0;
01167                 c_data->last_stop = 0;
01168                 c_data->last_length = 0;
01169                 
01170                 guint64 file_size = get_file_size(data->xdxf);
01171 
01172                 XML_SetUserData(c_data->parser, (gpointer)c_data);
01173                 XML_SetElementHandler(c_data->parser,
01174                                       caching_expat_start,
01175                                       caching_expat_end );
01176                 XML_SetCharacterDataHandler(c_data->parser, caching_expat_text);
01177 
01178                 GnomeVFSFileSize bytes_readed = DICT_CACHEING_BUFF_SIZE;
01179                 gchar b[DICT_CACHEING_BUFF_SIZE + 1];
01180                 gdouble last_prog = 0;
01181                 while(TRUE)
01182                 {
01183                         vfs_result = gnome_vfs_read( data->xdxf,
01184                                                      b,
01185                                                      DICT_CACHEING_BUFF_SIZE,
01186                                                      &bytes_readed );
01187                         XML_Parse(c_data->parser,
01188                                   b,
01189                                   bytes_readed,
01190                                   bytes_readed < DICT_CACHEING_BUFF_SIZE );
01191 
01192                         if(data->cb_progress_caching != NULL)
01193                         {
01194                                 GnomeVFSFileSize act_pos;
01195                                 gnome_vfs_tell(data->xdxf, &act_pos);
01196                                 gdouble progress = ((gdouble)act_pos)/
01197                                                         ((gdouble)file_size);
01198                                 if((( (progress - last_prog) /
01199                                     (data->cb_progress_caching_seed) ) > 1.0) ||
01200                                     (progress >= 1.0))
01201                                 {
01202                                         data->cb_progress_caching(
01203                                                 progress,
01204                                                 data->cb_progress_caching_data,
01205                                                 ENGINE_NO_ERROR );
01206                                         last_prog = progress;
01207                                 };
01208                         }
01209                         if(bytes_readed < DICT_CACHEING_BUFF_SIZE)
01210                         {
01211                                 break;
01212                         }
01213                 }
01214 
01215                 g_free(c_data->buffer);
01216                 g_free(c_data);
01217         }
01218 
01219         vfs_result = gnome_vfs_close(data->cache);
01220         vfs_result = gnome_vfs_open( &(data->cache),
01221                                      cache_path,
01222                                      GNOME_VFS_OPEN_READ );
01223         g_free(cache_path); cache_path = NULL;
01224         /* timer(TIMER_STOP,(gchar*)__FUNCTION__); */
01225         g_debug("XDXF/%s->%s()'s work finished.\n",__FILE__,__FUNCTION__);
01226 }
01227 
01232 gboolean xdxf_engine_check(gchar* location) 
01233 {
01234         g_debug("XDXF/%s->%s() called.\n-->PARAM:location=\'%s\'\n",
01235                 __FILE__,
01236                 __FUNCTION__,
01237                 location );
01238         /* timer(TIMER_START,(gchar*)__FUNCTION__); */
01239         gboolean result = TRUE;        
01240         gchar* filepath = g_strdup(location);
01241         gchar* tmp = NULL;
01242 
01243         string_to_path(&filepath);
01244         if (filepath == NULL)
01245         {
01246                 result = FALSE;
01247                 g_warning("XDXF/%s->%s() location \'%s\' is not a proper "
01248                         "path!\n",
01249                         __FILE__,
01250                         __FUNCTION__,
01251                         location
01252                         );
01253         }
01254         else
01255         {
01256                 tmp = g_strconcat(filepath,"/dict.xdxf",NULL);
01257                 g_free(filepath);
01258                 filepath = tmp;
01259                 tmp = NULL;
01260 
01261                 g_debug("XDXF/%s->%s() finnal file to check is: %s\n",
01262                         __FILE__,
01263                         __FUNCTION__,
01264                         filepath
01265                 );
01266                 if (!g_file_test(filepath, G_FILE_TEST_IS_REGULAR))
01267                 {
01268                         g_warning("XDXF/%s->%s() file \'%s\' does not "
01269                                 "exists!\n",
01270                                 __FILE__,
01271                                 __FUNCTION__,
01272                                 filepath
01273                                 );
01274                         result = FALSE;
01275                 };
01276         };
01277         if (result != FALSE) {
01278                 result = is_xdxf_file(filepath);
01279         };
01280 
01281         g_free(filepath);
01282         /* timer(TIMER_STOP,(gchar*)__FUNCTION__); */
01283         g_debug("XDXF/%s->%s() returned bool statement=%s.\n",
01284                 __FILE__,
01285                 __FUNCTION__,
01286                 PRINT_STATE(result)
01287         );
01288         return result;
01289 }
01290 
01296 static guint get_max_length(gchar* a, guint length) 
01297 {
01298         gchar* b = a;
01299         guint len = 0;
01300         guint n = 0;
01301         memcpy(&n,b,sizeof(guint));
01302         while((len + n) <= length) {
01303                 len += n;
01304                 b = b + n;
01305                 if(len >= (length-sizeof(guint))) break;
01306                 memcpy(&n,b,sizeof(guint));
01307         }
01308         return len;
01309 }
01310 
01315 void xdxf_engine_set_auto_free(Engine* engine, gboolean state) 
01316 {
01317         g_debug( "XDXF/%s->%s() called.\n"
01318                  "-->PARAM:engine at adress=%p\n"
01319                  "-->PARAM:state=%s\n",
01320                  __FILE__,
01321                  __FUNCTION__,
01322                  engine,
01323                  PRINT_STATE(state) );
01324         g_assert(engine != NULL);
01325         XDXFData* data = (XDXFData*)(engine->engine_data);
01326         data->auto_free = state;
01327         g_debug( "XDXF/%s->%s() Current auto_free is %s\n",
01328                  __FILE__,
01329                  __FUNCTION__,
01330                  PRINT_STATE(data->auto_free) );
01331 }
01332 
01336 gchar* xdxf_engine_version() 
01337 {
01338         g_debug("XDXF/%s->%s() called.\n",__FILE__,__FUNCTION__);
01339         gchar* result = g_strdup(DIC_ENG_VERSION);
01340         g_debug( "XDXF/%s->%s() return string=%s\n",
01341                  __FILE__,
01342                  __FUNCTION__,
01343                  result );
01344         return result;
01345 }
01346 
01350 gchar* xdxf_engine_format() 
01351 {
01352         g_debug("XDXF/%s->%s() called.\n",__FILE__,__FUNCTION__);
01353         gchar* result = g_strdup(DIC_ENG_FORMAT);
01354         g_debug("XDXF/%s->%s() return string=%s\n",
01355                 __FILE__,
01356                 __FUNCTION__,
01357                 result
01358         );
01359         return result;
01360 }
01361 
01365 gchar* xdxf_engine_description() 
01366 {
01367         g_debug("XDXF/%s->%s() called.\n",__FILE__,__FUNCTION__);
01368         gchar* result = g_strdup("This module operates on " 
01369                                  DIC_ENG_FORMAT
01370                                  " dictionaries. Version "
01371                                  DIC_ENG_VERSION
01372                                  "." );
01373         g_debug("XDXF/%s->%s() return string=%s\n",
01374                 __FILE__,
01375                 __FUNCTION__,
01376                 result );
01377         return result;
01378 }
01379 
01384 gboolean xdxf_engine_is_optimized(Engine* engine) 
01385 {
01386         g_debug("XDXF/%s->%s() called.\n-->PARAM: engine adress=%p\n",
01387                 __FILE__,
01388                 __FUNCTION__,
01389                 engine );
01390 
01391         g_assert(engine != NULL);
01392         XDXFData* data = (XDXFData*)(engine->engine_data);
01393         gboolean result = (data->cache != NULL);
01394         g_debug("XDXF/%s->%s() returned bool statement=%s.\n",
01395                 __FILE__,
01396                 __FUNCTION__,
01397                 PRINT_STATE(result) );
01398         return result;
01399 }
01400 
01405 gchar* xdxf_engine_location(Engine* engine)
01406 {
01407         g_debug("XDXF/%s->%s() called.\n-->PARAM: engine adress=%p\n",
01408                 __FILE__,
01409                 __FUNCTION__,
01410                 engine );
01411         g_assert(engine != NULL);
01412         XDXFData* data = (XDXFData*)(engine->engine_data);
01413         gchar* result;
01414         if(data->auto_free)
01415         {
01416                 result = data->dict_path;
01417         }
01418         else
01419         {
01420                 result = g_strdup(data->dict_path);
01421         }
01422 
01423         g_debug("XDXF/%s->%s() returned string=%s\n",
01424                 __FILE__,
01425                 __FUNCTION__,
01426                 result );
01427         return result;
01428 }
01429 
01430 static void search_word_list_start(void *data,
01431                                    const char *el,
01432                                    const char **attr )
01433 {
01434         XDXFWordsListData* loc_data = (XDXFWordsListData*)data;
01435         if( ('k' == el[0]) && ('\0' == el[1]) ) {
01436                 loc_data->one_word = 1;
01437         };
01438 }
01439 
01440 static void search_word_list_end(void *data, const char *el)
01441 {
01442         static gboolean matched   = FALSE;
01443         static gchar* tmp = NULL;
01444 
01445         XDXFWordsListData* loc_data = (XDXFWordsListData*)data;
01446         GPatternSpec* regex;
01447         regex = g_pattern_spec_new (loc_data->pattern);
01448         
01449         if( ('k' == el[0]) && ('\0' == el[1]) )
01450         {
01451                 loc_data->one_word = 0;
01452         }
01453         else
01454         {
01455                 return;
01456         }
01457 
01458         gchar *tmp1 = g_strconcat (loc_data->last_word, " ", NULL);
01459         tmp = g_utf8_casefold(tmp1, -1);
01460         g_free (tmp1);
01461         tmp1 = g_utf8_casefold(loc_data->last_word, -1);
01462 
01463         if (( g_pattern_match_string (regex, tmp) == TRUE ) ||
01464             ( g_pattern_match_string (regex, tmp1) == TRUE ) )
01465         {
01466                 matched = TRUE;
01467                 gchar* new = g_strdup(loc_data->last_word);
01468                 g_array_append_val((loc_data->result), new);
01469                 g_debug("New Word for pattern \"%s\" found: %s\n",
01470                         loc_data->pattern,
01471                         new );
01472         }
01473         else
01474         {
01475                 matched = FALSE;
01476         }
01477 
01478         /* "clearing" buffer for next word */
01479         loc_data->last_word_length = 0;
01480         /* if we passed words matching -> ends */
01481         if( (loc_data->result->len > 0) && (!matched) )
01482         {
01483                 loc_data->cont = FALSE;
01484         };
01485 
01486         g_free(tmp); tmp = NULL;
01487         g_free(tmp1);
01488         g_pattern_spec_free (regex);
01489 }
01490 
01491 static void search_word_list_text(void *data, const XML_Char *txt, int len) 
01492 {
01493         XDXFWordsListData* loc_data = (XDXFWordsListData*)data;
01494 
01495         if(1 == loc_data->one_word)
01496         {
01497                 memcpy( &(loc_data->last_word[loc_data->last_word_length]),
01498                         (gchar*)txt,
01499                         len );
01500                 loc_data->last_word_length += (guint)len;
01501                 loc_data->last_word[loc_data->last_word_length] = '\0';
01502         };
01503 }
01504 
01511 static void word_list_cache(XDXFData* data,
01512                             gchar* pattern,
01513                             GArray* result,
01514                             gpointer cb_data)
01515 {
01516         gnome_vfs_seek(data->cache, GNOME_VFS_SEEK_START, 0);
01517 
01518         GnomeVFSFileSize bytes_readed;
01519         guint record_length = 0;
01520         gchar buffer[DICT_SEARCHING_WORD_LIST_BUFF_SIZE];
01521         gchar* buf;
01522         guint already = 0;
01523         guint max_length = 0;
01524         guint64 file_size = get_file_size(data->cache);
01525         gchar* casefold_pattern = g_utf8_casefold(pattern, -1);
01526 
01527         
01528         GPatternSpec* regex;
01529         regex = g_pattern_spec_new (casefold_pattern);
01530         
01531         guint i = 0;
01532         while(TRUE)
01533         {
01534                 gnome_vfs_read( data->cache,
01535                                 buffer,
01536                                 DICT_SEARCHING_WORD_LIST_BUFF_SIZE,
01537                                 &bytes_readed );
01538 
01539                 max_length = get_max_length(buffer, (guint)bytes_readed);
01540                 already += max_length;
01541                 buf = buffer;
01542 
01543                 guint how_far = 0;
01544                 while(how_far < max_length)
01545                 {
01546                         ++i;
01547                         memcpy(&record_length, buf, sizeof(guint));
01548                         buf[record_length-sizeof(guint)*2] = '\0';
01549                         
01550                         gchar *tmp1 = g_strconcat( buf + sizeof(guint),
01551                                                    " ",
01552                                                    NULL );
01553                         gchar* tmp = g_utf8_casefold(tmp1, -1);
01554                         g_free (tmp1);
01555 
01556                         if ( g_pattern_match_string (regex, tmp) == TRUE )
01557                         {
01558                                 gchar* new = g_strndup(buf + sizeof(guint),
01559                                                        record_length -
01560                                                        3*sizeof(guint) );
01561                                 g_array_append_val(result, new);
01562                                 g_debug("New Word for pattern \"%s\" found: "
01563                                         "%s (pos:%d)\n",
01564                                         pattern,
01565                                         new,
01566                                         i );
01567                         };
01568                         how_far += record_length;
01569                         buf = buf + record_length;
01570                         g_free(tmp); tmp = NULL;
01571                 }
01572                 if( (bytes_readed < DICT_SEARCHING_WORD_LIST_BUFF_SIZE) ||
01573                      (already > (file_size -3)) )
01574                 {
01575                         break;
01576                 }
01577 
01578                 gnome_vfs_seek( data->cache,
01579                                 GNOME_VFS_SEEK_CURRENT,
01580                                 (gint)max_length -
01581                                 DICT_SEARCHING_WORD_LIST_BUFF_SIZE );
01582         }
01583 
01584         /* timer(TIMER_STOP,(gchar*)__FUNCTION__); */
01585         /* timer(TIMER_START,"callback for returning words list START"); */
01586         data->cb_search_word_list( result,
01587                                    pattern,
01588                                    cb_data,
01589                                    ENGINE_NO_ERROR );
01590         g_free(casefold_pattern);
01591         casefold_pattern = NULL;
01592         /* timer(TIMER_STOP,"callback for returning words list END"); */
01593 }
01594 
01601 static void word_list_xdxf(XDXFData* data,
01602                            gchar* pattern,
01603                            GArray* result,
01604                            gpointer cb_data)
01605 {
01606         gnome_vfs_seek(data->xdxf, GNOME_VFS_SEEK_START, 0);
01607         GnomeVFSResult vfs_result;
01608         GnomeVFSFileSize bytes_readed = DICT_SEARCHING_WORD_LIST_BUFF_SIZE;
01609         gchar buffer[DICT_SEARCHING_WORD_LIST_BUFF_SIZE+1];
01610         guint64 file_size = get_file_size(data->xdxf);
01611         gchar* casefold_pattern = g_utf8_casefold(pattern, -1);
01612         guint pattern_len = strlen(casefold_pattern);
01613         
01614 
01615         XML_Parser parser = XML_ParserCreate(NULL);
01616         if (!parser)
01617         {
01618                 g_warning("XDXF/%s->%s() Could not open initialize XML "
01619                         "parser.\n",
01620                         __FILE__,
01621                         __FUNCTION__
01622                         );
01623                 /* timer(TIMER_STOP,(gchar*)__FUNCTION__); */
01624                 return;
01625         };
01626 
01627         gchar tmp[DICT_MAX_WORD_LENGTH];
01628         XML_SetElementHandler( parser,
01629                                search_word_list_start,
01630                                search_word_list_end );
01631         XML_SetCharacterDataHandler(parser, search_word_list_text);
01632 
01633         /*
01634          buffer for single word 
01635          pattern to search 
01636          length of pattern 
01637          actal length of readed word 
01638          array to append words 
01639          continuation of the same word 
01640          continue of searching?
01641         */
01642         XDXFWordsListData search_data = { tmp,
01643                                           casefold_pattern,
01644                                           pattern_len,
01645                                           0,
01646                                           result,
01647                                           0,
01648                                           TRUE
01649                                         };
01650         XML_SetUserData(parser, &search_data);
01651 
01652         gdouble last_prog = 0;
01653         while(TRUE) {
01654                 vfs_result = gnome_vfs_read( data->xdxf,
01655                                              buffer,
01656                                              DICT_SEARCHING_WORD_LIST_BUFF_SIZE,
01657                                              &bytes_readed );
01658                 XML_Parse( parser,
01659                            buffer,
01660                            bytes_readed,
01661                            bytes_readed < DICT_SEARCHING_WORD_LIST_BUFF_SIZE );
01662 
01663                 if(NULL != data->cb_progress_word_list)
01664                 {
01665                         GnomeVFSFileSize act_pos;
01666                         gnome_vfs_tell(data->xdxf, &act_pos);
01667                         gdouble progress = ((gdouble)act_pos)/
01668                                                         ((gdouble)file_size);
01669                         if((((progress - last_prog)/
01670                              (data->cb_progress_word_list_seed)) > 1.0) ||
01671                              (progress >= 1.0))
01672                         {
01673                                 data->cb_progress_word_list(
01674                                           progress,
01675                                           data->cb_progress_word_list_data,
01676                                           ENGINE_NO_ERROR );
01677                                 last_prog = progress;
01678                         };
01679                 };
01680 
01681                 if(bytes_readed < DICT_SEARCHING_WORD_LIST_BUFF_SIZE)
01682                 {
01683                         break;
01684                 };
01685 
01686                 if(FALSE == search_data.cont)
01687                 {
01688                         g_debug("XDXF/%s->%s() We found every words matching "
01689                                 "pattern \"%s\". Abort further searching.\n",
01690                                 __FILE__,
01691                                 __FUNCTION__,
01692                                 pattern
01693                         );
01694                         break;
01695                 };
01696         }
01697         XML_ParserFree(parser);
01698         g_free(casefold_pattern); casefold_pattern = NULL;
01699 
01700         /* timer(TIMER_STOP,(gchar*)__FUNCTION__); */
01701         /* timer(TIMER_START,"callback for returning words list START"); */
01702         data->cb_search_word_list( result,
01703                                    pattern,
01704                                    cb_data,
01705                                    ENGINE_NO_ERROR );
01706         /* timer(TIMER_STOP,"callback for returning words list END"); */
01707 }
01708 
01714 void xdxf_engine_search_word_list(Engine* engine,
01715                                   gchar* pattern,
01716                                   gpointer user_data)
01717 {
01718         g_debug("XDXF/%s->%s() called. Searching words list\n"
01719                 "-->PARAM:engine at adress=%p\n"
01720                 "-->PARAM:pattern=\"%s\"\n",
01721                 __FILE__,
01722                 __FUNCTION__,
01723                 engine,
01724                 pattern );
01725 
01726         g_assert(engine != NULL);
01727         g_assert(pattern != NULL);
01728 
01729         /* timer(TIMER_START,(gchar*)__FUNCTION__); */
01730         XDXFData* data = (XDXFData*)(engine->engine_data);
01731         if(data->cb_search_word_list == NULL)
01732         {
01733                 g_warning( "XDXF/%s->%s() callback for Word List not set. "
01734                            "Searching aborted.\n",
01735                            __FILE__,
01736                            __FUNCTION__ );
01737                 /* timer(TIMER_STOP,(gchar*)__FUNCTION__); */
01738                 return;
01739         };
01740 
01741         gpointer cb_data =  user_data;
01742         if ( NULL == cb_data )
01743         {
01744                 cb_data = data->cb_search_word_list_data;
01745         }
01746 
01747         GArray* result = g_array_new(TRUE,FALSE,sizeof(gchar*));
01748         /* dictionary is optimized so search in cache file */
01749         if(data->cache != NULL)
01750         {
01751                 word_list_cache(data, pattern, result, cb_data);
01752         }
01753         else
01754         {
01755                 /* dictionary is not optimized-search directly fom XDXF file */
01756                 word_list_xdxf(data, pattern, result, cb_data);
01757         };
01758 
01759         guint i = 0;
01760         if (result!=NULL){
01761                 for (i = 0; i < result->len; i++)
01762                 {
01763                         g_free(g_array_index(result, gchar*, i));
01764                 }
01765                 g_array_free(result, TRUE);
01766                 result = NULL;
01767         }
01768 
01769         g_debug("XDXF/%s->%s() finished definately its work.\n",
01770                 __FILE__,
01771                 __FUNCTION__
01772         );
01773         return;
01774 }
01775 

Generated on Fri Jan 11 14:30:17 2008 for mDictionary Project by  doxygen 1.5.1