1 /* 2 * libpinyin 3 * Library to deal with pinyin. 4 * 5 * Copyright (C) 2006-2007 Peng Wu 6 * 7 * This program is free software: you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation, either version 3 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program. If not, see <http://www.gnu.org/licenses/>. 19 */ 20 21 #ifndef PHRASE_INDEX_H 22 #define PHRASE_INDEX_H 23 24 #include <stdio.h> 25 #include <glib.h> 26 #include "novel_types.h" 27 #include "chewing_key.h" 28 #include "pinyin_parser2.h" 29 #include "zhuyin_parser2.h" 30 #include "pinyin_phrase3.h" 31 #include "memory_chunk.h" 32 #include "phrase_index_logger.h" 33 #include "table_info.h" 34 35 /** 36 * Phrase Index File Format 37 * 38 * Indirect Index: Index by Token 39 * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 40 * + Phrase Offset + Phrase Offset + Phrase Offset + ...... + 41 * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 42 * Phrase Content: 43 * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 44 * + Phrase Length + number of Pronunciations + Uni-gram Frequency+ 45 * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 46 * + Phrase String(UCS4) + n Pronunciations with Frequency + 47 * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 48 */ 49 50 namespace pinyin{ 51 52 /* Store delta info by phrase index logger in user home directory. 53 */ 54 55 const size_t phrase_item_header = sizeof(guint8) + sizeof(guint8) + sizeof(guint32); 56 57 /** 58 * PhraseItem: 59 * 60 * The PhraseItem to access the items in phrase index. 61 * 62 */ 63 class PhraseItem{ 64 friend class SubPhraseIndex; 65 friend bool _compute_new_header(PhraseIndexLogger * logger, 66 phrase_token_t mask, 67 phrase_token_t value, 68 guint32 & new_total_freq); 69 70 private: 71 MemoryChunk m_chunk; 72 bool set_n_pronunciation(guint8 n_prouns); 73 public: 74 /** 75 * PhraseItem::PhraseItem: 76 * 77 * The constructor of the PhraseItem. 78 * 79 */ PhraseItem()80 PhraseItem(){ 81 m_chunk.set_size(phrase_item_header); 82 memset(m_chunk.begin(), 0, m_chunk.size()); 83 } 84 85 #if 0 86 PhraseItem(MemoryChunk & chunk){ 87 m_chunk.set_content(0, chunk->begin(), chunk->size()); 88 assert ( m_chunk.size() >= phrase_item_header); 89 } 90 #endif 91 92 /** 93 * PhraseItem::get_phrase_length: 94 * @returns: the length of this phrase item. 95 * 96 * Get the length of this phrase item. 97 * 98 */ get_phrase_length()99 guint8 get_phrase_length(){ 100 char * buf_begin = (char *)m_chunk.begin(); 101 return (*(guint8 *)buf_begin); 102 } 103 104 /** 105 * PhraseItem::get_n_pronunciation: 106 * @returns: the number of the pronunciations. 107 * 108 * Get the number of the pronunciations. 109 * 110 */ get_n_pronunciation()111 guint8 get_n_pronunciation(){ 112 char * buf_begin = ( char *) m_chunk.begin(); 113 return (*(guint8 *)(buf_begin + sizeof(guint8))); 114 } 115 116 /** 117 * PhraseItem::get_unigram_frequency: 118 * @returns: the uni-gram frequency of this phrase item. 119 * 120 * Get the uni-gram frequency of this phrase item. 121 * 122 */ get_unigram_frequency()123 guint32 get_unigram_frequency(){ 124 char * buf_begin = (char *)m_chunk.begin(); 125 return (*(guint32 *)(buf_begin + sizeof(guint8) + sizeof(guint8))); 126 } 127 128 /** 129 * PhraseItem::get_pronunciation_possibility: 130 * @keys: the pronunciation keys. 131 * @returns: the possibility of this phrase item pronounces the pinyin. 132 * 133 * Get the possibility of this phrase item pronounces the pinyin. 134 * 135 */ get_pronunciation_possibility(ChewingKey * keys)136 gfloat get_pronunciation_possibility(ChewingKey * keys){ 137 guint8 phrase_length = get_phrase_length(); 138 guint8 npron = get_n_pronunciation(); 139 size_t offset = phrase_item_header + phrase_length * sizeof (ucs4_t); 140 char * buf_begin = (char *)m_chunk.begin(); 141 guint32 matched = 0, total_freq =0; 142 for ( int i = 0 ; i < npron ; ++i){ 143 char * chewing_begin = buf_begin + offset + 144 i * (phrase_length * sizeof(ChewingKey) + sizeof(guint32)); 145 guint32 * freq = (guint32 *)(chewing_begin + 146 phrase_length * sizeof(ChewingKey)); 147 total_freq += *freq; 148 if ( 0 == pinyin_compare_with_tones(keys, (ChewingKey *)chewing_begin, 149 phrase_length) ){ 150 matched += *freq; 151 } 152 } 153 154 #if 1 155 /* an additional safe guard for chewing. */ 156 if ( 0 == total_freq ) 157 return 0; 158 #endif 159 160 /* used preprocessor to avoid zero freq, in gen_pinyin_table. */ 161 gfloat retval = matched / (gfloat) total_freq; 162 return retval; 163 } 164 165 /** 166 * PhraseItem::increase_pronunciation_possibility: 167 * @keys: the pronunciation keys. 168 * @delta: the delta to be added to the pronunciation keys. 169 * 170 * Add the delta to the pronunciation of the pronunciation keys. 171 * 172 */ 173 void increase_pronunciation_possibility(ChewingKey * keys, 174 gint32 delta); 175 176 /** 177 * PhraseItem::get_phrase_string: 178 * @phrase: the ucs4 character buffer. 179 * @returns: whether the get operation is successful. 180 * 181 * Get the ucs4 characters of this phrase item. 182 * 183 */ 184 bool get_phrase_string(ucs4_t * phrase); 185 186 /** 187 * PhraseItem::set_phrase_string: 188 * @phrase_length: the ucs4 character length of this phrase item. 189 * @phrase: the ucs4 character buffer. 190 * @returns: whether the set operation is successful. 191 * 192 * Set the length and ucs4 characters of this phrase item. 193 * 194 */ 195 bool set_phrase_string(guint8 phrase_length, ucs4_t * phrase); 196 197 /** 198 * PhraseItem::get_nth_pronunciation: 199 * @index: the pronunciation index. 200 * @keys: the pronunciation keys. 201 * @freq: the frequency of the pronunciation. 202 * @returns: whether the get operation is successful. 203 * 204 * Get the nth pronunciation of this phrase item. 205 * 206 */ 207 bool get_nth_pronunciation(size_t index, 208 /* out */ ChewingKey * keys, 209 /* out */ guint32 & freq); 210 211 /** 212 * PhraseItem::add_pronunciation: 213 * @keys: the pronunciation keys. 214 * @delta: the delta of the frequency of the pronunciation. 215 * @returns: whether the add operation is successful. 216 * 217 * Add one pronunciation. 218 * 219 */ 220 bool add_pronunciation(ChewingKey * keys, guint32 delta); 221 222 /** 223 * PhraseItem::remove_nth_pronunciation: 224 * @index: the pronunciation index. 225 * 226 * Remove the nth pronunciation. 227 * 228 * Note: Normally don't change the first pronunciation, 229 * which decides the token number. 230 * 231 */ 232 void remove_nth_pronunciation(size_t index); 233 234 bool operator == (const PhraseItem & rhs) const{ 235 if (m_chunk.size() != rhs.m_chunk.size()) 236 return false; 237 return memcmp(m_chunk.begin(), rhs.m_chunk.begin(), 238 m_chunk.size()) == 0; 239 } 240 241 bool operator != (const PhraseItem & rhs) const{ 242 return ! (*this == rhs); 243 } 244 }; 245 246 /* 247 * In Sub Phrase Index, token == (token & PHRASE_MASK). 248 */ 249 250 /** 251 * SubPhraseIndex: 252 * 253 * The SubPhraseIndex class for internal usage. 254 * 255 */ 256 class SubPhraseIndex{ 257 private: 258 guint32 m_total_freq; 259 MemoryChunk m_phrase_index; 260 MemoryChunk m_phrase_content; 261 MemoryChunk * m_chunk; 262 reset()263 void reset(){ 264 m_total_freq = 0; 265 m_phrase_index.set_size(0); 266 m_phrase_content.set_size(0); 267 if ( m_chunk ){ 268 delete m_chunk; 269 m_chunk = NULL; 270 } 271 } 272 273 public: 274 /** 275 * SubPhraseIndex::SubPhraseIndex: 276 * 277 * The constructor of the SubPhraseIndex. 278 * 279 */ SubPhraseIndex()280 SubPhraseIndex():m_total_freq(0){ 281 m_chunk = NULL; 282 } 283 284 /** 285 * SubPhraseIndex::~SubPhraseIndex: 286 * 287 * The destructor of the SubPhraseIndex. 288 * 289 */ ~SubPhraseIndex()290 ~SubPhraseIndex(){ 291 reset(); 292 } 293 294 /** 295 * SubPhraseIndex::load: 296 * @chunk: the memory chunk of the binary sub phrase index. 297 * @offset: the begin of binary data in the memory chunk. 298 * @end: the end of binary data in the memory chunk. 299 * @returns: whether the load operation is successful. 300 * 301 * Load the sub phrase index from the memory chunk. 302 * 303 */ 304 bool load(MemoryChunk * chunk, 305 table_offset_t offset, table_offset_t end); 306 307 /** 308 * SubPhraseIndex::store: 309 * @new_chunk: the new memory chunk to store this sub phrase index. 310 * @offset: the begin of binary data in the memory chunk. 311 * @end: the end of stored binary data in the memory chunk. 312 * @returns: whether the store operation is successful. 313 * 314 * Store the sub phrase index to the new memory chunk. 315 * 316 */ 317 bool store(MemoryChunk * new_chunk, 318 table_offset_t offset, table_offset_t & end); 319 320 /** 321 * SubPhraseIndex::diff: 322 * @oldone: the original content of sub phrase index. 323 * @logger: the delta information of user self-learning data. 324 * @returns: whether the diff operation is successful. 325 * 326 * Compare this sub phrase index with the original content of the system 327 * sub phrase index to generate the logger of difference. 328 * 329 * Note: Switch to logger format to reduce user space storage. 330 * 331 */ 332 bool diff(SubPhraseIndex * oldone, PhraseIndexLogger * logger); 333 334 /** 335 * SubPhraseIndex::merge: 336 * @logger: the logger of difference in user home directory. 337 * @returns: whether the merge operation is successful. 338 * 339 * Merge the user logger of difference with this sub phrase index. 340 * 341 */ 342 bool merge(PhraseIndexLogger * logger); 343 344 /** 345 * SubPhraseIndex::get_range: 346 * @range: the token range. 347 * @returns: whether the get operation is successful. 348 * 349 * Get the token range in this sub phrase index. 350 * 351 */ 352 int get_range(/* out */ PhraseIndexRange & range); 353 354 /** 355 * SubPhraseIndex::get_phrase_index_total_freq: 356 * @returns: the total frequency of this sub phrase index. 357 * 358 * Get the total frequency of this sub phrase index. 359 * 360 * Note: maybe call it "Zero-gram". 361 * 362 */ 363 guint32 get_phrase_index_total_freq(); 364 365 /** 366 * SubPhraseIndex::add_unigram_frequency: 367 * @token: the phrase token. 368 * @delta: the delta value of the phrase token. 369 * @returns: the status of the add operation. 370 * 371 * Add delta value to the phrase of the token. 372 * 373 * Note: this method is a fast path to add delta value. 374 * Maybe use the get_phrase_item method instead in future. 375 * 376 */ 377 int add_unigram_frequency(phrase_token_t token, guint32 delta); 378 379 /** 380 * SubPhraseIndex::get_phrase_item: 381 * @token: the phrase token. 382 * @item: the phrase item of the token. 383 * @returns: the status of the get operation. 384 * 385 * Get the phrase item from this sub phrase index. 386 * 387 * Note:get_phrase_item function can't modify the phrase item size, 388 * but can increment the freq of the special pronunciation, 389 * or change the content without size increasing. 390 * 391 */ 392 int get_phrase_item(phrase_token_t token, PhraseItem & item); 393 394 /** 395 * SubPhraseIndex::add_phrase_item: 396 * @token: the phrase token. 397 * @item: the phrase item of the token. 398 * @returns: the status of the add operation. 399 * 400 * Add the phrase item to this sub phrase index. 401 * 402 */ 403 int add_phrase_item(phrase_token_t token, PhraseItem * item); 404 405 /** 406 * SubPhraseIndex::remove_phrase_item: 407 * @token: the phrase token. 408 * @item: the removed phrase item of the token. 409 * @returns: the status of the remove operation. 410 * 411 * Remove the phrase item of the token. 412 * 413 * Note: this remove_phrase_item method will substract the unigram 414 * frequency of the removed item from m_total_freq. 415 * 416 */ 417 int remove_phrase_item(phrase_token_t token, /* out */ PhraseItem * & item); 418 419 /** 420 * SubPhraseIndex::mask_out: 421 * @mask: the mask. 422 * @value: the value. 423 * @returns: whether the mask out operation is successful. 424 * 425 * Mask out the matched phrase items. 426 * 427 */ 428 bool mask_out(phrase_token_t mask, phrase_token_t value); 429 }; 430 431 /** 432 * FacadePhraseIndex: 433 * 434 * The facade class of phrase index. 435 * 436 */ 437 class FacadePhraseIndex{ 438 private: 439 guint32 m_total_freq; 440 SubPhraseIndex * m_sub_phrase_indices[PHRASE_INDEX_LIBRARY_COUNT]; 441 public: 442 /** 443 * FacadePhraseIndex::FacadePhraseIndex: 444 * 445 * The constructor of the FacadePhraseIndex. 446 * 447 */ FacadePhraseIndex()448 FacadePhraseIndex(){ 449 m_total_freq = 0; 450 memset(m_sub_phrase_indices, 0, sizeof(m_sub_phrase_indices)); 451 } 452 453 /** 454 * FacadePhraseIndex::~FacadePhraseIndex: 455 * 456 * The destructor of the FacadePhraseIndex. 457 * 458 */ ~FacadePhraseIndex()459 ~FacadePhraseIndex(){ 460 for ( size_t i = 0; i < PHRASE_INDEX_LIBRARY_COUNT; ++i){ 461 if ( m_sub_phrase_indices[i] ){ 462 delete m_sub_phrase_indices[i]; 463 m_sub_phrase_indices[i] = NULL; 464 } 465 } 466 } 467 468 /** 469 * FacadePhraseIndex::load_text: 470 * @phrase_index: the index of sub phrase index to be loaded. 471 * @infile: the textual format file of the phrase table. 472 * @type: the type of phonetic table. 473 * @returns: whether the load operation is successful. 474 * 475 * Load one sub phrase index from the textual format file. 476 * Note: load sub phrase index according to the config in future. 477 * 478 */ 479 bool load_text(guint8 phrase_index, FILE * infile, 480 TABLE_PHONETIC_TYPE type); 481 482 /** 483 * FacadePhraseIndex::load: 484 * @phrase_index: the index of sub phrase index to be loaded. 485 * @chunk: the memory chunk of sub phrase index to be loaded. 486 * @returns: whether the load operation is successful. 487 * 488 * Load one sub phrase index from the memory chunk. 489 * 490 */ 491 bool load(guint8 phrase_index, MemoryChunk * chunk); 492 493 /** 494 * FacadePhraseIndex::store: 495 * @phrase_index: the index of sub phrase index to be stored. 496 * @new_chunk: the memory chunk of sub phrase index to be stored. 497 * @returns: whether the store operation is successful. 498 * 499 * Store one sub phrase index to the memory chunk. 500 * 501 */ 502 bool store(guint8 phrase_index, MemoryChunk * new_chunk); 503 504 /** 505 * FacadePhraseIndex::unload: 506 * @phrase_index: the index of sub phrase index to be unloaded. 507 * @returns: whether the unload operation is successful. 508 * 509 * Unload one sub phrase index. 510 * 511 */ 512 bool unload(guint8 phrase_index); 513 514 515 /** 516 * FacadePhraseIndex::diff: 517 * @phrase_index: the index of sub phrase index to be differed. 518 * @oldchunk: the original content of sub phrase index. 519 * @newlog: the delta information of user self-learning data. 520 * @returns: whether the diff operation is successful. 521 * 522 * Store user delta information in the logger format. 523 * 524 * Note: the ownership of oldchunk is transfered here. 525 * 526 */ 527 bool diff(guint8 phrase_index, MemoryChunk * oldchunk, 528 MemoryChunk * newlog); 529 530 /** 531 * FacadePhraseIndex::merge: 532 * @phrase_index: the index of sub phrase index to be merged. 533 * @log: the logger of difference in user home directory. 534 * @returns: whether the merge operation is successful. 535 * 536 * Merge the user logger of difference with the sub phrase index. 537 * 538 * Note: the ownership of log is transfered here. 539 * 540 */ 541 bool merge(guint8 phrase_index, MemoryChunk * log); 542 543 /** 544 * FacadePhraseIndex::merge_with_mask: 545 * @phrase_index: the index of sub phrase index to be merged. 546 * @log: the logger of difference in user home directory. 547 * @mask: the mask. 548 * @value: the value. 549 * @returns: whether the merge operation is successful. 550 * 551 * Merge the user logger of difference with mask operation. 552 * 553 * Note: the ownership of log is transfered here. 554 * 555 */ 556 bool merge_with_mask(guint8 phrase_index, MemoryChunk * log, 557 phrase_token_t mask, phrase_token_t value); 558 559 /** 560 * FacadePhraseIndex::compact: 561 * @returns: whether the compact operation is successful. 562 * 563 * Compat all sub phrase index memory usage. 564 * 565 */ 566 bool compact(); 567 568 /** 569 * FacadePhraseIndex::mask_out: 570 * @phrase_index: the index of sub phrase index. 571 * @mask: the mask. 572 * @value: the value. 573 * @returns: whether the mask out operation is successful. 574 * 575 * Mask out the matched phrase items. 576 * 577 * Note: should call compact() after the mask out operation. 578 * 579 */ 580 bool mask_out(guint8 phrase_index, 581 phrase_token_t mask, phrase_token_t value); 582 583 /** 584 * FacadePhraseIndex::get_sub_phrase_range: 585 * @min_index: the minimal sub phrase index. 586 * @max_index: the maximal sub phrase index. 587 * @returns: the status of the get operation. 588 * 589 * Get the minimum and maximum of the sub phrase index. 590 * 591 */ 592 int get_sub_phrase_range(guint8 & min_index, guint8 & max_index); 593 594 /** 595 * FacadePhraseIndex::get_range: 596 * @phrase_index: the index of sub phrase index. 597 * @range: the token range of the sub phrase index. 598 * @returns: the status of the get operation. 599 * 600 * Get the token range of the sub phrase index. 601 * 602 */ 603 int get_range(guint8 phrase_index, /* out */ PhraseIndexRange & range); 604 605 /** 606 * FacadePhraseIndex::get_phrase_index_total_freq: 607 * @returns: the total freq of the facade phrase index. 608 * 609 * Get the total freq of the facade phrase index. 610 * 611 * Note: maybe call it "Zero-gram". 612 * 613 */ get_phrase_index_total_freq()614 guint32 get_phrase_index_total_freq(){ 615 return m_total_freq; 616 } 617 618 /** 619 * FacadePhraseIndex::add_unigram_frequency: 620 * @token: the phrase token. 621 * @delta: the delta value of the phrase token. 622 * @returns: the status of the add operation. 623 * 624 * Add delta value to the phrase of the token. 625 * 626 */ add_unigram_frequency(phrase_token_t token,guint32 delta)627 int add_unigram_frequency(phrase_token_t token, guint32 delta){ 628 guint8 index = PHRASE_INDEX_LIBRARY_INDEX(token); 629 SubPhraseIndex * sub_phrase = m_sub_phrase_indices[index]; 630 if ( !sub_phrase ) 631 return ERROR_NO_SUB_PHRASE_INDEX; 632 m_total_freq += delta; 633 return sub_phrase->add_unigram_frequency(token, delta); 634 } 635 636 /** 637 * FacadePhraseIndex::get_phrase_item: 638 * @token: the phrase token. 639 * @item: the phrase item of the token. 640 * @returns: the status of the get operation. 641 * 642 * Get the phrase item from the facade phrase index. 643 * 644 */ get_phrase_item(phrase_token_t token,PhraseItem & item)645 int get_phrase_item(phrase_token_t token, PhraseItem & item){ 646 guint8 index = PHRASE_INDEX_LIBRARY_INDEX(token); 647 SubPhraseIndex * sub_phrase = m_sub_phrase_indices[index]; 648 if ( !sub_phrase ) 649 return ERROR_NO_SUB_PHRASE_INDEX; 650 return sub_phrase->get_phrase_item(token, item); 651 } 652 653 /** 654 * FacadePhraseIndex::add_phrase_item: 655 * @token: the phrase token. 656 * @item: the phrase item of the token. 657 * @returns: the status of the add operation. 658 * 659 * Add the phrase item to the facade phrase index. 660 * 661 */ add_phrase_item(phrase_token_t token,PhraseItem * item)662 int add_phrase_item(phrase_token_t token, PhraseItem * item){ 663 guint8 index = PHRASE_INDEX_LIBRARY_INDEX(token); 664 SubPhraseIndex * & sub_phrase = m_sub_phrase_indices[index]; 665 if ( !sub_phrase ){ 666 sub_phrase = new SubPhraseIndex; 667 } 668 m_total_freq += item->get_unigram_frequency(); 669 return sub_phrase->add_phrase_item(token, item); 670 } 671 672 /** 673 * FacadePhraseIndex::remove_phrase_item: 674 * @token: the phrase token. 675 * @item: the removed phrase item of the token. 676 * @returns: the status of the remove operation. 677 * 678 * Remove the phrase item of the token. 679 * 680 */ remove_phrase_item(phrase_token_t token,PhraseItem * & item)681 int remove_phrase_item(phrase_token_t token, PhraseItem * & item){ 682 guint8 index = PHRASE_INDEX_LIBRARY_INDEX(token); 683 SubPhraseIndex * & sub_phrase = m_sub_phrase_indices[index]; 684 if ( !sub_phrase ){ 685 return ERROR_NO_SUB_PHRASE_INDEX; 686 } 687 int result = sub_phrase->remove_phrase_item(token, item); 688 if ( result ) 689 return result; 690 m_total_freq -= item->get_unigram_frequency(); 691 return result; 692 } 693 694 /** 695 * FacadePhraseIndex::prepare_ranges: 696 * @ranges: the ranges to be prepared. 697 * @returns: whether the prepare operation is successful. 698 * 699 * Prepare the ranges. 700 * 701 */ prepare_ranges(PhraseIndexRanges ranges)702 bool prepare_ranges(PhraseIndexRanges ranges) { 703 /* assume memset(ranges, 0, sizeof(ranges)); */ 704 for (size_t i = 0; i < PHRASE_INDEX_LIBRARY_COUNT; ++i) { 705 GArray * & range = ranges[i]; 706 assert(NULL == range); 707 708 SubPhraseIndex * sub_phrase = m_sub_phrase_indices[i]; 709 if (sub_phrase) { 710 range = g_array_new(FALSE, FALSE, sizeof(PhraseIndexRange)); 711 } 712 } 713 return true; 714 } 715 716 /** 717 * FacadePhraseIndex::clear_ranges: 718 * @ranges: the ranges to be cleared. 719 * @returns: whether the clear operation is successful. 720 * 721 * Clear the ranges. 722 * 723 */ clear_ranges(PhraseIndexRanges ranges)724 bool clear_ranges(PhraseIndexRanges ranges) { 725 for (size_t i = 0; i < PHRASE_INDEX_LIBRARY_COUNT; ++i) { 726 GArray * range = ranges[i]; 727 if (range) { 728 g_array_set_size(range, 0); 729 } 730 } 731 return true; 732 } 733 734 /** 735 * FacadePhraseIndex::destroy_ranges: 736 * @ranges: the ranges to be destroyed. 737 * @returns: whether the destroy operation is successful. 738 * 739 * Destroy the ranges. 740 * 741 */ destroy_ranges(PhraseIndexRanges ranges)742 bool destroy_ranges(PhraseIndexRanges ranges) { 743 for (size_t i = 0; i < PHRASE_INDEX_LIBRARY_COUNT; ++i) { 744 GArray * & range = ranges[i]; 745 if (range) { 746 g_array_free(range, TRUE); 747 range = NULL; 748 } 749 } 750 return true; 751 } 752 753 /** 754 * FacadePhraseIndex::prepare_tokens: 755 * @tokens: the tokens to be prepared. 756 * @returns: whether the prepare operation is successful. 757 * 758 * Prepare the tokens. 759 * 760 */ prepare_tokens(PhraseTokens tokens)761 bool prepare_tokens(PhraseTokens tokens) { 762 /* assume memset(tokens, 0, sizeof(tokens)); */ 763 for (size_t i = 0; i < PHRASE_INDEX_LIBRARY_COUNT; ++i) { 764 GArray * & token = tokens[i]; 765 assert(NULL == token); 766 767 SubPhraseIndex * sub_phrase = m_sub_phrase_indices[i]; 768 if (sub_phrase) { 769 token = g_array_new(FALSE, FALSE, sizeof(phrase_token_t)); 770 } 771 } 772 return true; 773 } 774 775 /** 776 * FacadePhraseIndex::clear_tokens: 777 * @tokens: the tokens to be cleared. 778 * @return: whether the clear operation is successful. 779 * 780 * Clear the tokens. 781 * 782 */ clear_tokens(PhraseTokens tokens)783 bool clear_tokens(PhraseTokens tokens) { 784 for (size_t i = 0; i < PHRASE_INDEX_LIBRARY_COUNT; ++i) { 785 GArray * token = tokens[i]; 786 if (token) { 787 g_array_set_size(token, 0); 788 } 789 } 790 return true; 791 } 792 793 /** 794 * FacadePhraseIndex::destroy_tokens: 795 * @tokens: the tokens to be destroyed. 796 * @returns: whether the destroy operation is successful. 797 * 798 * Destroy the tokens. 799 * 800 */ destroy_tokens(PhraseTokens tokens)801 bool destroy_tokens(PhraseTokens tokens) { 802 for (size_t i = 0; i < PHRASE_INDEX_LIBRARY_COUNT; ++i) { 803 GArray * & token = tokens[i]; 804 if (token) { 805 g_array_free(token, TRUE); 806 token = NULL; 807 } 808 } 809 return true; 810 } 811 812 /** 813 * FacadePhraseIndex::create_sub_phrase: 814 * @index: the phrase index to be created. 815 * @returns: the result of the create operation. 816 * 817 * Create the sub phrase index. 818 * 819 */ create_sub_phrase(guint8 index)820 int create_sub_phrase(guint8 index) { 821 SubPhraseIndex * & sub_phrase = m_sub_phrase_indices[index]; 822 if (sub_phrase) { 823 return ERROR_ALREADY_EXISTS; 824 } 825 826 sub_phrase = new SubPhraseIndex; 827 828 return ERROR_OK; 829 } 830 }; 831 832 PhraseIndexLogger * mask_out_phrase_index_logger 833 (PhraseIndexLogger * oldlogger, phrase_token_t mask, phrase_token_t value); 834 835 }; 836 837 #endif 838