Example #1
0
Array ClassInfo::GetConstants() {
  if (!s_loaded) Load();
  Array res;
  Array dyn;
  {
    const ConstantMap &scm = s_systemFuncs->getConstants();
    for (ConstantMap::const_iterator it = scm.begin(); it != scm.end(); ++it) {
      res.set(it->first, it->second->value);
    }
  }
  {
    const ConstantMap &ucm = s_userFuncs->getConstants();
    for (ConstantMap::const_iterator it = ucm.begin(); it != ucm.end(); ++it) {
      res.set(it->first, it->second->value);
    }
  }
  if (s_hook) {
    dyn = s_hook->getConstants();
    if (!dyn.isNull()) {
      res.merge(dyn);
    }
  }
  dyn = get_globals()->getDynamicConstants();
  if (!dyn.isNull()) {
    res.merge(dyn);
  }
  return res;
}
Example #2
0
Variant f_stream_context_create(const Array& options /* = null_array */,
                                const Array& params /* = null_array */) {
  if (!options.isNull() && !StreamContext::validateOptions(options)) {
    return false;
  }
  return Resource(NEWOBJ(StreamContext)(options, params));
}
Example #3
0
Array ClassInfo::GetClasses(bool declaredOnly) {
  if (!s_loaded) Load();

  Array ret;
  for (ClassMap::const_iterator iter = s_classes.begin();
       iter != s_classes.end(); ++iter) {
    if (!declaredOnly || !(iter->second->m_attribute & IsVolatile)) {
      ret.append(iter->first);
    }
  }
  // This way, the order of newly declared classes can be more consistent
  // with PHP.
  if (declaredOnly) {
    Array classes = get_globals()->getVolatileClasses();
    for (ArrayIter iter(classes); iter; ++iter) {
      ret.append(iter.first());
    }
  }
  if (s_hook) {
    Array dyn = s_hook->getClasses();
    if (!dyn.isNull()) {
      ret = ret.merge(dyn);
    }
  }
  return ret;
}
Example #4
0
bool ExecutionContext::callUserErrorHandler(const Exception &e, int64 errnum,
                                            bool swallowExceptions) {
  int errline = 0;
  String errfile;
  Array backtrace;
  const ExtendedException *ee = dynamic_cast<const ExtendedException*>(&e);
  if (ee) {
    ArrayPtr arr = ee->getBackTrace();
    if (arr) {
      backtrace = *arr;
      Array top = backtrace.rvalAt(0);
      if (!top.isNull()) {
        errfile = top.rvalAt("file");
        errline = top.rvalAt("line").toInt64();
      }
    }
  }
  if (backtrace.isNull()) {
    backtrace = stackTraceToBackTrace(e.getStackTrace());
  }

  bool retval = false;
  RequestData::Data *data = s_request_data->data;
  if (!data->systemExceptionHandlers.empty()) {
    // Avoid calling the user error handler recursively
    if (!data->insideUserHandler) {
      data->insideUserHandler = true;
      try {
        if (!same(f_call_user_func_array
                  (data->systemExceptionHandlers.back(),
                   CREATE_VECTOR6(errnum, String(e.getMessage()), errfile,
                                  errline, "", backtrace)),
                  false)) {
          retval = true;
        }
      } catch (...) {
        data->insideUserHandler = false;
        if (!swallowExceptions) throw;
      }
      data->insideUserHandler = false;
    }
  }

  return retval;
}
Example #5
0
Array StreamContext::getParams() const {
  Array params = m_params;
  if (params.isNull()) {
    params = Array::Create();
  }
  const String& options_key = String::FromCStr("options");
  params.set(options_key, getOptions());
  return params;
}
Example #6
0
Array CmdWhere::fetchStackTrace(DebuggerClient *client) {
  Array st = client->getStackTrace();
  if (st.isNull()) {
    CmdWherePtr cmd = client->xend<CmdWhere>(this);
    st = cmd->m_stacktrace;
    client->setStackTrace(st);
  }
  return st;
}
Example #7
0
Variant f_stream_context_create(const Array& options /* = null_array */,
                                const Array& params /* = null_array */) {
  if (!options.isNull() && !StreamContext::validateOptions(options)) {
    raise_warning("options should have the form "
                  "[\"wrappername\"][\"optionname\"] = $value");
    return Resource(NEWOBJ(StreamContext)(HPHP::null_array, HPHP::null_array));
  }
  return Resource(NEWOBJ(StreamContext)(options, params));
}
Example #8
0
bool same(const Variant& v1, const Array& v2) {
  bool null1 = v1.isNull();
  bool null2 = v2.isNull();
  if (null1 && null2) return true;
  if (null1 || null2) return false;
  if (!v1.isArray()) return false;
  auto const ad = v1.getArrayData();
  return v2->equal(ad, true);
}
bool BaseExecutionContext::callUserErrorHandler(const Exception &e, int errnum,
                                                bool swallowExceptions) {
  switch (getErrorState()) {
  case ExecutingUserHandler:
  case ErrorRaisedByUserHandler:
    return false;
  default:
    break;
  }
  if (!m_userErrorHandlers.empty() &&
      (m_userErrorHandlers.back().second & errnum) != 0) {
    int errline = 0;
    String errfile;
    Array backtrace;
    const ExtendedException *ee = dynamic_cast<const ExtendedException*>(&e);
    if (ee) {
      ArrayPtr arr = ee->getBackTrace();
      if (arr) {
        backtrace = *arr;
        Array top = backtrace.rvalAt(0);
        if (!top.isNull()) {
          errfile = top.rvalAt("file");
          errline = top.rvalAt("line").toInt64();
        }
      }
    }
    if (backtrace.isNull()) {
      backtrace = stackTraceToBackTrace(e.getStackTrace());
    }
    try {
      ErrorStateHelper esh(this, ExecutingUserHandler);
      if (!same(f_call_user_func_array
                (m_userErrorHandlers.back().first,
                 CREATE_VECTOR6(errnum, String(e.getMessage()), errfile,
                                errline, "", backtrace)),
                false)) {
        return true;
      }
    } catch (...) {
      if (!swallowExceptions) throw;
    }
  }
  return false;
}
Example #10
0
Array CmdWhere::fetchStackTrace(DebuggerClient &client) {
  Array st = client.getStackTrace();
  if (st.isNull()) {
    m_stackArgs = client.getDebuggerStackArgs();
    CmdWherePtr cmd = client.xend<CmdWhere>(this);
    st = cmd->m_stacktrace;
    client.setStackTrace(st);
  }
  return st;
}
Example #11
0
Variant f_stream_context_get_default(const Array& options /* = null_array */) {
  Resource &resource = g_context->getStreamContext();
  if (resource.isNull()) {
    resource = Resource(NEWOBJ(StreamContext)(Array::Create(),
                                              Array::Create()));
    g_context->setStreamContext(resource);
  }
  StreamContext *context = resource.getTyped<StreamContext>();
  if (!options.isNull() && !f_stream_context_set_option0(context, options)) {
    return false;
  }
  return resource;
}
Example #12
0
Array ClassInfo::GetClassLike(unsigned mask, unsigned value) {
  assert(s_loaded);

  Array ret = Array::Create();
  for (ClassMap::const_iterator iter = s_class_like.begin();
       iter != s_class_like.end(); ++iter) {
    const ClassInfo *info = iter->second->getDeclared();

    if (!info || (info->m_attribute & mask) != value) continue;
    ret.append(info->m_name);
  }
  if (value & IsInterface) {
    Array dyn = Unit::getInterfacesInfo();
    if (!dyn.isNull()) {
      ret.merge(dyn);
      // De-dup values, then renumber (for aesthetics).
      ret = ArrayUtil::StringUnique(ret).toArrRef();
      ret->renumber();
    }
  } else if (value & IsTrait) {
    Array dyn = Unit::getTraitsInfo();
    if (!dyn.isNull()) {
      ret.merge(dyn);
      // De-dup values, then renumber (for aesthetics).
      ret = ArrayUtil::StringUnique(ret).toArrRef();
      ret->renumber();
    }
  } else {
    Array dyn = Unit::getClassesInfo();
    if (!dyn.isNull()) {
      ret.merge(dyn);
      // De-dup values, then renumber (for aesthetics).
      ret = ArrayUtil::StringUnique(ret).toArrRef();
      ret->renumber();
    }
  }
  return ret;
}
Example #13
0
Array CmdWhere::fetchStackTrace(DebuggerClient &client) {
  Array st = client.getStackTrace();
  // Only grab a new stack trace if we don't have one cached, or if
  // the one cached does not match the type of stack trace being
  // requested.
  bool isAsync = m_type == KindOfWhereAsync;
  if (st.isNull() || (isAsync != client.isStackTraceAsync())) {
    m_stackArgs = client.getDebuggerClientStackArgs();
    auto cmd = client.xend<CmdWhere>(this);
    st = cmd->m_stacktrace;
    client.setStackTrace(st, isAsync);
  }
  return st;
}
Example #14
0
ATTRIBUTE_NORETURN
void raise_fatal_error(const char* msg,
                       const Array& bt /* = null_array */,
                       bool recoverable /* = false */,
                       bool silent /* = false */,
                       bool throws /* = true */) {
  if (RuntimeOption::PHP7_EngineExceptions && throws) {
    VMRegAnchor _;
    SystemLib::throwErrorObject(Variant(msg));
  }
  auto ex = bt.isNull() && !recoverable
    ? FatalErrorException(msg)
    : FatalErrorException(msg, bt, recoverable);
  ex.setSilent(silent);
  throw ex;
}
Example #15
0
Array ClassInfo::GetInterfaces(bool declaredOnly) {
  if (!s_loaded) Load();

  Array ret;
  for (ClassMap::const_iterator iter = s_interfaces.begin();
       iter != s_interfaces.end(); ++iter) {
    if (!declaredOnly || iter->second->isDeclared()) {
      ret.append(iter->first);
    }
  }
  if (s_hook) {
    Array dyn = s_hook->getInterfaces();
    if (!dyn.isNull()) {
      ret = ret.merge(dyn);
    }
  }
  return ret;
}
Example #16
0
Array ClassInfo::GetUserFunctions() {
  if (!s_loaded) Load();

  Array ret = Array::Create();
  if (s_userFuncs) {
    const MethodMap &methods = s_userFuncs->getMethods();
    for (MethodMap::const_iterator iter = methods.begin();
         iter != methods.end(); ++iter) {
      ret.append(iter->first);
    }
  }
  if (s_hook) {
    Array dyn = s_hook->getClasses();
    if (!dyn.isNull()) {
      ret = ret.merge(dyn);
    }
  }
  return ret;
}
Example #17
0
void ExtendedLogger::Log(LogLevelType level, const Array& stackTrace,
                         bool escape /* = true */,
                         bool escapeMore /* = false */) {
  assert(!escapeMore || escape);
  ThreadData *threadData = s_threadData.get();
  if (threadData->message != -1 &&
      ++threadData->message > MaxMessagesPerRequest &&
      MaxMessagesPerRequest >= 0) {
    return;
  }

  if (stackTrace.isNull()) return;

  if (UseLogFile) {
    FILE *f = Output ? Output : GetStandardOut(level);
    PrintStackTrace(f, stackTrace, escape, escapeMore);

    FILE *tf = threadData->log;
    if (tf) {
      PrintStackTrace(tf, stackTrace, escape, escapeMore);
    }
  }
}
Example #18
0
Array FrameInjection::GetBacktrace(bool skip /* = false */,
                                   bool withSelf /* = false */,
                                   bool withThis /* = true */) {
  Array bt = Array::Create();
  FrameInjection *t = ThreadInfo::s_threadInfo->m_top;
  if (skip && t) {
    t = t->m_prev;
  }
  // This is used by onError with extended exceptions
  if (withSelf && t) {
    String filename = t->getFileName();
    // If the top frame is not an extension function, and has actually been
    // entered (i.e. has a real line number) add it to the trace
    if (filename != "" && t->m_line != 0) {
      Array frame = Array::Create();
      frame.set(s_file, filename, true);
      frame.set(s_line, t->m_line, true);
      bt.append(frame);
    }
  }
  Array sbt = bt;
  FrameInjection *st = t;
  while (t && (RuntimeOption::InjectedStackTraceLimit < 0 ||
               bt.size() < RuntimeOption::InjectedStackTraceLimit)) {
    Array frame = t->getStackFrame(withSelf, withThis);
    if (frame.isNull()) return bt;
    bt.append(frame);
    t = t->m_prev;
  }
  if (!t) return bt;
  // The stack depth has exceeded the limit. Re-construct bt to include the
  // top and bottom frames. This is considered more useful in cases such as
  // infinite recursion.
  ASSERT(bt.size() == RuntimeOption::InjectedStackTraceLimit);
  int half = RuntimeOption::InjectedStackTraceLimit / 2;

  // start over, get the top half
  bt = sbt;
  t = st;
  while (t && bt.size() < half) {
    Array frame = t->getStackFrame(withSelf, withThis);
    if (frame.isNull()) assert(false);
    bt.append(frame);
    t = t->m_prev;
  }
  // then the bottom half
  std::vector<FrameInjection *> remainingFrames;
  while (t) {
    if (!t->m_prev && (t->m_flags & PseudoMain)) break;
    remainingFrames.push_back(t);
    t = t->m_prev;
  }
  int remaining = remainingFrames.size();
  int omitted = remaining - half;
  assert(omitted >= 0);
  if (omitted > 0) {
    std::string tmp("(...) ");
    tmp += boost::lexical_cast<std::string>(omitted) +
           " omitted frame" + ((omitted > 1) ? "s" : "");
    Array frame;
    frame.set(s_function, tmp);
    bt.append(frame);
  }
  for (int i = omitted; i < remaining; i++) {
    Array frame = remainingFrames[i]->getStackFrame(withSelf, withThis);
    if (frame.isNull()) assert(false);
    bt.append(frame);
  }
  return bt;
}
Example #19
0
Array FrameInjection::GetBacktrace(bool skip /* = false */,
                                   bool withSelf /* = false */,
                                   bool withThis /* = true */) {
  Array bt = Array::Create();
  FrameInjection *t = ThreadInfo::s_threadInfo->m_top;
  if (skip && t) {
    t = t->m_prev;
  }
  // This is used by onError with extended exceptions
  if (withSelf && t) {
    String filename = t->getFileName();
    // If the top frame is not an extension function,
    // add it to the trace
    if (filename != "") {
      Array frame = Array::Create();
      frame.set(s_file, filename, true);
      frame.set(s_line, t->m_line, true);
      bt.append(frame);
    }
  }
  while (t) {
    Array frame = Array::Create();

    if (t->m_prev) {
      String file = t->m_prev->getFileName();
      if (!file.empty() && t->m_prev->m_line) {
        frame.set(s_file, file, true);
        frame.set(s_line, t->m_prev->m_line, true);
      }
    } else if (t->m_flags & PseudoMain) {
      // Stop at top, don't include top file
      break;
    }

    if (t->m_flags & PseudoMain) {
      frame.set(s_function, "include", true);
      frame.set(s_args, Array::Create(t->getFileName()), true);
    } else {
      const char *c = strstr(t->m_name, "::");
      if (c) {
        frame.set(s_function, String(c + 2), true);
        frame.set(s_class, t->m_class->copy(), true);
        if (!t->m_object.isNull()) {
          if (withThis) {
            frame.set(s_object, t->m_object, true);
          }
          frame.set(s_type, "->", true);
        } else {
          frame.set(s_type, "::", true);
        }
      } else {
        frame.set(s_function, t->m_name, true);
      }

      Array args = t->getArgs();
      if (!args.isNull()) {
        frame.set(s_args, args, true);
      } else {
        frame.set(s_args, Array::Create(), true);
      }
    }

    bt.append(frame);
    t = t->m_prev;
  }
  return bt;
}
Example #20
0
bool TestCppBase::TestArray() {
  // Array::Create(), Array constructors and informational
  {
    Array arr;
    VERIFY(arr.empty()); VERIFY(arr.size() == 0); VERIFY(arr.length() == 0);
    VERIFY(arr.isNull());

    arr = Array::Create();
    VERIFY(arr.empty()); VERIFY(arr.size() == 0); VERIFY(arr.length() == 0);
    VERIFY(!arr.isNull());

    arr = Array::Create(0);
    VERIFY(!arr.empty()); VERIFY(arr.size() == 1); VERIFY(arr.length() == 1);
    VERIFY(!arr.isNull());
    VERIFY(arr[0].toInt32() == 0);

    arr = Array::Create("test");
    VERIFY(!arr.empty()); VERIFY(arr.size() == 1); VERIFY(arr.length() == 1);
    VERIFY(!arr.isNull());
    VERIFY(equal(arr[0], String("test")));

    Array arrCopy = arr;
    arr = Array::Create(arr);
    VERIFY(!arr.empty()); VERIFY(arr.size() == 1); VERIFY(arr.length() == 1);
    VERIFY(!arr.isNull());
    VERIFY(arr[0].toArray().size() == 1);
    VS(arr[0], arrCopy);

    arr = Array::Create("name", 1);
    VERIFY(!arr.empty()); VERIFY(arr.size() == 1); VERIFY(arr.length() == 1);
    VERIFY(!arr.isNull());
    VERIFY(arr[s_name].toInt32() == 1);

    arr = Array::Create(s_name, "test");
    VERIFY(!arr.empty()); VERIFY(arr.size() == 1); VERIFY(arr.length() == 1);
    VERIFY(!arr.isNull());
    VERIFY(equal(arr[s_name], String("test")));

    arrCopy = arr;
    arr = Array::Create(s_name, arr);
    VERIFY(!arr.empty()); VERIFY(arr.size() == 1); VERIFY(arr.length() == 1);
    VERIFY(!arr.isNull());
    VS(arr[s_name], arrCopy);
    VERIFY(arr[s_name].toArray().size() == 1);
  }

  // iteration
  {
    Array arr = make_map_array("n1", "v1", "n2", "v2");
    int i = 0;
    for (ArrayIter iter = arr.begin(); iter; ++iter, ++i) {
      if (i == 0) {
        VERIFY(equal(iter.first(), String("n1")));
        VERIFY(equal(iter.second(), String("v1")));
      } else {
        VERIFY(equal(iter.first(), String("n2")));
        VERIFY(equal(iter.second(), String("v2")));
      }
    }
    VERIFY(i == 2);
  }

  static const StaticString s_Array("Array");

  // conversions
  {
    Array arr0;
    VERIFY(arr0.toBoolean() == false);
    VERIFY(arr0.toByte() == 0);
    VERIFY(arr0.toInt16() == 0);
    VERIFY(arr0.toInt32() == 0);
    VERIFY(arr0.toInt64() == 0);
    VERIFY(arr0.toDouble() == 0.0);
    VERIFY(arr0.toString().empty());

    Array arr1 = Array::Create("test");
    VERIFY(arr1.toBoolean() == true);
    VERIFY(arr1.toByte() == 1);
    VERIFY(arr1.toInt16() == 1);
    VERIFY(arr1.toInt32() == 1);
    VERIFY(arr1.toInt64() == 1);
    VERIFY(arr1.toDouble() == 1.0);
    VERIFY(arr1.toString() == s_Array);
  }

  // offset
  {
    Array arr;
    arr.set(0, "v1");
    arr.set(1, "v2");
    VS(arr, make_packed_array("v1", "v2"));
  }
  {
    Array arr;
    arr.set(s_n1, "v1");
    arr.set(s_n2, "v2");
    VS(arr, make_map_array("n1", "v1", "n2", "v2"));
  }
  {
    Array arr;
    arr.lvalAt(0) = String("v1");
    arr.lvalAt(1) = String("v2");
    VS(arr, make_packed_array("v1", "v2"));
  }
  {
    Array arr;
    arr.lvalAt(s_n1) = String("v1");
    arr.lvalAt(s_n2) = String("v2");
    VS(arr, make_map_array("n1", "v1", "n2", "v2"));
  }
  {
    Array arr;
    Variant name = "name";
    arr.lvalAt(name) = String("value");
    VS(arr, make_map_array("name", "value"));
  }

  {
    Array arr;
    arr.lvalAt(1) = 10;
    VS(arr[1], 10);
    VS(arr[Variant(1.5)], 10);
    VS(arr[s_1], 10);
    VS(arr[Variant("1")], 10);
  }
  {
    Array arr;
    arr.lvalAt(Variant(1.5)) = 10;
    VS(arr[1], 10);
    VS(arr[Variant(1.5)], 10);
    VS(arr[s_1], 10);
    VS(arr[Variant("1")], 10);
  }
  {
    Array arr;
    arr.lvalAt(s_1) = 10;
    VS(arr[1], 10);
    VS(arr[Variant(1.5)], 10);
    VS(arr[s_1], 10);
    VS(arr[Variant("1")], 10);
  }
  {
    Array arr;
    arr.lvalAt(Variant("1")) = 10;
    VS(arr[1], 10);
    VS(arr[Variant(1.5)], 10);
    VS(arr[s_1], 10);
    VS(arr[Variant("1")], 10);
  }

  // membership
  {
    Array arr;
    arr.lvalAt(0) = String("v1");
    arr.lvalAt(1) = String("v2");
    VERIFY(arr.exists(0));
    arr.remove(0);
    VERIFY(!arr.exists(0));
    VS(arr, Array::Create(1, "v2"));
    arr.append("v3");
    VS(arr, make_map_array(1, "v2", 2, "v3"));
  }
  {
    static const StaticString s_0("0");
    Array arr;
    arr.lvalAt(0) = String("v1");
    VERIFY(arr.exists(0));
    arr.remove(String(s_0));
    VERIFY(!arr.exists(0));
  }
  {
    Array arr;
    arr.lvalAt(0) = String("v1");
    VERIFY(arr.exists(0));
    arr.remove(Variant("0"));
    VERIFY(!arr.exists(0));
  }
  {
    Array arr;
    arr.lvalAt(0) = String("v1");
    VERIFY(arr.exists(0));
    arr.remove(Variant(Variant("0")));
    VERIFY(!arr.exists(0));
  }
  {
    Array arr;
    arr.lvalAt(0) = String("v1");
    VERIFY(arr.exists(0));
    arr.remove(Variant(Variant(0.5)));
    VERIFY(!arr.exists(0));
  }
  {
    Array arr;
    arr.lvalAt(Variant()) = 123;
    VERIFY(arr.exists(empty_string_ref));
    arr.remove(Variant());
    VERIFY(!arr.exists(empty_string_ref));
  }
  {
    Array arr;
    arr.lvalAt(s_n1) = String("v1");
    arr.lvalAt(s_n2) = String("v2");
    VERIFY(arr.exists(s_n1));
    arr.remove(s_n1);
    VERIFY(!arr.exists(s_n1));
    VS(arr, Array::Create(s_n2, "v2"));
    arr.append("v3");
    VS(arr, make_map_array("n2", "v2", 0, "v3"));
  }
  {
    Array arr;
    arr.lvalAt() = String("test");
    VS(arr, make_packed_array("test"));
  }
  {
    Array arr;
    arr.lvalAt(s_name) = String("value");
    VERIFY(arr.exists(s_name));
  }
  {
    Array arr;
    arr.lvalAt(1) = String("value");
    VERIFY(arr.exists(1));
    VERIFY(arr.exists(s_1));
    VERIFY(arr.exists(Variant("1")));
    VERIFY(arr.exists(Variant(1)));
    VERIFY(arr.exists(Variant(1.5)));
  }
  {
    Array arr;
    arr.lvalAt(s_1) = String("value");
    VERIFY(arr.exists(1));
    VERIFY(arr.exists(s_1));
    VERIFY(arr.exists(Variant("1")));
    VERIFY(arr.exists(Variant(1)));
    VERIFY(arr.exists(Variant(1.5)));
  }
  {
    Array arr;
    arr.lvalAt(Variant(1.5)) = String("value");
    VERIFY(arr.exists(1));
    VERIFY(arr.exists(s_1));
    VERIFY(arr.exists(Variant("1")));
    VERIFY(arr.exists(Variant(1)));
    VERIFY(arr.exists(Variant(1.5)));
  }
  {
    Array arr;
    arr.lvalAt(Variant("1")) = String("value");
    VERIFY(arr.exists(1));
    VERIFY(arr.exists(s_1));
    VERIFY(arr.exists(Variant("1")));
    VERIFY(arr.exists(Variant(1)));
    VERIFY(arr.exists(Variant(1.5)));
  }

  // merge
  {
    Array arr = Array::Create(0) + Array::Create(1);
    VS(arr, Array::Create(0));
    arr += make_packed_array(0, 1);
    VS(arr, make_packed_array(0, 1));

    arr = Array::Create(0).merge(Array::Create(1));
    VS(arr, make_packed_array(0, 1));
    arr = arr.merge(make_packed_array(0, 1));
    VS(arr, make_packed_array(0, 1, 0, 1));

    arr = Array::Create("s0").merge(Array::Create("s1"));
    VS(arr, make_packed_array("s0", "s1"));

    arr = Array::Create("n0", "s0") + Array::Create("n1", "s1");
    VS(arr, make_map_array("n0", "s0", "n1", "s1"));
    arr += make_map_array("n0", "s0", "n1", "s1");
    VS(arr, make_map_array("n0", "s0", "n1", "s1"));

    arr = Array::Create("n0", "s0").merge(Array::Create("n1", "s1"));
    VS(arr, make_map_array("n0", "s0", "n1", "s1"));
    Array arrX = make_map_array("n0", "s2", "n1", "s3");
    arr = arr.merge(arrX);
    VS(arr, make_map_array("n0", "s2", "n1", "s3"));
  }

  {
    Array arr = make_map_array(0, "a", 1, "b");
    VERIFY(arr->isVectorData());
  }
  {
    Array arr = make_map_array(1, "a", 0, "b");
    VERIFY(!arr->isVectorData());
  }
  {
    Array arr = make_map_array(1, "a", 2, "b");
    VERIFY(!arr->isVectorData());
  }
  {
    Array arr = make_map_array(1, "a");
    arr.set(0, "b");
    VERIFY(!arr->isVectorData());
  }

  return Count(true);
}
Example #21
0
bool TestCppBase::TestArray() {
  // Array::Create(), Array constructors and informational
  {
    Array arr;
    VERIFY(arr.empty()); VERIFY(arr.size() == 0); VERIFY(arr.length() == 0);
    VERIFY(arr.isNull());

    arr = Array::Create();
    VERIFY(arr.empty()); VERIFY(arr.size() == 0); VERIFY(arr.length() == 0);
    VERIFY(!arr.isNull());

    arr = Array::Create(0);
    VERIFY(!arr.empty()); VERIFY(arr.size() == 1); VERIFY(arr.length() == 1);
    VERIFY(!arr.isNull());
    VERIFY((int)arr[0] == 0);
    VS(arr, Array(ArrayInit(1).set(0).create()));

    arr = Array::Create("test");
    VERIFY(!arr.empty()); VERIFY(arr.size() == 1); VERIFY(arr.length() == 1);
    VERIFY(!arr.isNull());
    VERIFY(arr[0] == "test");
    VS(arr, Array(ArrayInit(1).set("test").create()));

    Array arrCopy = arr;
    arr = Array::Create(arr);
    VERIFY(!arr.empty()); VERIFY(arr.size() == 1); VERIFY(arr.length() == 1);
    VERIFY(!arr.isNull());
    VERIFY(arr[0].toArray().size() == 1);
    VS(arr[0], arrCopy);
    VS(arr, Array(ArrayInit(1).set(arrCopy).create()));

    arr = Array::Create("name", 1);
    VERIFY(!arr.empty()); VERIFY(arr.size() == 1); VERIFY(arr.length() == 1);
    VERIFY(!arr.isNull());
    VERIFY((int)arr[s_name] == 1);
    VS(arr, Array(ArrayInit(1).set(s_name, 1).create()));

    arr = Array::Create(s_name, "test");
    VERIFY(!arr.empty()); VERIFY(arr.size() == 1); VERIFY(arr.length() == 1);
    VERIFY(!arr.isNull());
    VERIFY(arr[s_name] == "test");
    VS(arr, Array(ArrayInit(1).set(s_name, "test").create()));

    arrCopy = arr;
    arr = Array::Create(s_name, arr);
    VERIFY(!arr.empty()); VERIFY(arr.size() == 1); VERIFY(arr.length() == 1);
    VERIFY(!arr.isNull());
    VS(arr[s_name], arrCopy);
    VERIFY(arr[s_name].toArray().size() == 1);
    VS(arr, Array(ArrayInit(1).set(s_name, arrCopy).create()));
  }

  // iteration
  {
    Array arr = CREATE_MAP2("n1", "v1", "n2", "v2");
    int i = 0;
    for (ArrayIter iter = arr.begin(); iter; ++iter, ++i) {
      if (i == 0) {
        VERIFY(iter.first() == "n1");
        VERIFY(iter.second() == "v1");
      } else {
        VERIFY(iter.first() == "n2");
        VERIFY(iter.second() == "v2");
      }
    }
    VERIFY(i == 2);
  }
  /* TODO: fix this
  {
    Variant arr = CREATE_MAP2("n1", "v1", "n2", "v2");
    arr.escalate();
    for (ArrayIterPtr iter = arr.begin(arr, true); !iter->end(); iter->next()){
      unset(arr.lvalAt(iter->first()));
    }
    VS(arr, Array::Create());
  }
  */

  // conversions
  {
    Array arr0;
    VERIFY(arr0.toBoolean() == false);
    VERIFY(arr0.toByte() == 0);
    VERIFY(arr0.toInt16() == 0);
    VERIFY(arr0.toInt32() == 0);
    VERIFY(arr0.toInt64() == 0);
    VERIFY(arr0.toDouble() == 0.0);
    VERIFY(arr0.toString() == "");

    Array arr1 = Array::Create("test");
    VERIFY(arr1.toBoolean() == true);
    VERIFY(arr1.toByte() == 1);
    VERIFY(arr1.toInt16() == 1);
    VERIFY(arr1.toInt32() == 1);
    VERIFY(arr1.toInt64() == 1);
    VERIFY(arr1.toDouble() == 1.0);
    VERIFY(arr1.toString() == "Array");
  }

  // offset
  {
    Array arr;
    arr.set(0, "v1");
    arr.set(1, "v2");
    VS(arr, CREATE_VECTOR2("v1", "v2"));
  }
  {
    Array arr;
    arr.set(s_n1, "v1");
    arr.set(s_n2, "v2");
    VS(arr, CREATE_MAP2("n1", "v1", "n2", "v2"));
  }
  {
    Array arr;
    arr.lvalAt(0) = String("v1");
    arr.lvalAt(1) = String("v2");
    VS(arr, CREATE_VECTOR2("v1", "v2"));
  }
  {
    Array arr;
    arr.lvalAt(s_n1) = String("v1");
    arr.lvalAt(s_n2) = String("v2");
    VS(arr, CREATE_MAP2("n1", "v1", "n2", "v2"));
  }
  {
    Array arr;
    Variant name = "name";
    arr.lvalAt(name) = String("value");
    VS(arr, CREATE_MAP1("name", "value"));
  }
  {
    Array arr;
    arr.lvalAt(s_A) = 10;
    arr.lvalAt(s_A)++;
    VS(arr[s_A], 11);
  }

  {
    Array arr;
    arr.lvalAt(1) = 10;
    VS(arr[1], 10);
    VS(arr[1.5], 10);
    VS(arr[Variant(1.5)], 10);
    VS(arr[s_1], 10);
    VS(arr[Variant("1")], 10);
  }
  {
    Array arr;
    arr.lvalAt(Variant(1.5)) = 10;
    VS(arr[1], 10);
    VS(arr[1.5], 10);
    VS(arr[Variant(1.5)], 10);
    VS(arr[s_1], 10);
    VS(arr[Variant("1")], 10);
  }
  {
    Array arr;
    arr.lvalAt(s_1) = 10;
    VS(arr[1], 10);
    VS(arr[1.5], 10);
    VS(arr[Variant(1.5)], 10);
    VS(arr[s_1], 10);
    VS(arr[Variant("1")], 10);
  }
  {
    Array arr;
    arr.lvalAt(Variant("1")) = 10;
    VS(arr[1], 10);
    VS(arr[1.5], 10);
    VS(arr[Variant(1.5)], 10);
    VS(arr[s_1], 10);
    VS(arr[Variant("1")], 10);
  }

  // membership
  {
    Array arr;
    arr.lvalAt(0) = String("v1");
    arr.lvalAt(1) = String("v2");
    VERIFY(arr.exists(0));
    arr.remove(0);
    VERIFY(!arr.exists(0));
    VS(arr, Array::Create(1, "v2"));
    arr.append("v3");
    VS(arr, CREATE_MAP2(1, "v2", 2, "v3"));
  }
  {
    static const StaticString s_0("0");
    Array arr;
    arr.lvalAt(0) = String("v1");
    VERIFY(arr.exists(0));
    arr.remove(String(s_0));
    VERIFY(!arr.exists(0));
  }
  {
    Array arr;
    arr.lvalAt(0) = String("v1");
    VERIFY(arr.exists(0));
    arr.remove(Variant("0"));
    VERIFY(!arr.exists(0));
  }
  {
    Array arr;
    arr.lvalAt(0) = String("v1");
    VERIFY(arr.exists(0));
    arr.remove(Variant(Variant("0")));
    VERIFY(!arr.exists(0));
  }
  {
    Array arr;
    arr.lvalAt(0) = String("v1");
    VERIFY(arr.exists(0));
    arr.remove(Variant(Variant(0.5)));
    VERIFY(!arr.exists(0));
  }
  {
    Array arr;
    arr.lvalAt(Variant()) = 123;
    VERIFY(arr.exists(empty_string));
    arr.remove(Variant());
    VERIFY(!arr.exists(empty_string));
  }
  {
    Array arr;
    arr.lvalAt(s_n1) = String("v1");
    arr.lvalAt(s_n2) = String("v2");
    VERIFY(arr.exists(s_n1));
    arr.remove(s_n1);
    VERIFY(!arr.exists(s_n1));
    VS(arr, Array::Create(s_n2, "v2"));
    arr.append("v3");
    VS(arr, CREATE_MAP2("n2", "v2", 0, "v3"));
  }
  {
    Array arr;
    arr.lvalAt() = String("test");
    VS(arr, CREATE_VECTOR1("test"));
  }
  {
    Array arr;
    arr.lvalAt(s_name) = String("value");
    VERIFY(arr.exists(s_name));
  }
  {
    Array arr;
    arr.lvalAt(1) = String("value");
    VERIFY(arr.exists(1));
    VERIFY(arr.exists(1.5));
    VERIFY(arr.exists(s_1));
    VERIFY(arr.exists(Variant("1")));
    VERIFY(arr.exists(Variant(1)));
    VERIFY(arr.exists(Variant(1.5)));
  }
  {
    Array arr;
    arr.lvalAt(s_1) = String("value");
    VERIFY(arr.exists(1));
    VERIFY(arr.exists(1.5));
    VERIFY(arr.exists(s_1));
    VERIFY(arr.exists(Variant("1")));
    VERIFY(arr.exists(Variant(1)));
    VERIFY(arr.exists(Variant(1.5)));
  }
  {
    Array arr;
    arr.lvalAt(1.5) = String("value");
    VERIFY(arr.exists(1));
    VERIFY(arr.exists(1.5));
    VERIFY(arr.exists(s_1));
    VERIFY(arr.exists(Variant("1")));
    VERIFY(arr.exists(Variant(1)));
    VERIFY(arr.exists(Variant(1.5)));
  }
  {
    Array arr;
    arr.lvalAt(Variant(1.5)) = String("value");
    VERIFY(arr.exists(1));
    VERIFY(arr.exists(1.5));
    VERIFY(arr.exists(s_1));
    VERIFY(arr.exists(Variant("1")));
    VERIFY(arr.exists(Variant(1)));
    VERIFY(arr.exists(Variant(1.5)));
  }
  {
    Array arr;
    arr.lvalAt(Variant("1")) = String("value");
    VERIFY(arr.exists(1));
    VERIFY(arr.exists(1.5));
    VERIFY(arr.exists(s_1));
    VERIFY(arr.exists(Variant("1")));
    VERIFY(arr.exists(Variant(1)));
    VERIFY(arr.exists(Variant(1.5)));
  }

  // merge
  {
    Array arr = Array::Create(0) + Array::Create(1);
    VS(arr, Array::Create(0));
    arr += CREATE_VECTOR2(0, 1);
    VS(arr, CREATE_VECTOR2(0, 1));

    arr = Array::Create(0).merge(Array::Create(1));
    VS(arr, CREATE_VECTOR2(0, 1));
    arr = arr.merge(CREATE_VECTOR2(0, 1));
    VS(arr, CREATE_VECTOR4(0, 1, 0, 1));

    arr = Array::Create("s0").merge(Array::Create("s1"));
    VS(arr, CREATE_VECTOR2("s0", "s1"));

    arr = Array::Create("n0", "s0") + Array::Create("n1", "s1");
    VS(arr, CREATE_MAP2("n0", "s0", "n1", "s1"));
    arr += CREATE_MAP2("n0", "s0", "n1", "s1");
    VS(arr, CREATE_MAP2("n0", "s0", "n1", "s1"));

    arr = Array::Create("n0", "s0").merge(Array::Create("n1", "s1"));
    VS(arr, CREATE_MAP2("n0", "s0", "n1", "s1"));
    Array arrX = CREATE_MAP2("n0", "s2", "n1", "s3");
    arr = arr.merge(arrX);
    VS(arr, CREATE_MAP2("n0", "s2", "n1", "s3"));
  }

  // slice
  {
    Array arr = CREATE_VECTOR2("test1", "test2");
    Array sub = arr.slice(1, 1, true);
    VS(sub, CREATE_MAP1(1, "test2"));
  }
  {
    Array arr = CREATE_VECTOR2("test1", "test2");
    Array sub = arr.slice(1, 1, false);
    VS(sub, CREATE_VECTOR1("test2"));
  }
  {
    Array arr = CREATE_MAP2("n1", "test1", "n2", "test2");
    Array sub = arr.slice(1, 1, true);
    VS(sub, CREATE_MAP1("n2", "test2"));
  }
  {
    Array arr = CREATE_MAP2("n1", "test1", "n2", "test2");
    Array sub = arr.slice(1, 1, false);
    VS(sub, CREATE_MAP1("n2", "test2"));
  }

  // escalation
  {
    Array arr;
    lval(arr.lvalAt(0)).lvalAt(0) = 1.2;
    VS(arr, CREATE_VECTOR1(CREATE_VECTOR1(1.2)));
  }
  {
    Array arr;
    lval(arr.lvalAt(s_name)).lvalAt(0) = 1.2;
    VS(arr, CREATE_MAP1(s_name, CREATE_VECTOR1(1.2)));
  }
  {
    Array arr = Array::Create();
    lval(arr.lvalAt(0)).lvalAt(0) = 1.2;
    VS(arr, CREATE_VECTOR1(CREATE_VECTOR1(1.2)));
  }
  {
    Array arr = Array::Create();
    lval(arr.lvalAt(s_name)).lvalAt(0) = 1.2;
    VS(arr, CREATE_MAP1(s_name, CREATE_VECTOR1(1.2)));
  }
  {
    Array arr = Array::Create("test");
    arr.lvalAt(0) = CREATE_VECTOR1(1.2);
    VS(arr, CREATE_VECTOR1(CREATE_VECTOR1(1.2)));
  }
  {
    Array arr = Array::Create("test");
    lval(arr.lvalAt(s_name)).lvalAt(0) = 1.2;
    VS(arr, CREATE_MAP2(0, "test", s_name, CREATE_VECTOR1(1.2)));
  }
  {
    Array arr = Array::Create();
    arr.append("apple");
    arr.set(2, "pear");
    VS(arr[2], "pear");
  }

  {
    Array arr = CREATE_MAP2(0, "a", 1, "b");
    VERIFY(arr->isVectorData());
  }
  {
    Array arr = CREATE_MAP2(1, "a", 0, "b");
    VERIFY(!arr->isVectorData());
  }
  {
    Array arr = CREATE_MAP2(1, "a", 2, "b");
    VERIFY(!arr->isVectorData());
  }
  {
    Array arr = CREATE_MAP1(1, "a");
    arr.set(0, "b");
    VERIFY(!arr->isVectorData());
  }

  return Count(true);
}
Example #22
0
/**
 * New sprintf implementation for PHP.
 *
 * Modifiers:
 *
 *  " "   pad integers with spaces
 *  "-"   left adjusted field
 *   n    field size
 *  "."n  precision (floats only)
 *  "+"   Always place a sign (+ or -) in front of a number
 *
 * Type specifiers:
 *
 *  "%"   literal "%", modifiers are ignored.
 *  "b"   integer argument is printed as binary
 *  "c"   integer argument is printed as a single character
 *  "d"   argument is an integer
 *  "f"   the argument is a float
 *  "o"   integer argument is printed as octal
 *  "s"   argument is a string
 *  "x"   integer argument is printed as lowercase hexadecimal
 *  "X"   integer argument is printed as uppercase hexadecimal
 */
