bool CoinQBlockTreeSqlite3::insertHeader(const Coin::CoinBlockHeader& header) { if (!db.isOpen()) { throw std::runtime_error("Database is not open."); } std::stringstream sql; SQLite3Stmt stmt; sql << "SELECT `height`, `chain_work`, `version`, `timestamp`, `bits`" << " FROM `block_headers` WHERE `hash` = '" << header.prevBlockHash.getHex() << "'"; stmt.prepare(db, sql.str()); if (stmt.step() != SQLITE_ROW) { throw std::runtime_error("Parent not found."); } // TODO: validate header ChainHeader chainHeader(header); chainHeader.height = stmt.getInt(0) + 1; chainHeader.chainWork.setDec((char*)stmt.getText(1)); chainHeader.chainWork += chainHeader.getWork(); std::string chainHeaderHashStr = chainHeader.getHashLittleEndian().getHex(); SQLite3Tx sqliteTx(db, SQLite3Tx::Type::IMMEDIATE); stmt.finalize(); sql.str(""); sql << "INSERT INTO `block_headers` (`hash`, `in_best_chain`, `height`, `chain_work`, `version`, `prev_block_hash`, `merkle_root`, `timestamp`, `bits`, `nonce`)" << " VALUES ('" << chainHeaderHashStr << "',0," << chainHeader.height << ",'" << chainHeader.chainWork.getDec() << "'," << chainHeader.version << ",'" << chainHeader.prevBlockHash.getHex() << "','" << chainHeader.merkleRoot.getHex() << "'," << chainHeader.timestamp << "," << chainHeader.bits << "," << chainHeader.nonce << ")"; stmt.prepare(db, sql.str()); try { stmt.step(); notifyInsert(chainHeader); } catch (const SQLite3Exception& e) { if (e.code() == SQLITE_CONSTRAINT) return false; throw e; } if (chainHeader.chainWork > getTotalWork()) { setBestChain(chainHeaderHashStr); } sqliteTx.commit(); return true; }
U_NAMESPACE_BEGIN void MorphTableHeader::process(const LETableReference &base, LEGlyphStorage &glyphStorage, LEErrorCode &success) const { le_uint32 chainCount = SWAPL(this->nChains); LEReferenceTo<ChainHeader> chainHeader(base, success, chains); // moving header LEReferenceToArrayOf<ChainHeader> chainHeaderArray(base, success, chains, chainCount); le_uint32 chain; for (chain = 0; LE_SUCCESS(success) && (chain < chainCount); chain += 1) { if (chain > 0) { le_uint32 chainLength = SWAPL(chainHeader->chainLength); if (chainLength & 0x03) { // incorrect alignment for 32 bit tables success = LE_MEMORY_ALLOCATION_ERROR; // as good a choice as any return; } chainHeader.addOffset(chainLength, success); } FeatureFlags defaultFlags = SWAPL(chainHeader->defaultFlags); le_int16 nFeatureEntries = SWAPW(chainHeader->nFeatureEntries); le_int16 nSubtables = SWAPW(chainHeader->nSubtables); LEReferenceTo<MorphSubtableHeader> subtableHeader = LEReferenceTo<MorphSubtableHeader>(chainHeader,success, &(chainHeader->featureTable[nFeatureEntries])); le_int16 subtable; for (subtable = 0; LE_SUCCESS(success) && (subtable < nSubtables); subtable += 1) { if (subtable > 0) { le_int16 length = SWAPW(subtableHeader->length); if (length & 0x03) { // incorrect alignment for 32 bit tables success = LE_MEMORY_ALLOCATION_ERROR; // as good a choice as any return; } subtableHeader.addOffset(length, success); } SubtableCoverage coverage = SWAPW(subtableHeader->coverage); FeatureFlags subtableFeatures = SWAPL(subtableHeader->subtableFeatures); // should check coverage more carefully... if ((coverage & scfVertical) == 0 && (subtableFeatures & defaultFlags) != 0 && LE_SUCCESS(success)) { subtableHeader->process(subtableHeader, glyphStorage, success); } } } }
U_NAMESPACE_BEGIN void MorphTableHeader2::process(const LEReferenceTo<MorphTableHeader2> &base, LEGlyphStorage &glyphStorage, le_int32 typoFlags, LEErrorCode &success) const { if(LE_FAILURE(success)) return; le_uint32 chainCount = SWAPL(this->nChains); LEReferenceTo<ChainHeader2> chainHeader(base, success, &chains[0]); /* chainHeader and subtableHeader are implemented as a moving pointer rather than an array dereference * to (slightly) reduce code churn. However, must be careful to preincrement them the 2nd time through. * We don't want to increment them at the end of the loop, as that would attempt to dereference * out of range memory. */ le_uint32 chain; for (chain = 0; LE_SUCCESS(success) && (chain < chainCount); chain++) { if (chain>0) { le_uint32 chainLength = SWAPL(chainHeader->chainLength); chainHeader.addOffset(chainLength, success); // Don't increment the first time } FeatureFlags flag = SWAPL(chainHeader->defaultFlags); le_uint32 nFeatureEntries = SWAPL(chainHeader->nFeatureEntries); le_uint32 nSubtables = SWAPL(chainHeader->nSubtables); LEReferenceTo<MorphSubtableHeader2> subtableHeader(chainHeader, success, (const MorphSubtableHeader2 *)&chainHeader->featureTable[nFeatureEntries]); le_uint32 subtable; if(LE_FAILURE(success)) break; // malformed table if (typoFlags != 0) { le_uint32 featureEntry; LEReferenceToArrayOf<FeatureTableEntry> featureTableRef(chainHeader, success, &chainHeader->featureTable[0], nFeatureEntries); if(LE_FAILURE(success)) break; // Feature subtables for (featureEntry = 0; featureEntry < nFeatureEntries; featureEntry++) { const FeatureTableEntry &featureTableEntry = featureTableRef(featureEntry, success); le_int16 featureType = SWAPW(featureTableEntry.featureType); le_int16 featureSetting = SWAPW(featureTableEntry.featureSetting); le_uint32 enableFlags = SWAPL(featureTableEntry.enableFlags); le_uint32 disableFlags = SWAPL(featureTableEntry.disableFlags); switch (featureType) { case ligaturesType: if ((typoFlags & LE_Ligatures_FEATURE_ENUM ) && (featureSetting ^ 0x1)){ flag &= disableFlags; flag |= enableFlags; } else { if (((typoFlags & LE_RLIG_FEATURE_FLAG) && featureSetting == requiredLigaturesOnSelector) || ((typoFlags & LE_CLIG_FEATURE_FLAG) && featureSetting == contextualLigaturesOnSelector) || ((typoFlags & LE_HLIG_FEATURE_FLAG) && featureSetting == historicalLigaturesOnSelector) || ((typoFlags & LE_LIGA_FEATURE_FLAG) && featureSetting == commonLigaturesOnSelector)) { flag &= disableFlags; flag |= enableFlags; } } break; case letterCaseType: if ((typoFlags & LE_SMCP_FEATURE_FLAG) && featureSetting == smallCapsSelector) { flag &= disableFlags; flag |= enableFlags; } break; case verticalSubstitutionType: break; case linguisticRearrangementType: break; case numberSpacingType: break; case smartSwashType: if ((typoFlags & LE_SWSH_FEATURE_FLAG) && (featureSetting ^ 0x1)){ flag &= disableFlags; flag |= enableFlags; } break; case diacriticsType: break; case verticalPositionType: break; case fractionsType: if (((typoFlags & LE_FRAC_FEATURE_FLAG) && featureSetting == diagonalFractionsSelector) || ((typoFlags & LE_AFRC_FEATURE_FLAG) && featureSetting == verticalFractionsSelector)) { flag &= disableFlags; flag |= enableFlags; } else { flag &= disableFlags; } break; case typographicExtrasType: if ((typoFlags & LE_ZERO_FEATURE_FLAG) && featureSetting == slashedZeroOnSelector) { flag &= disableFlags; flag |= enableFlags; } break; case mathematicalExtrasType: break; case ornamentSetsType: break; case characterAlternativesType: break; case designComplexityType: if (((typoFlags & LE_SS01_FEATURE_FLAG) && featureSetting == designLevel1Selector) || ((typoFlags & LE_SS02_FEATURE_FLAG) && featureSetting == designLevel2Selector) || ((typoFlags & LE_SS03_FEATURE_FLAG) && featureSetting == designLevel3Selector) || ((typoFlags & LE_SS04_FEATURE_FLAG) && featureSetting == designLevel4Selector) || ((typoFlags & LE_SS05_FEATURE_FLAG) && featureSetting == designLevel5Selector) || ((typoFlags & LE_SS06_FEATURE_FLAG) && featureSetting == designLevel6Selector) || ((typoFlags & LE_SS07_FEATURE_FLAG) && featureSetting == designLevel7Selector)) { flag &= disableFlags; flag |= enableFlags; } break; case styleOptionsType: break; case characterShapeType: break; case numberCaseType: break; case textSpacingType: break; case transliterationType: break; case annotationType: if ((typoFlags & LE_NALT_FEATURE_FLAG) && featureSetting == circleAnnotationSelector) { flag &= disableFlags; flag |= enableFlags; } break; case kanaSpacingType: break; case ideographicSpacingType: break; case rubyKanaType: if ((typoFlags & LE_RUBY_FEATURE_FLAG) && featureSetting == rubyKanaOnSelector) { flag &= disableFlags; flag |= enableFlags; } break; case cjkRomanSpacingType: break; default: break; } } } for (subtable = 0; LE_SUCCESS(success) && subtable < nSubtables; subtable++) { if(subtable>0) { le_uint32 length = SWAPL(subtableHeader->length); subtableHeader.addOffset(length, success); // Don't addOffset for the last entry. } le_uint32 coverage = SWAPL(subtableHeader->coverage); FeatureFlags subtableFeatures = SWAPL(subtableHeader->subtableFeatures); // should check coverage more carefully... if (((coverage & scfIgnoreVt2) || !(coverage & scfVertical2)) && (subtableFeatures & flag) != 0) { subtableHeader->process(subtableHeader, glyphStorage, success); } } } }