PyType PyType::lookupType(const std::string &typeNameIn, ULONG64 module) { if (debuggingTypeEnabled()) DebugPrint() << "lookup type '" << typeNameIn << "'"; std::string typeName = typeNameIn; trimBack(typeName); trimFront(typeName); if (isPointerType(typeName) || isArrayType(typeName)) return PyType(0, 0, typeName); if (typeName.find("enum ") == 0) typeName.erase(0, 5); if (endsWith(typeName, " const")) typeName.erase(typeName.length() - 6); if (typeName == "__int64" || typeName == "unsigned __int64") typeName.erase(typeName.find("__"), 2); const static std::regex typeNameRE("^[a-zA-Z_][a-zA-Z0-9_]*!?[a-zA-Z0-9_<>:, \\*\\&\\[\\]]*$"); if (!std::regex_match(typeName, typeNameRE)) return PyType(); CIDebugSymbols *symbols = ExtensionCommandContext::instance()->symbols(); ULONG typeId; HRESULT result = S_FALSE; if (module != 0 && !isIntegralType(typeName) && !isFloatType(typeName)) result = symbols->GetTypeId(module, typeName.c_str(), &typeId); if (FAILED(result) || result == S_FALSE) result = symbols->GetSymbolTypeId(typeName.c_str(), &typeId, &module); if (FAILED(result)) return createUnresolvedType(typeName); return PyType(module, typeId, typeName); }
std::string PyType::name(bool withModule) const { if (m_name.empty()) { auto symbols = ExtensionCommandContext::instance()->symbols(); ULONG size = 0; symbols->GetTypeName(m_module, m_typeId, NULL, 0, &size); if (size == 0) return std::string(); std::string typeName(size - 1, '\0'); if (FAILED(symbols->GetTypeName(m_module, m_typeId, &typeName[0], size, &size))) return std::string(); m_name = typeName; } if (withModule && !isIntegralType(m_name) && !isFloatType(m_name)) { std::string completeName = module(); if (!completeName.empty()) completeName.append("!"); completeName.append(m_name); return completeName; } return m_name; }
int PyType::code() const { if (!m_resolved) return TypeCodeUnresolvable; if (m_tag < 0) { // try to parse typeName const std::string &typeName = name(); if (typeName.empty()) return TypeCodeUnresolvable; if (isPointerType(typeName)) return TypeCodePointer; if (isArrayType(typeName)) return TypeCodeArray; if (typeName.find("<function>") == 0) return TypeCodeFunction; if (isIntegralType(typeName)) return TypeCodeIntegral; if (isFloatType(typeName)) return TypeCodeFloat; IDebugSymbolGroup2 *sg = 0; if (FAILED(ExtensionCommandContext::instance()->symbols()->CreateSymbolGroup2(&sg))) return TypeCodeStruct; if (knownType(name(), 0) != KT_Unknown) return TypeCodeStruct; const std::string helperValueName = SymbolGroupValue::pointedToSymbolName(0, name(true)); ULONG index = DEBUG_ANY_ID; if (SUCCEEDED(sg->AddSymbol(helperValueName.c_str(), &index))) m_tag = PyValue(index, sg).tag(); sg->Release(); } switch (m_tag) { case SymTagUDT: return TypeCodeStruct; case SymTagEnum: return TypeCodeEnum; case SymTagTypedef: return TypeCodeTypedef; case SymTagFunctionType: return TypeCodeFunction; case SymTagPointerType: return TypeCodePointer; case SymTagArrayType: return TypeCodeArray; case SymTagBaseType: return isIntegralType(name()) ? TypeCodeIntegral : TypeCodeFloat; default: break; } return TypeCodeStruct; }
void Type::generateHeader(std::ostream& ostr, unsigned long _indent) const { // if(name_.isEmpty()) // throw QString("No class name specified."); unsigned long indent = _indent; if (!isExtern()) { // debug ostream operator if (parent_.isEmpty()) { ostr << spaces.left(indent) << "struct " << name_ << "Parameters;" << std::endl << spaces.left(indent) << "std::ostream&" << std::endl << spaces.left(indent) << "operator << (std::ostream& ostr, const " << name_ << "Parameters& rhs);" << std::endl << std::endl; } ostr << spaces.left(indent) << "class " << name_ << "Parameters"; if (!parent_.isEmpty()) ostr << " : public " << parent_; ostr << std::endl << spaces.left(indent) << "{" << std::endl; indent += STEP; if (!parent_.isEmpty()) ostr << spaces.left(indent) << "typedef " << parent_ << " Super;" << std::endl << std::endl; ostr << spaces.left(indent - STEP) << "public: " << std::endl; // data members ParameterVector::const_iterator j; for (j = parameter_.begin(); j != parameter_.end(); ++j) ostr << spaces.left(indent) << ((j->type_ != "angle")? j->type_ : QString("double")) << " " << j->name_ << ";" << std::endl; if (parameter_.size() != 0) ostr << std::endl; // const static data members for (j = staticConstParameter_.begin(); j != staticConstParameter_.end(); ++j) { ostr << spaces.left(indent) << "static const " << ((j->type_ != "angle")? j->type_ : QString("double")) << " " << j->name_; if (isIntegralType(j->type_)) { ostr << " = " << j->fullDefault_; } ostr << ";" << std::endl; } if (staticConstParameter_.size() != 0) ostr << std::endl; // static data members QStringPairVector::const_iterator k; for (k = staticData_.begin(); k != staticData_.end(); ++k) ostr << spaces.left(indent) << "static " << k->first << " " << k->second << ";" << std::endl; if (staticData_.size() != 0) ostr << std::endl; // constructor ostr << spaces.left(indent) << name_ << "Parameters();" << std::endl; // destructor if (parent_.isEmpty()) ostr << spaces.left(indent) << "virtual ~"<< name_ << "Parameters();" << std::endl; // parsing operator ostr << std::endl; if (parameter_.size() > 0 || parent_.isEmpty()) { ostr << spaces.left(indent) << "virtual void operator <<= (const QDomNode&);" << std::endl; ostr << spaces.left(indent) << "virtual QDomElement operator >>= (QDomNode&) const;" << std::endl; } // debug output operator if (parameter_.size() > 0 || parent_.isEmpty()) { ostr << spaces.left(indent - STEP) << "protected:" << std::endl << spaces.left(indent) << "virtual void printToStream(std::ostream&) const;" << std::endl; } if (parent_.isEmpty()) ostr << spaces.left(indent) << "friend" << std::endl << spaces.left(indent) << "std::ostream&" << std::endl << spaces.left(indent) << "operator << (std::ostream& ostr, const " << name_ << "Parameters& rhs);" << std::endl; } else { // if this is a externally defined class, // use global operators for parsing ostr << spaces.left(indent) << "void operator <<= (" << name_ << "&, const QDomNode&);" << std::endl; ostr << spaces.left(indent) << "QDomElement operator >>= (const " << name_ << "&, QDomNode&);" << std::endl; } while (indent > _indent) { indent -= STEP; ostr << spaces.left(indent) << "};" << std::endl; } }
void Type::generateSource(std::ostream& ostr, unsigned long _indent) const { // if(name_.isEmpty()) // throw QString("No class name specified."); unsigned long indent = _indent; if (!isExtern()) { QStringVector::const_iterator i; ParameterVector::const_iterator j; // debug ostream operator if (parent_.isEmpty()) { ostr << spaces.left(indent) << "std::ostream&" << std::endl << spaces.left(indent) << "operator << (std::ostream& ostr, const " << name_ << "Parameters& rhs)" << std::endl << spaces.left(indent) << "{" << std::endl; indent += STEP; ostr << spaces.left(indent) << "rhs.printToStream(ostr);" << std::endl << spaces.left(indent) << "return ostr;" << std::endl; indent -= STEP; ostr << spaces.left(indent) << "}" << std::endl << std::endl; } // static data members QStringPairVector::const_iterator k; for (k = staticData_.begin(); k != staticData_.end(); ++k) ostr << spaces.left(indent) << k->first << " " << name_ << "Parameters::" << k->second << ";" << std::endl; if (staticData_.size() != 0) ostr << std::endl; // const static data members for (j = staticConstParameter_.begin(); j != staticConstParameter_.end(); ++j) { ostr << spaces.left(indent) << "const " << ((j->type_ != "angle")? j->type_ : QString("double")) << " " << name_ << "Parameters::" << j->name_; if (!isIntegralType(j->type_)) { ostr << "(" << j->fullDefault_ << ")"; } ostr << ";" << std::endl; } if (staticConstParameter_.size() != 0) ostr << std::endl; // constructor ostr << spaces.left(indent) << name_ << "Parameters::" << name_ << "Parameters()"; if (parameter_.size() > 0) { ostr << " :"; indent += 2; for (j = parameter_.begin(); j != parameter_.end(); ++j) { if (j != parameter_.begin()) ostr << ","; ostr << std::endl << spaces.left(indent) << j->name_ << "(" << j->fullDefault_ <<")"; } indent -= 2; } ostr << std::endl << spaces.left(indent) << "{" << std::endl; indent += STEP; for (i = ctor_.begin(); i != ctor_.end(); ++i) ostr << spaces.left(indent) << *i << std::endl; indent -= STEP; ostr << spaces.left(indent) << "}" << std::endl << std::endl; // destructor if (parent_.isEmpty()) ostr << spaces.left(indent) << name_ << "Parameters::~" << name_ << "Parameters()" << std::endl << spaces.left(indent) << "{}" << std::endl << std::endl; if (parameter_.size() > 0 || parent_.isEmpty()) { // operator <<= ostr << spaces.left(indent) << "void" << std::endl << spaces.left(indent) << name_ << "Parameters::operator <<= (const QDomNode&"; if (parameter_.size() > 0 || !parent_.isEmpty()) ostr <<" _node"; ostr << ")" << std::endl; generateQDomOutOperator(ostr, "this->", indent); // operator >>= ostr << spaces.left(indent) << "QDomElement" << std::endl << spaces.left(indent) << name_ << "Parameters::operator >>= (QDomNode& _node) const" << std::endl; generateQDomInOperator(ostr, "this->", indent); // stream output ostr << std::endl << spaces.left(indent) << "void" << std::endl << spaces.left(indent) << name_ <<"Parameters::printToStream(std::ostream&"; if (parameter_.size() > 0 || !parent_.isEmpty()) ostr << " ostr"; ostr << ") const" << std::endl << spaces.left(indent) << "{" << std::endl; indent += STEP; if (!parent_.isEmpty()) ostr << spaces.left(indent) << "Super::printToStream(ostr);" << std::endl << std::endl; if (parameter_.size() > 0) { ostr << spaces.left(indent) << "ostr << "; indent += 5; for (j = parameter_.begin(); j != parameter_.end(); ++j) { if (j != parameter_.begin()) ostr << std::endl << spaces.left(indent) << "<< "; if (!j->description_.isEmpty()) ostr << "\"" << j->description_; else { QString name(j->name_); name[0] = name[0].upper(); ostr << "\"" << name; } ostr << ": \" << "; if (j->type_ != "angle") ostr << j->name_; else ostr << "Miro::rad2Deg(" << j->name_ << ")" << std::endl; if (!j->measure_.isEmpty()) ostr << " << \"" << j->measure_ << "\""; ostr << " << std::endl"; } ostr << ";" << std::endl; indent -= 5; } indent -= STEP; ostr << spaces.left(indent) << "}" << std::endl; } } else { // operator <<= ostr << spaces.left(indent) << "void" << std::endl << spaces.left(indent) << "operator<<= (" << name_ <<"& _lhs, const QDomNode& _node)" << std::endl; generateQDomOutOperator(ostr, "_lhs.", indent); // operator >>= ostr << spaces.left(indent) << "QDomElement" << std::endl << spaces.left(indent) << "operator>>= (const " << name_ <<"& _lhs, QDomNode& _node)" << std::endl; generateQDomInOperator(ostr, "_lhs.", indent); } }
TableIndex *TableIndexFactory::getInstance(const TableIndexScheme &scheme) { const TupleSchema *tupleSchema = scheme.tupleSchema; assert(tupleSchema); bool isIntsOnly = true; bool isInlinesOrColumnsOnly = true; std::vector<ValueType> keyColumnTypes; std::vector<int32_t> keyColumnLengths; size_t valueCount = 0; size_t exprCount = scheme.indexedExpressions.size(); if (exprCount != 0) { valueCount = exprCount; // TODO: This is where we could gain some extra runtime and space efficiency by // somehow marking which indexed expressions happen to be non-inlined column expressions. // This case is significant because it presents an opportunity for the GenericPersistentKey // index keys to avoid a persistent allocation and copy of an already persistent value. // This could be implemented as a bool attribute of TupleSchema::ColumnInfo that is only // set to true in this special case. It would universally disable deep copying of that // particular "tuple column"'s referenced object. for (size_t ii = 0; ii < valueCount; ++ii) { ValueType exprType = scheme.indexedExpressions[ii]->getValueType(); if ( ! isIntegralType(exprType)) { isIntsOnly = false; } uint32_t declaredLength; if (exprType == VALUE_TYPE_VARCHAR || exprType == VALUE_TYPE_VARBINARY) { // Setting the column length to TUPLE_SCHEMA_COLUMN_MAX_VALUE_LENGTH constrains the // maximum length of expression values that can be indexed with the same limit // that gets applied to column values. // In theory, indexed expression values could have an independent limit // up to any length that can be allocated via ThreadLocalPool. // Currently, all of these cases are constrained with the same limit, // which is also the default/maximum size for variable columns defined in schema, // as controlled in java by VoltType.MAX_VALUE_LENGTH. // It's not clear whether scheme.indexedExpressions[ii]->getValueSize() // can or should be called for a more useful answer. // There's probably little to gain since expressions usually do not contain enough information // to reliably determine that the result value is always small enough to "inline". declaredLength = TupleSchema::COLUMN_MAX_VALUE_LENGTH; isInlinesOrColumnsOnly = false; } else { declaredLength = NValue::getTupleStorageSize(exprType); } keyColumnTypes.push_back(exprType); keyColumnLengths.push_back(declaredLength); } } else { valueCount = scheme.columnIndices.size(); for (size_t ii = 0; ii < valueCount; ++ii) { ValueType exprType = tupleSchema->columnType(scheme.columnIndices[ii]); if ( ! isIntegralType(exprType)) { isIntsOnly = false; } keyColumnTypes.push_back(exprType); keyColumnLengths.push_back(tupleSchema->columnLength(scheme.columnIndices[ii])); } } std::vector<bool> keyColumnAllowNull(valueCount, true); TupleSchema *keySchema = TupleSchema::createTupleSchema(keyColumnTypes, keyColumnLengths, keyColumnAllowNull, true); assert(keySchema); VOLT_TRACE("Creating index for '%s' with key schema '%s'", scheme.name.c_str(), keySchema->debug().c_str()); TableIndexPicker picker(keySchema, isIntsOnly, isInlinesOrColumnsOnly, scheme); TableIndex *retval = picker.getInstance(); return retval; }