char *string_printf(const char *format, int len, CArrRef args, int *outlen) {
  Array vargs = args;
  if (!vargs.isNull() && !vargs->isVectorData()) {
    vargs = Array::Create();
    for (ArrayIter iter(args); iter; ++iter) {
      vargs.append(iter.second());
    }
  }

  if (len == 0) {
    return strdup("");
  }

  int size = 240;
  char *result = (char *)malloc(size);
  int outpos = 0;

  int argnum = 0, currarg = 1;
  for (int inpos = 0; inpos < len; ++inpos) {
    char ch = format[inpos];

    int expprec = 0;
    if (ch != '%') {
      appendchar(&result, &outpos, &size, ch);
      continue;
    }

    if (format[inpos + 1] == '%') {
      appendchar(&result, &outpos, &size, '%');
      inpos++;
      continue;
    }

    /* starting a new format specifier, reset variables */
    int alignment = ALIGN_RIGHT;
    int adjusting = 0;
    char padding = ' ';
    int always_sign = 0;
    int width, precision;
    inpos++;      /* skip the '%' */
    ch = format[inpos];

    if (isascii(ch) && !isalpha(ch)) {
      /* first look for argnum */
      int temppos = inpos;
      while (isdigit((int)format[temppos])) temppos++;
      if (format[temppos] == '$') {
        argnum = getnumber(format, &inpos);
        if (argnum <= 0) {
          free(result);
          throw_invalid_argument("argnum: must be greater than zero");
          return nullptr;
        }
        inpos++;  /* skip the '$' */
      } else {
        argnum = currarg++;
      }

      /* after argnum comes modifiers */
      for (;; inpos++) {
        ch = format[inpos];

        if (ch == ' ' || ch == '0') {
          padding = ch;
        } else if (ch == '-') {
          alignment = ALIGN_LEFT;
          /* space padding, the default */
        } else if (ch == '+') {
          always_sign = 1;
        } else if (ch == '\'') {
          padding = format[++inpos];
        } else {
          break;
        }
      }
      ch = format[inpos];

      /* after modifiers comes width */
      if (isdigit(ch)) {
        if ((width = getnumber(format, &inpos)) < 0) {
          free(result);
          throw_invalid_argument("width: must be greater than zero "
                                 "and less than %d", INT_MAX);
          return nullptr;
        }
        adjusting |= ADJ_WIDTH;
      } else {
        width = 0;
      }
      ch = format[inpos];

      /* after width and argnum comes precision */
      if (ch == '.') {
        ch = format[++inpos];
        if (isdigit((int)ch)) {
          if ((precision = getnumber(format, &inpos)) < 0) {
            free(result);
            throw_invalid_argument("precision: must be greater than zero "
                                   "and less than %d", INT_MAX);
            return nullptr;
          }
          ch = format[inpos];
          adjusting |= ADJ_PRECISION;
          expprec = 1;
        } else {
          precision = 0;
        }
      } else {
        precision = 0;
      }
    } else {
      width = precision = 0;
      argnum = currarg++;
    }

    if (argnum > vargs.size()) {
      free(result);
      throw_invalid_argument("arguments: (too few)");
      return nullptr;
    }

    if (ch == 'l') {
      ch = format[++inpos];
    }
    /* now we expect to find a type specifier */
    Variant tmp = vargs[argnum-1];

    switch (ch) {
    case 's': {
      String s = tmp.toString();
      appendstring(&result, &outpos, &size, s.c_str(),
                   width, precision, padding, alignment, s.size(),
                   0, expprec, 0);
      break;
    }
    case 'd':
      appendint(&result, &outpos, &size, tmp.toInt64(),
                width, padding, alignment, always_sign);
      break;
    case 'u':
      appenduint(&result, &outpos, &size, tmp.toInt64(),
                 width, padding, alignment);
      break;

    case 'g':
    case 'G':
    case 'e':
    case 'E':
    case 'f':
    case 'F':
      appenddouble(&result, &outpos, &size, tmp.toDouble(),
                   width, padding, alignment, precision, adjusting,
                   ch, always_sign);
      break;

    case 'c':
      appendchar(&result, &outpos, &size, tmp.toByte());
      break;

    case 'o':
      append2n(&result, &outpos, &size, tmp.toInt64(),
               width, padding, alignment, 3, hexchars, expprec);
      break;

    case 'x':
      append2n(&result, &outpos, &size, tmp.toInt64(),
               width, padding, alignment, 4, hexchars, expprec);
      break;

    case 'X':
      append2n(&result, &outpos, &size, tmp.toInt64(),
               width, padding, alignment, 4, HEXCHARS, expprec);
      break;

    case 'b':
      append2n(&result, &outpos, &size, tmp.toInt64(),
               width, padding, alignment, 1, hexchars, expprec);
      break;

    case '%':
      appendchar(&result, &outpos, &size, '%');

      break;
    default:
      break;
    }
  }

  /* possibly, we have to make sure we have room for the terminating null? */
  result[outpos]=0;
  if (outlen) *outlen = outpos;
  return result;
}
Example #23
0
Array FrameInjection::getStackFrame(bool withSelf, bool withThis) {
  Array frame = Array::Create();

  if (m_prev) {
    String file = m_prev->getFileName();
    if (!file.empty() && m_prev->m_line) {
      frame.set(s_file, file, true);
      frame.set(s_line, m_prev->m_line, true);
    }
  } else if (m_flags & PseudoMain) {
    // Stop at top, don't include top file
    return Array();
  }

  if (m_flags & PseudoMain) {
    frame.set(s_function, "include", true);
    frame.set(s_args, Array::Create(getFileName()), true);
  } else {
    const char *c = strstr(m_name, "::");
    const char *f = m_name;
    if (c) {
      f = c + 2;
      frame.set(s_class, getClassName()->copy(), true);
      if (ObjectData *obj = getObjectV()) {
        if (withThis) {
          frame.set(s_object, Object(obj), true);
        }
        frame.set(s_type, "->", true);
      } else {
        frame.set(s_type, "::", true);
      }
    }
    ASSERT(f);
    switch (f[0]) {
    case ParserBase::CharClosure:
      frame.set(s_function, s_closureBrackets, true);
      break;
    case ParserBase::CharContinuationFromClosure:
      frame.set(s_function, s_closureGenBrackets, true);
      break;
    default:
      if (const char *c = strstr(f, "$$")) {
        frame.set(s_function, String(f, c - f, CopyString), true);
      } else {
        if (isEvalFrame()) {
          frame.set(s_function, String(f, CopyString), true);
        } else {
          frame.set(s_function, f, true);
        }
      }
      break;
    }

    Array args = getArgs();
    if (!args.isNull()) {
      frame.set(s_args, args, true);
    } else {
      frame.set(s_args, Array::Create(), true);
    }
  }
  return frame;
}