bool same(const Variant& v1, int64_t v2) { auto const cell = v1.asCell(); if (isIntType(cell->m_type)) { return v2 == cell->m_data.num; } return false; }
// gets the ith item of a number list // 0.0 if no such type or out of bounds double Tag::getListItemAsFloat(int32_t i) const { if (isIntType(payload->tagList.type)) return payload->tagList.values->at(i)->tagInt; if (isFloatType(payload->tagList.type)) return payload->tagList.values->at(i)->tagFloat; return 0.0; }
// get value as string // might contain '\n' if list or compound std::string Tag::asString() const { if (isIntType(type)) return std::to_string(payload->tagInt); else if (isFloatType(type)) return std::to_string(payload->tagFloat); else if (type == tagTypeString) return *payload->tagString; else if (isListType(type) || type == tagTypeCompound) { std::string str = std::to_string(getListSize()) + " entries\n{\n"; for (int32_t i = 0; i < getListSize(); i++) { // limit output to 10-15 lines if (isListType(type) && i >= 10 && getListSize() > 15) { str += " ... and " + std::to_string(getListSize()-10) + " more\n"; break; } Tag * tag = getListItemAsTag(i); if (tag != NULL) { std::string content = " " + tag->toString(); // indent content for (size_t pos = content.find_first_of('\n'); pos != std::string::npos; pos = content.find_first_of('\n', pos+1)) { content = content.replace(pos, 1, "\n "); } str += content + "\n"; } else str += " ERROR\n"; } str += "}"; return str; } return ""; }
ArrayData* ArrayCommon::ToKeyset(ArrayData* a, bool) { auto const size = a->size(); if (!size) return staticEmptyKeysetArray(); KeysetInit init{size}; IterateV( a, [&](const TypedValue* v) { if (UNLIKELY(v->m_type == KindOfRef)) { if (v->m_data.pref->isReferenced()) { throwRefInvalidArrayValueException(init.toArray()); } v = v->m_data.pref->tv(); assertx(v->m_type != KindOfRef); } if (LIKELY(isStringType(v->m_type))) { init.add(v->m_data.pstr); } else if (LIKELY(isIntType(v->m_type))) { init.add(v->m_data.num); } else { throwInvalidArrayKeyException(v, init.toArray().get()); } } ); return init.create(); }
//-------------------------------------------------------------- bool ofxMuiNumberData::addValue(float val, ofxMuiRange _bounds, ofxMuiRange _range) { // prepare iterators // start inserting historyLength.push_back(_defaults->dataHistoryLength); deque<float> initQ(_defaults->dataHistoryLength, val); // create a history values.push_back(initQ); // add the queue bounds.push_back(_bounds); ranges.push_back(_range); displayPrecision.push_back(_defaults->displayPrecision); if(isBoolType() || isIntType()) { incrementValues.push_back(_defaults->incrementInt); } else if(isFloatType()) { incrementValues.push_back(_defaults->incrementFloat); } bool boundsChanged = false; bool rangeChanged = false; bool valueChanged = false; checkRange(boundsChanged, rangeChanged, getNumValues()-1); constrainValue(valueChanged, getNumValues()-1); }
const EnumValues* EnumCache::loadEnumValues(const Class* klass, bool recurse) { auto const numConstants = klass->numConstants(); auto values = Array::CreateDArray(); auto names = Array::CreateDArray(); auto const consts = klass->constants(); bool persist = true; for (size_t i = 0; i < numConstants; i++) { if (consts[i].isAbstract() || consts[i].isType()) { continue; } if (consts[i].cls != klass && !recurse) { continue; } Cell value = consts[i].val; // Handle dynamically set constants if (value.m_type == KindOfUninit) { persist = false; value = klass->clsCnsGet(consts[i].name); } assertx(value.m_type != KindOfUninit); if (UNLIKELY(!(isIntType(value.m_type) || tvIsString(&value)))) { // only int and string values allowed for enums. std::string msg; msg += klass->name()->data(); msg += " enum can only contain string and int values"; EnumCache::failLookup(msg); } values.set(StrNR(consts[i].name), cellAsCVarRef(value)); // Manually perform int-like key coercion even if names is a dict for // backwards compatibility. int64_t n; if (tvIsString(&value) && value.m_data.pstr->isStrictlyInteger(n)) { names.set(n, make_tv<KindOfPersistentString>(consts[i].name)); } else { names.set(value, make_tv<KindOfPersistentString>(consts[i].name), true); } } assertx(names.isDictOrDArray()); assertx(values.isDictOrDArray()); // If we saw dynamic constants we cannot cache the enum values across requests // as they may not be the same in every request. return persist ? cachePersistentEnumValues( klass, recurse, std::move(names), std::move(values)) : cacheRequestEnumValues( klass, recurse, std::move(names), std::move(values)); }
Type keysetElemType(SSATmp* arr, SSATmp* idx) { assertx(arr->isA(TKeyset)); assertx(!idx || idx->isA(TInt | TStr)); if (arr->hasConstVal()) { // If both the array and idx are known statically, we can resolve it to the // precise type. if (idx && idx->hasConstVal(TInt)) { auto const idxVal = idx->intVal(); auto const val = SetArray::NvGetInt(arr->keysetVal(), idxVal); return val ? Type(val->m_type) : TBottom; } if (idx && idx->hasConstVal(TStr)) { auto const idxVal = idx->strVal(); auto const val = SetArray::NvGetStr(arr->keysetVal(), idxVal); return val ? Type(val->m_type) : TBottom; } // Otherwise we can constrain the type according to the union of all the // types present in the keyset. Type type{TBottom}; SetArray::Iterate( SetArray::asSet(arr->keysetVal()), [&](const TypedValue* k) { // Ignore values which can't correspond to the key's type if (isIntType(k->m_type)) { if (!idx || idx->type().maybe(TInt)) type |= Type(k->m_type); } else { assertx(isStringType(k->m_type)); if (!idx || idx->type().maybe(TStr)) type |= Type(k->m_type); } } ); // The key is always the value, so, for instance, if there's nothing but // strings in the keyset, we know an int idx can't access a valid value. if (idx) { if (idx->isA(TInt)) type &= TInt; if (idx->isA(TStr)) type &= TStr; } return type; } // Keysets always contain strings or integers. We can further constrain this // if we know the idx type, as the key is always the value. auto type = TStr | TInt; if (idx) { if (idx->isA(TInt)) type &= TInt; if (idx->isA(TStr)) type &= TStr; } if (arr->isA(TPersistentKeyset)) type &= TUncountedInit; return type; }
const EnumCache::EnumValues* EnumCache::loadEnumValues(const Class* klass, bool recurse) { auto const numConstants = klass->numConstants(); size_t foundOnClass = 0; Array values; Array names; auto const consts = klass->constants(); for (size_t i = 0; i < numConstants; i++) { if (consts[i].isAbstract() || consts[i].isType()) { continue; } if (consts[i].m_class == klass) foundOnClass++; else if (!recurse) continue; Cell value = consts[i].m_val; // Handle dynamically set constants if (value.m_type == KindOfUninit) { value = klass->clsCnsGet(consts[i].m_name); } assert(value.m_type != KindOfUninit); if (UNLIKELY(!(isIntType(value.m_type) || (tvIsString(&value) && value.m_data.pstr->isStatic())))) { // only int and string values allowed for enums. Moreover the strings // must be static std::string msg; msg += klass->name()->data(); msg += " enum can only contain static string and int values"; EnumCache::failLookup(msg); } values.set(StrNR(consts[i].m_name), cellAsCVarRef(value)); names.set(cellAsCVarRef(value), VarNR(consts[i].m_name)); } if (UNLIKELY(foundOnClass == 0)) { std::string msg; msg += klass->name()->data(); msg += " enum must contain values"; EnumCache::failLookup(msg); } { std::unique_ptr<EnumCache::EnumValues> enums(new EnumCache::EnumValues()); enums->values = ArrayData::GetScalarArray(values.get()); enums->names = ArrayData::GetScalarArray(names.get()); intptr_t key = getKey(klass, recurse); EnumValuesMap::accessor acc; if (!m_enumValuesMap.insert(acc, key)) { return acc->second; } // add to the map the newly created values acc->second = enums.release(); return acc->second; } }
const EnumValues* EnumCache::loadEnumValues(const Class* klass, bool recurse) { auto const numConstants = klass->numConstants(); auto values = Array::Create(); auto names = Array::Create(); auto const consts = klass->constants(); bool persist = true; for (size_t i = 0; i < numConstants; i++) { if (consts[i].isAbstract() || consts[i].isType()) { continue; } if (consts[i].cls != klass && !recurse) { continue; } Cell value = consts[i].val; // Handle dynamically set constants if (value.m_type == KindOfUninit) { persist = false; value = klass->clsCnsGet(consts[i].name); } assert(value.m_type != KindOfUninit); if (UNLIKELY(!(isIntType(value.m_type) || (tvIsString(&value) && value.m_data.pstr->isStatic())))) { // only int and string values allowed for enums. Moreover the strings // must be static std::string msg; msg += klass->name()->data(); msg += " enum can only contain static string and int values"; EnumCache::failLookup(msg); } values.set(StrNR(consts[i].name), cellAsCVarRef(value)); names.set(value, make_tv<KindOfPersistentString>(consts[i].name)); } // If we saw dynamic constants we cannot cache the enum values across requests // as they may not be the same in every request. return persist ? cachePersistentEnumValues( klass, recurse, std::move(names), std::move(values)) : cacheRequestEnumValues( klass, recurse, std::move(names), std::move(values)); }
// gets the ith item of a list as string // "" if out of bounds // may contain '\n' if list or compound std::string Tag::getListItemAsString(int32_t i) const { if (isIntType(payload->tagList.type)) return std::to_string(payload->tagList.values->at(i)->tagInt); if (isFloatType(payload->tagList.type)) return std::to_string(payload->tagList.values->at(i)->tagFloat); if (payload->tagList.type == tagTypeString) return *payload->tagList.values->at(i)->tagString; // no primitive type, use Tag::asString() Tag * tag = getListItemAsTag(i); if (tag) { std::string str = tag->asString(); delete tag; return str; } return ""; }
bool TypeConstraint::checkTypeAliasNonObj(const TypedValue* tv) const { assert(tv->m_type != KindOfObject); assert(isObject()); auto p = getTypeAliasOrClassWithAutoload(m_namedEntity, m_typeName); auto td = p.first; auto c = p.second; // Common case is that we actually find the alias: if (td) { if (td->nullable && tv->m_type == KindOfNull) return true; auto result = annotCompat(tv->m_type, td->type, td->klass ? td->klass->name() : nullptr); switch (result) { case AnnotAction::Pass: return true; case AnnotAction::Fail: return false; case AnnotAction::CallableCheck: return is_callable(tvAsCVarRef(tv)); case AnnotAction::DictCheck: return tv->m_data.parr->isDict(); case AnnotAction::VecCheck: return tv->m_data.parr->isVecArray(); case AnnotAction::ObjectCheck: break; } assert(result == AnnotAction::ObjectCheck); assert(td->type == AnnotType::Object); // Fall through to the check below, since this could be a type // alias to an enum type c = td->klass; } // Otherwise, this isn't a proper type alias, but it *might* be a // first-class enum. Check if the type is an enum and check the // constraint if it is. We only need to do this when the underlying // type is not an object, since only int and string can be enums. if (c && isEnum(c)) { auto dt = c->enumBaseTy(); // For an enum, if the underlying type is mixed, we still require // it is either an int or a string! if (dt) { return equivDataTypes(*dt, tv->m_type); } else { return isIntType(tv->m_type) || isStringType(tv->m_type); } } return false; }
Variant ArrayUtil::CountValues(const Array& input) { Array ret = Array::Create(); for (ArrayIter iter(input); iter; ++iter) { auto const inner = iter.secondRval().unboxed(); if (isIntType(inner.type()) || isStringType(inner.type())) { if (!ret.exists(inner.tv())) { ret.set(inner.tv(), make_tv<KindOfInt64>(1)); } else { ret.set(inner.tv(), make_tv<KindOfInt64>(ret[inner.tv()].toInt64() + 1)); } } else { raise_warning("Can only count STRING and INTEGER values!"); } } return ret; }
//-------------------------------------------------------------- bool ofxMuiNumberData::insertValue(int index, float val, ofxMuiRange _bounds, ofxMuiRange _range) { if(isValidInsertionIndex(index)) { // prepare iterators valuesIter = values.begin() + index; historyLengthIter = historyLength.begin() + index; boundsIter = bounds.begin() + index; rangesIter = ranges.begin() + index; displayPrecisionIter = displayPrecision.begin() + index; incrementValuesIter = incrementValues.begin() + index; // start inserting historyLength.insert(historyLengthIter, _defaults->dataHistoryLength); deque<float> initQ(_defaults->dataHistoryLength, val); // create a history values.push_back(initQ); // add the queue values.insert(valuesIter, initQ); bounds.insert(boundsIter, _bounds); ranges.insert(rangesIter, _range); // if it's global, take it from the other displayPrecision.insert(displayPrecisionIter, _defaults->displayPrecision); if(isBoolType() || isIntType()) { incrementValues.insert(incrementValuesIter, _defaults->incrementInt); } else if(isFloatType()) { incrementValues.insert(incrementValuesIter, _defaults->incrementFloat); } bool boundsChanged = false; bool rangeChanged = false; bool valueChanged = false; checkRange(boundsChanged, rangeChanged, index); constrainValue(valueChanged,index); } else { return false; } }
static int getUniform(GLuint progHandle, ActiveUniform *u) { int error; allocateUniformStorage(u); if (!u->value) { return DBG_ERROR_MEMORY_ALLOCATION_FAILED; } if (isIntType(u->type)) { ORIG_GL(glGetUniformiv)(progHandle, u->location, u->value); } else if (isUIntType(u->type)) { ORIG_GL(glGetUniformuivEXT)(progHandle, u->location, u->value); } else { ORIG_GL(glGetUniformfv)(progHandle, u->location, u->value); } error = glError(); if (error) { free(u->value); return error; } return DBG_NO_ERROR; }
Type dictElemType(SSATmp* arr, SSATmp* idx) { assertx(arr->isA(TDict)); assertx(!idx || idx->isA(TInt | TStr)); if (arr->hasConstVal()) { // If both the array and idx are known statically, we can resolve it to the // precise type. if (idx && idx->hasConstVal(TInt)) { auto const idxVal = idx->intVal(); auto const val = MixedArray::NvGetIntDict(arr->dictVal(), idxVal); return val ? Type(val->m_type) : TBottom; } if (idx && idx->hasConstVal(TStr)) { auto const idxVal = idx->strVal(); auto const val = MixedArray::NvGetStrDict(arr->dictVal(), idxVal); return val ? Type(val->m_type) : TBottom; } // Otherwise we can constrain the type according to the union of all the // types present in the dict. Type type{TBottom}; MixedArray::IterateKV( MixedArray::asMixed(arr->dictVal()), [&](const TypedValue* k, const TypedValue* v) { // Ignore values which can't correspond to the key's type if (isIntType(k->m_type)) { if (!idx || idx->type().maybe(TInt)) type |= Type(v->m_type); } else if (isStringType(k->m_type)) { if (!idx || idx->type().maybe(TStr)) type |= Type(v->m_type); } } ); return type; } // Dicts always contain initialized cells return arr->isA(TPersistentDict) ? TUncountedInit : TInitCell; }
bool isIntOrFloatType(const QByteArray &type) { return isIntType(type) || isFloatType(type); }
/* * Writes the stub implementation */ void generateStubImpl(const QString &idl, const QString &header, const QString & /*headerBase*/, const QString &filename, QDomElement de) { QFile impl(filename); if(!impl.open(IO_WriteOnly)) qFatal("Could not write to %s", filename.latin1()); QTextStream str(&impl); str << "/****************************************************************************" << endl; str << "**" << endl; str << "** DCOP Stub Implementation created by dcopidl2cpp from " << idl << endl; str << "**" << endl; str << "** WARNING! All changes made in this file will be lost!" << endl; str << "**" << endl; str << "*****************************************************************************/" << endl; str << endl; str << "#include \"" << header << "\"" << endl; str << "#include <dcopclient.h>" << endl << endl; str << "#include <qdatastream.h>" << endl; QDomElement e = de.firstChild().toElement(); for(; !e.isNull(); e = e.nextSibling().toElement()) { if(e.tagName() != "CLASS") continue; QDomElement n = e.firstChild().toElement(); Q_ASSERT(n.tagName() == "NAME"); QString classNameBase = n.firstChild().toText().data(); QString className_stub = classNameBase + "_stub"; QString classNameFull = className_stub; // class name with possible namespaces prepended // namespaces will be removed from className now int namespace_count = 0; QString namespace_tmp = className_stub; str << endl; for(;;) { int pos = namespace_tmp.find("::"); if(pos < 0) { className_stub = namespace_tmp; break; } str << "namespace " << namespace_tmp.left(pos) << " {" << endl; ++namespace_count; namespace_tmp = namespace_tmp.mid(pos + 2); } str << endl; // Write constructors str << className_stub << "::" << className_stub << "( const QCString& app, const QCString& obj )" << endl; str << " : "; // Always explicitly call DCOPStub constructor, because it's virtual base class. // Calling other ones doesn't matter, as they don't do anything important. str << "DCOPStub( app, obj )" << endl; str << "{" << endl; str << "}" << endl << endl; str << className_stub << "::" << className_stub << "( DCOPClient* client, const QCString& app, const QCString& obj )" << endl; str << " : "; str << "DCOPStub( client, app, obj )" << endl; str << "{" << endl; str << "}" << endl << endl; str << className_stub << "::" << className_stub << "( const DCOPRef& ref )" << endl; str << " : "; str << "DCOPStub( ref )" << endl; str << "{" << endl; str << "}" << endl << endl; // Write marshalling code QDomElement s = e.firstChild().toElement(); for(; !s.isNull(); s = s.nextSibling().toElement()) { if(s.tagName() != "FUNC") continue; QDomElement r = s.firstChild().toElement(); Q_ASSERT(r.tagName() == "TYPE"); QString result = r.firstChild().toText().data(); bool async = result == "ASYNC"; if(async) { result = "void"; str << result << " "; } else result = writeType(str, r); r = r.nextSibling().toElement(); Q_ASSERT(r.tagName() == "NAME"); QString funcName = r.firstChild().toText().data(); str << className_stub << "::" << funcName << "("; QStringList args; QStringList argtypes; bool first = true; r = r.nextSibling().toElement(); for(; !r.isNull(); r = r.nextSibling().toElement()) { if(!first) str << ", "; else str << " "; first = false; Q_ASSERT(r.tagName() == "ARG"); QDomElement a = r.firstChild().toElement(); QString type = writeType(str, a); argtypes.append(type); args.append(QString("arg") + QString::number(args.count())); str << args.last(); } if(!first) str << " "; str << ")"; // const methods in a stub can't compile, they need to call setStatus() // if ( s.hasAttribute("qual") ) // str << " " << s.attribute("qual"); str << endl; str << "{" << endl; funcName += "("; first = true; for(QStringList::Iterator it = argtypes.begin(); it != argtypes.end(); ++it) { if(!first) funcName += ","; first = false; funcName += *it; } funcName += ")"; if(async) { str << " if ( !dcopClient() ) {" << endl; str << "\tsetStatus( CallFailed );" << endl; str << "\treturn;" << endl; str << " }" << endl; str << " QByteArray data;" << endl; if(!args.isEmpty()) { str << " QDataStream arg( data, IO_WriteOnly );" << endl; for(QStringList::Iterator args_count = args.begin(); args_count != args.end(); ++args_count) { str << " arg << " << *args_count << ";" << endl; } } str << " dcopClient()->send( app(), obj(), \"" << funcName << "\", data );" << endl; str << " setStatus( CallSucceeded );" << endl; } else { if(result != "void") { str << " " << result << " result"; if(isIntType(result)) str << " = 0"; else if(result == "float" || result == "double") str << " = 0.0"; else if(result == "bool") str << " = false"; str << ";" << endl; } str << " if ( !dcopClient() ) {" << endl; str << "\tsetStatus( CallFailed );" << endl; if(result != "void") str << "\treturn result;" << endl; else str << "\treturn;" << endl; str << " }" << endl; str << " QByteArray data, replyData;" << endl; str << " QCString replyType;" << endl; if(!args.isEmpty()) { str << " QDataStream arg( data, IO_WriteOnly );" << endl; for(QStringList::Iterator args_count = args.begin(); args_count != args.end(); ++args_count) { str << " arg << " << *args_count << ";" << endl; } } str << " if ( dcopClient()->call( app(), obj(), \"" << funcName << "\","; str << " data, replyType, replyData ) ) {" << endl; if(result != "void") { str << "\tif ( replyType == \"" << result << "\" ) {" << endl; str << "\t QDataStream _reply_stream( replyData, IO_ReadOnly );" << endl; str << "\t _reply_stream >> result;" << endl; str << "\t setStatus( CallSucceeded );" << endl; str << "\t} else {" << endl; str << "\t callFailed();" << endl; str << "\t}" << endl; } else { str << "\tsetStatus( CallSucceeded );" << endl; } str << " } else { " << endl; str << "\tcallFailed();" << endl; str << " }" << endl; if(result != "void") str << " return result;" << endl; } str << "}" << endl << endl; } for(; namespace_count > 0; --namespace_count) str << "} // namespace" << endl; str << endl; } impl.close(); }
static int setUniform(GLint progHandle, ActiveUniform *u) { int error; GLint location; dbgPrint(DBGLVL_INFO, "setUniform(%i, %s)\n", progHandle, u->name); /* handle the special case of a uninitialized sampler uniform */ if (isSamplerType(u->type)) { GLint numTexUnits, maxTexCoords, maxCombinedTextureImageUnits; ORIG_GL(glGetIntegerv)(GL_MAX_TEXTURE_COORDS, &maxTexCoords); ORIG_GL(glGetIntegerv)(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxCombinedTextureImageUnits); numTexUnits = maxTexCoords > maxCombinedTextureImageUnits ? maxTexCoords : maxCombinedTextureImageUnits; if (((GLint*)u->value)[0] < 0 || ((GLint*)u->value)[0] >= numTexUnits) { dbgPrint(DBGLVL_INFO, "Sampler \"%s\" seems to be uninitialized (%i/%i/%i); ignoring\n", u->name, ((GLint*)u->value)[0], maxTexCoords, maxCombinedTextureImageUnits); return DBG_NO_ERROR; } } location = ORIG_GL(glGetUniformLocation)(progHandle, u->name); error = glError(); if (error) { return error; } if (location < 0) { dbgPrint(DBGLVL_INFO, "HMM, A UNIFORM NAMED \"%s\" IS NOT KNOWN TO " "THE PROGRAM\n", u->name); return DBG_NO_ERROR; } if (isMatrixType(u->type)) { switch (u->type) { case GL_FLOAT_MAT2: ORIG_GL(glUniformMatrix2fv)(location, u->size, 0, u->value); break; case GL_FLOAT_MAT2x3: ORIG_GL(glUniformMatrix2x3fv)(location, u->size, 0, u->value); break; case GL_FLOAT_MAT2x4: ORIG_GL(glUniformMatrix2x4fv)(location, u->size, 0, u->value); break; case GL_FLOAT_MAT3: ORIG_GL(glUniformMatrix3fv)(location, u->size, 0, u->value); break; case GL_FLOAT_MAT3x2: ORIG_GL(glUniformMatrix3x2fv)(location, u->size, 0, u->value); break; case GL_FLOAT_MAT3x4: ORIG_GL(glUniformMatrix3x4fv)(location, u->size, 0, u->value); break; case GL_FLOAT_MAT4: ORIG_GL(glUniformMatrix4fv)(location, u->size, 0, u->value); break; case GL_FLOAT_MAT4x2: ORIG_GL(glUniformMatrix4x2fv)(location, u->size, 0, u->value); break; case GL_FLOAT_MAT4x3: ORIG_GL(glUniformMatrix4x3fv)(location, u->size, 0, u->value); break; } } else if (isIntType(u->type)) { switch (uniformNumElements(u)) { case 1: ORIG_GL(glUniform1iv)(location, u->size, u->value); break; case 2: ORIG_GL(glUniform2iv)(location, u->size, u->value); break; case 3: ORIG_GL(glUniform3iv)(location, u->size, u->value); break; case 4: ORIG_GL(glUniform4iv)(location, u->size, u->value); break; } } else if (isUIntType(u->type)) { switch (uniformNumElements(u)) { case 1: ORIG_GL(glUniform1uivEXT)(location, u->size, u->value); break; case 2: ORIG_GL(glUniform2uivEXT)(location, u->size, u->value); break; case 3: ORIG_GL(glUniform3uivEXT)(location, u->size, u->value); break; case 4: ORIG_GL(glUniform4uivEXT)(location, u->size, u->value); break; } } else { /* float type */ switch (uniformNumElements(u)) { case 1: ORIG_GL(glUniform1fv)(location, u->size, u->value); break; case 2: ORIG_GL(glUniform2fv)(location, u->size, u->value); break; case 3: ORIG_GL(glUniform3fv)(location, u->size, u->value); break; case 4: ORIG_GL(glUniform4fv)(location, u->size, u->value); break; } } error = glError(); if (error) { return error; } else { return DBG_NO_ERROR; } }
void staticArrayStreamer(const ArrayData* ad, std::ostream& out) { out << "array("; if (!ad->empty()) { bool comma = false; for (ArrayIter it(ad); !it.end(); it.next()) { if (comma) { out << ","; } else { comma = true; } Variant key = it.first(); // Key. if (isIntType(key.getType())) { out << *key.getInt64Data(); } else if (isStringType(key.getType())) { out << "\"" << escapeStringForCPP(key.getStringData()->data(), key.getStringData()->size()) << "\""; } else { assert(false); } out << "=>"; Variant val = it.second(); // Value. [&] { switch (val.getType()) { case KindOfUninit: case KindOfNull: out << "null"; return; case KindOfBoolean: out << (val.toBoolean() ? "true" : "false"); return; case KindOfInt64: out << *val.getInt64Data(); return; case KindOfDouble: out << *val.getDoubleData(); return; case KindOfPersistentString: case KindOfString: out << "\"" << escapeStringForCPP(val.getStringData()->data(), val.getStringData()->size()) << "\""; return; case KindOfPersistentArray: case KindOfArray: staticArrayStreamer(val.getArrayData(), out); return; case KindOfObject: case KindOfResource: case KindOfRef: case KindOfClass: not_reached(); } }(); } } out << ")"; }
bool isSimpleType(const Type* t) { return isIntType(t) || isCharType(t) || isPointer(t) || isReference(t); }