public static PhpArray GetDefinedVariables(Dictionary <string, object> localVariables) { PhpArray globals = (localVariables != null) ? null : ScriptContext.CurrentContext.GlobalVariables; PhpArray result = new PhpArray((localVariables != null) ? localVariables.Count : globals.Count); foreach (KeyValuePair <string, object> entry in PhpArray.GetEnumerator(globals, localVariables)) { result.Add(entry.Key, PhpVariable.DeepCopy(entry.Value)); } return(result); }
public static PhpArray Compact(Dictionary <string, object> localVariables, params object[] names) { if (names == null) { PhpException.ArgumentNull("names"); return(null); } PhpArray globals = (localVariables != null) ? null : ScriptContext.CurrentContext.GlobalVariables; PhpArray result = new PhpArray(); for (int i = 0; i < names.Length; i++) { string name; PhpArray array; if ((name = PhpVariable.AsString(names[i])) != null) { // if variable exists adds a copy of its current value to the result: object value; if (PhpHashtable.TryGetValue(globals, localVariables, name, out value)) { result.Add(name, PhpVariable.DeepCopy(value)); } } else if ((array = names[i] as PhpArray) != null) { // recursively searches for string variable names: using (PhpHashtable.RecursiveEnumerator iterator = array.GetRecursiveEnumerator(false, true)) { while (iterator.MoveNext()) { if ((name = PhpVariable.AsString(iterator.Current.Value)) != null) { // if variable exists adds a copy of its current value to the result: object value; if (PhpHashtable.TryGetValue(globals, localVariables, name, out value)) { result.Add(name, PhpVariable.DeepCopy(value)); } } } } } } return(result); }
private static void AddGpcVariables(PhpArray /*!*/ globals, PhpArray /*!*/ gpcArray, string prefix) { foreach (KeyValuePair <IntStringKey, object> entry in gpcArray) { string name = prefix + entry.Key.ToString(); if (name == VariableName.GlobalsName) { PhpException.Throw(PhpError.Warning, LibResources.GetString("attempted_variable_override", VariableName.GlobalsName)); } else { globals[name] = PhpVariable.DeepCopy(entry.Value); } } }
public static DObject CreateClrThread(PhpCallback /*!*/ callback, params object[] args) { if (callback == null) { PhpException.ArgumentNull("callback"); } if (!callback.Bind()) { return(null); } object[] copies = (args != null) ? new object[args.Length] : ArrayUtils.EmptyObjects; for (int i = 0; i < copies.Length; i++) { copies[i] = PhpVariable.DeepCopy(args[i]); } return(ClrObject.WrapRealObject(ThreadPool.QueueUserWorkItem(new Worker(ScriptContext.CurrentContext, copies).Run, callback))); }
public static int Extract(Dictionary <string, object> localVariables, PhpArray /*!*/ vars, ExtractType type, string prefix) { if (vars == null) { PhpException.ArgumentNull("vars"); return(0); } if (vars.Count == 0) { return(0); } // unfortunately, type contains flags are combined with enumeration: bool refs = (type & ExtractType.Refs) != 0; type &= ExtractType.NonFlags; // // construct the action used to set the variable into the locals/globals // Action <string /*name*/, object /*value*/> updateVariableFn; // function that writes the value to locals/globals Predicate <string /*name*/> containsFn; // function that checks if variable exists PhpArray globals = (localVariables != null) ? null : ScriptContext.CurrentContext.GlobalVariables; #region select function that writes the variable if (refs) { // makes a reference and writes it back (deep copy is not necessary, "no duplicate pointers" rule preserved): if (localVariables != null) { updateVariableFn = (name, value) => { localVariables[name] = vars[name] = PhpVariable.MakeReference(value); }; } else { updateVariableFn = (name, value) => { globals[name] = vars[name] = PhpVariable.MakeReference(value); }; } } else { if (localVariables != null) { updateVariableFn = (name, value) => { // deep copy the value value = PhpVariable.DeepCopy(PhpVariable.Dereference(value)); // put into locals object item; PhpReference ref_item; if (localVariables.TryGetValue(name, out item) && (ref_item = item as PhpReference) != null) { ref_item.Value = value; } else { localVariables[name] = value; } }; } else { updateVariableFn = (name, value) => { // deep copy the value value = PhpVariable.DeepCopy(PhpVariable.Dereference(value)); // set the value to globals object item; PhpReference ref_item; if (globals.TryGetValue(name, out item) && (ref_item = item as PhpReference) != null) { ref_item.Value = value; } else { globals[name] = value; } }; } } #endregion Debug.Assert(updateVariableFn != null); #region select function that checks if variable exists if (localVariables != null) { containsFn = (name) => localVariables.ContainsKey(name); } else { containsFn = (name) => globals.ContainsKey(name); } #endregion Debug.Assert(containsFn != null); // // // int extracted_count = 0; foreach (KeyValuePair <IntStringKey, object> entry in vars) { string name = entry.Key.ToString(); if (String.IsNullOrEmpty(name) && type != ExtractType.PrefixInvalid) { continue; } switch (type) { case ExtractType.Overwrite: // anything is overwritten: break; case ExtractType.Skip: // skips existing name: if (containsFn(name)) { continue; } break; case ExtractType.IfExists: // skips nonexistent name: if (!containsFn(name)) { continue; } break; case ExtractType.PrefixAll: // prefix anything: name = String.Concat(prefix, "_", name); break; case ExtractType.PrefixInvalid: // prefixes invalid, others are overwritten: if (!PhpVariable.IsValidName(name)) { name = String.Concat(prefix, "_", name); } break; case ExtractType.PrefixSame: // prefixes existing, others are overwritten: if (containsFn(name)) { name = String.Concat(prefix, "_", name); } break; case ExtractType.PrefixIfExists: // prefixes existing, others are skipped: if (containsFn(name)) { name = String.Concat(prefix, "_", name); } else { continue; } break; default: PhpException.InvalidArgument("type", LibResources.GetString("arg:invalid_value")); return(0); } // invalid names are skipped: if (PhpVariable.IsValidName(name)) { // write the value to locals or globals: updateVariableFn(name, entry.Value); extracted_count++; } } return(extracted_count); }
//[return: PhpDeepCopy] // already deep copied public static PhpArray GetObjectVars(DTypeDesc caller, DObject obj, bool IgnoreReferences) { if (obj == null) { return(null); } Converter <object, object> copy = null; /////////////////////////////////////// // This is hot fix for a reference counting problem when reference aren't released in same way as in PHP. // Hence, we need to perform deep copy ignoring references if (IgnoreReferences) { copy = (value) => { PhpReference refValue = value as PhpReference; if (refValue != null) { return(copy(refValue.Value)); } PhpArray array = value as PhpArray; if (array != null) { PhpArray dst = new PhpArray(array.IntegerCount, array.StringCount); foreach (KeyValuePair <IntStringKey, object> entry in array) { // checks whether a value is a reference pointing to the instance itself: refValue = entry.Value as PhpReference; if (refValue != null && refValue.Value == array) { // copies the value so that it will self-reference the new instance (not the old one): dst.Add(entry.Key, new PhpReference(dst)); } else { dst.Add(entry.Key, copy(entry.Value)); } } return(dst); } return(value); } } ; else { copy = (value) => { return(PhpVariable.DeepCopy(value)); } }; // perform InplaceDeepCopy() here to save one more iteration through the array /////////////////////////////////////// PhpArray result = new PhpArray(0, obj.Count); var foreachEnumerator = obj.GetEnumerator((caller != null && caller.IsUnknown) ? PhpStackTrace.GetClassContext() : caller); while (foreachEnumerator.MoveNext()) //foreach (DictionaryEntry pair in obj) { DictionaryEntry pair = (DictionaryEntry)foreachEnumerator.Current; result.Add((string)pair.Key, copy(pair.Value)); } //result.InplaceCopyOnReturn = true; // already deep copied return(result); }