Variant IniSetting::Unbox(const Variant& boxed, std::set<ArrayData*>& seen, bool& use_defaults, const String& array_key) { assert(boxed.isArray()); Variant unboxed(Array::Create()); auto ad = boxed.getArrayData(); if (seen.insert(ad).second) { for (auto it = boxed.toArray().begin(); it; it.next()) { auto key = it.first(); // asserting here to ensure that key is a scalar type that can be // converted to a string. assert(key.isScalar()); auto& elem = it.secondRef(); unboxed.asArrRef().set( key, elem.isArray() ? Unbox(elem, seen, use_defaults, key.toString()) : elem ); } seen.erase(ad); } else { // The insert into seen wasn't successful. We have recursion. // break the recursive cycle, so the elements can be freed by the MM. // The const_cast is ok because we fully own the array, with no sharing. // Use the current array key to give a little help in the log message const_cast<Variant&>(boxed).unset(); use_defaults = true; Logger::Warning("INI Recursion Detected at offset named %s. " "Using default runtime settings.", array_key.toCppString().c_str()); } return unboxed; }
FObject EnvironmentGet(FObject env, FObject symid) { if (IdentifierP(symid)) symid = AsIdentifier(symid)->Symbol; FAssert(SymbolP(symid)); FObject gl = EqHashMapRef(AsEnvironment(env)->HashMap, symid, FalseObject); if (GlobalP(gl)) { FAssert(BoxP(AsGlobal(gl)->Box)); return(Unbox(AsGlobal(gl)->Box)); } return(NoValueObject); }
IniSettingMap IniSetting::FromStringAsMap(const std::string& ini, const std::string& filename) { Lock lock(s_mutex); // ini parser is not thread-safe // We are parsing something new, so reset this flag s_config_is_a_constant = false; SystemParserCallback cb; Variant parsed; zend_parse_ini_string(ini, filename, NormalScanner, cb, &parsed); if (parsed.isNull()) { return uninit_null(); } // We have the final values for our ini settings. // Unbox everything so that we have no more references in the map since we do // things that might require us not to have references // (e.g. calling Variant::SetEvalScalar(), which will assert if an // arraydata's elements are KindOfRef) std::set<ArrayData*> seen; bool use_defaults = false; Variant ret = Unbox(parsed, seen, use_defaults, empty_string()); if (use_defaults) { return uninit_null(); } return ret; }