bool Ver4BigramListPolicy::removeEntry(const int terminalId, const int targetTerminalId) { const int bigramListPos = mBigramDictContent->getBigramListHeadPos(terminalId); if (bigramListPos == NOT_A_DICT_POS) { // Bigram list doesn't exist. return false; } const int entryPosToUpdate = getEntryPosToUpdate(targetTerminalId, bigramListPos, nullptr /* outTailEntryPos */); if (entryPosToUpdate == NOT_A_DICT_POS) { // Bigram entry doesn't exist. return false; } const BigramEntry bigramEntry = mBigramDictContent->getBigramEntry(entryPosToUpdate); if (targetTerminalId != bigramEntry.getTargetTerminalId()) { // Bigram entry doesn't exist. return false; } // Remove bigram entry by marking it as invalid entry and overwriting the original entry. const BigramEntry updatedBigramEntry = bigramEntry.getInvalidatedEntry(); return mBigramDictContent->writeBigramEntry(&updatedBigramEntry, entryPosToUpdate); }
bool Ver4BigramListPolicy::addNewEntry(const int terminalId, const int newTargetTerminalId, const BigramProperty *const bigramProperty, bool *const outAddedNewEntry) { // 1. The word has no bigrams yet. // 2. The word has bigrams, and there is the target in the list. // 3. The word has bigrams, and there is an invalid entry that can be reclaimed. // 4. The word has bigrams. We have to append new bigram entry to the list. // 5. Same as 4, but the list is the last entry of the content file. if (outAddedNewEntry) { *outAddedNewEntry = false; } const int bigramListPos = mBigramDictContent->getBigramListHeadPos(terminalId); if (bigramListPos == NOT_A_DICT_POS) { // Case 1. PtNode that doesn't have a bigram list. // Create new bigram list. if (!mBigramDictContent->createNewBigramList(terminalId)) { return false; } const BigramEntry newBigramEntry(false /* hasNext */, NOT_A_PROBABILITY, newTargetTerminalId); const BigramEntry bigramEntryToWrite = createUpdatedBigramEntryFrom(&newBigramEntry, bigramProperty); // Write an entry. int writingPos = mBigramDictContent->getBigramListHeadPos(terminalId); if (!mBigramDictContent->writeBigramEntryAndAdvancePosition(&bigramEntryToWrite, &writingPos)) { AKLOGE("Cannot write bigram entry. pos: %d.", writingPos); return false; } if (!mBigramDictContent->writeTerminator(writingPos)) { AKLOGE("Cannot write bigram list terminator. pos: %d.", writingPos); return false; } if (outAddedNewEntry) { *outAddedNewEntry = true; } return true; } int tailEntryPos = NOT_A_DICT_POS; const int entryPosToUpdate = getEntryPosToUpdate(newTargetTerminalId, bigramListPos, &tailEntryPos); if (entryPosToUpdate == NOT_A_DICT_POS) { // Case 4, 5. Add new entry to the bigram list. const int contentTailPos = mBigramDictContent->getContentTailPos(); // If the tail entry is at the tail of content buffer, the new entry can be written without // link (Case 5). const bool canAppendEntry = contentTailPos == tailEntryPos + mBigramDictContent->getBigramEntrySize(); const int newEntryPos = canAppendEntry ? tailEntryPos : contentTailPos; int writingPos = newEntryPos; // Write new entry at the tail position of the bigram content. const BigramEntry newBigramEntry(false /* hasNext */, NOT_A_PROBABILITY, newTargetTerminalId); const BigramEntry bigramEntryToWrite = createUpdatedBigramEntryFrom( &newBigramEntry, bigramProperty); if (!mBigramDictContent->writeBigramEntryAndAdvancePosition(&bigramEntryToWrite, &writingPos)) { AKLOGE("Cannot write bigram entry. pos: %d.", writingPos); return false; } if (!mBigramDictContent->writeTerminator(writingPos)) { AKLOGE("Cannot write bigram list terminator. pos: %d.", writingPos); return false; } if (!canAppendEntry) { // Update link of the current tail entry. if (!mBigramDictContent->writeLink(newEntryPos, tailEntryPos)) { AKLOGE("Cannot update bigram entry link. pos: %d, linked entry pos: %d.", tailEntryPos, newEntryPos); return false; } } if (outAddedNewEntry) { *outAddedNewEntry = true; } return true; } // Case 2. Overwrite the existing entry. Case 3. Reclaim and reuse the existing invalid entry. const BigramEntry originalBigramEntry = mBigramDictContent->getBigramEntry(entryPosToUpdate); if (!originalBigramEntry.isValid()) { // Case 3. Reuse the existing invalid entry. outAddedNewEntry is false when an existing // entry is updated. if (outAddedNewEntry) { *outAddedNewEntry = true; } } const BigramEntry updatedBigramEntry = originalBigramEntry.updateTargetTerminalIdAndGetEntry(newTargetTerminalId); const BigramEntry bigramEntryToWrite = createUpdatedBigramEntryFrom( &updatedBigramEntry, bigramProperty); return mBigramDictContent->writeBigramEntry(&bigramEntryToWrite, entryPosToUpdate); }
bool Ver4BigramListPolicy::addNewEntry(const int terminalId, const int newTargetTerminalId, const BigramProperty *const bigramProperty, bool *const outAddedNewEntry) { // 1. The word has no bigrams yet. // 2. The word has bigrams, and there is the target in the list. // 3. The word has bigrams, and there is an invalid entry that can be reclaimed. // 4. The word has bigrams. We have to append new bigram entry to the list. // 5. Same as 4, but the list is the last entry of the content file. if (outAddedNewEntry) { *outAddedNewEntry = false; } const int bigramListPos = mBigramDictContent->getBigramListHeadPos(terminalId); if (bigramListPos == NOT_A_DICT_POS) { // Case 1. PtNode that doesn't have a bigram list. // Create new bigram list. if (!mBigramDictContent->createNewBigramList(terminalId)) { return false; } const BigramEntry newBigramEntry(false /* hasNext */, NOT_A_PROBABILITY, newTargetTerminalId); const BigramEntry bigramEntryToWrite = createUpdatedBigramEntryFrom(&newBigramEntry, bigramProperty); // Write an entry. const int writingPos = mBigramDictContent->getBigramListHeadPos(terminalId); if (!mBigramDictContent->writeBigramEntry(&bigramEntryToWrite, writingPos)) { return false; } if (outAddedNewEntry) { *outAddedNewEntry = true; } return true; } int tailEntryPos = NOT_A_DICT_POS; const int entryPosToUpdate = getEntryPosToUpdate(newTargetTerminalId, bigramListPos, &tailEntryPos); if (tailEntryPos != NOT_A_DICT_POS || entryPosToUpdate == NOT_A_DICT_POS) { // Case 4, 5. // Add new entry to the bigram list. if (tailEntryPos == NOT_A_DICT_POS) { // Case 4. Create new bigram list. if (!mBigramDictContent->createNewBigramList(terminalId)) { return false; } const int destPos = mBigramDictContent->getBigramListHeadPos(terminalId); // Copy existing bigram list. if (!mBigramDictContent->copyBigramList(bigramListPos, destPos, &tailEntryPos)) { return false; } } // Write new entry at the tail position of the bigram content. const BigramEntry newBigramEntry(false /* hasNext */, NOT_A_PROBABILITY, newTargetTerminalId); const BigramEntry bigramEntryToWrite = createUpdatedBigramEntryFrom( &newBigramEntry, bigramProperty); if (!mBigramDictContent->writeBigramEntryAtTail(&bigramEntryToWrite)) { return false; } // Update has next flag of the tail entry. if (!updateHasNextFlag(true /* hasNext */, tailEntryPos)) { return false; } if (outAddedNewEntry) { *outAddedNewEntry = true; } return true; } // Case 2. Overwrite the existing entry. Case 3. Reclaim and reuse the existing invalid entry. const BigramEntry originalBigramEntry = mBigramDictContent->getBigramEntry(entryPosToUpdate); if (!originalBigramEntry.isValid()) { // Case 3. Reuse the existing invalid entry. outAddedNewEntry is false when an existing // entry is updated. if (outAddedNewEntry) { *outAddedNewEntry = true; } } const BigramEntry updatedBigramEntry = originalBigramEntry.updateTargetTerminalIdAndGetEntry(newTargetTerminalId); const BigramEntry bigramEntryToWrite = createUpdatedBigramEntryFrom( &updatedBigramEntry, bigramProperty); return mBigramDictContent->writeBigramEntry(&bigramEntryToWrite, entryPosToUpdate); }