Arquivos
hhvm/hphp/runtime/ext/ext_spl.cpp
T
andrewparoski 6ddef58d56 Remove LVariableTable, RVariableTable, and getHphpBinaryType()
This diff removes LVariableTable, RVariableTable, and getHphpBinaryType().
It also consolidates some of the include logic that was spread across
multiple files.
2013-03-12 14:22:13 -07:00

349 linhas
10 KiB
C++

/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010- Facebook, Inc. (http://www.facebook.com) |
| Copyright (c) 1997-2010 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#include <runtime/ext/ext_spl.h>
#include <runtime/ext/ext_math.h>
#include <runtime/ext/ext_class.h>
#include <system/lib/systemlib.h>
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
static StaticString s_spl_autoload("spl_autoload");
static StaticString s_spl_autoload_call("spl_autoload_call");
static StaticString s_default_extensions(".inc,.php");
#define SPL_ADD_CLASS(cls) ret.set(#cls, #cls)
Array f_spl_classes() {
Array ret;
SPL_ADD_CLASS(AppendIterator);
SPL_ADD_CLASS(ArrayIterator);
SPL_ADD_CLASS(ArrayObject);
SPL_ADD_CLASS(BadFunctionCallException);
SPL_ADD_CLASS(BadMethodCallException);
SPL_ADD_CLASS(CachingIterator);
SPL_ADD_CLASS(Countable);
SPL_ADD_CLASS(DirectoryIterator);
SPL_ADD_CLASS(DomainException);
SPL_ADD_CLASS(EmptyIterator);
SPL_ADD_CLASS(FilesystemIterator);
SPL_ADD_CLASS(FilterIterator);
SPL_ADD_CLASS(GlobIterator);
SPL_ADD_CLASS(InfiniteIterator);
SPL_ADD_CLASS(InvalidArgumentException);
SPL_ADD_CLASS(IteratorIterator);
SPL_ADD_CLASS(LengthException);
SPL_ADD_CLASS(LimitIterator);
SPL_ADD_CLASS(LogicException);
SPL_ADD_CLASS(MultipleIterator);
SPL_ADD_CLASS(NoRewindIterator);
SPL_ADD_CLASS(OuterIterator);
SPL_ADD_CLASS(OutOfBoundsException);
SPL_ADD_CLASS(OutOfRangeException);
SPL_ADD_CLASS(OverflowException);
SPL_ADD_CLASS(ParentIterator);
SPL_ADD_CLASS(RangeException);
SPL_ADD_CLASS(RecursiveArrayIterator);
SPL_ADD_CLASS(RecursiveCachingIterator);
SPL_ADD_CLASS(RecursiveDirectoryIterator);
SPL_ADD_CLASS(RecursiveFilterIterator);
SPL_ADD_CLASS(RecursiveIterator);
SPL_ADD_CLASS(RecursiveIteratorIterator);
SPL_ADD_CLASS(RecursiveRegexIterator);
SPL_ADD_CLASS(RecursiveTreeIterator);
SPL_ADD_CLASS(RegexIterator);
SPL_ADD_CLASS(RuntimeException);
SPL_ADD_CLASS(SeekableIterator);
SPL_ADD_CLASS(SplDoublyLinkedList);
SPL_ADD_CLASS(SplFileInfo);
SPL_ADD_CLASS(SplFileObject);
SPL_ADD_CLASS(SplFixedArray);
SPL_ADD_CLASS(SplHeap);
SPL_ADD_CLASS(SplMinHeap);
SPL_ADD_CLASS(SplMaxHeap);
SPL_ADD_CLASS(SplObjectStorage);
SPL_ADD_CLASS(SplObserver);
SPL_ADD_CLASS(SplPriorityQueue);
SPL_ADD_CLASS(SplQueue);
SPL_ADD_CLASS(SplStack);
SPL_ADD_CLASS(SplSubject);
SPL_ADD_CLASS(SplTempFileObject);
SPL_ADD_CLASS(UnderflowException);
SPL_ADD_CLASS(UnexpectedValueException);
return ret;
}
void throw_spl_exception(const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
std::string msg;
Util::string_vsnprintf(msg, fmt, ap);
va_end(ap);
throw Object(SystemLib::AllocExceptionObject(Variant(msg)));
}
static bool s_inited = false;
static int64_t s_hash_mask_handle = 0;
static Mutex s_mutex;
String f_spl_object_hash(CObjRef obj) {
if (!s_inited) {
Lock lock(s_mutex);
if (!s_inited) {
f_mt_srand();
s_hash_mask_handle |= f_mt_rand(); s_hash_mask_handle <<= 16;
s_hash_mask_handle |= f_mt_rand(); s_hash_mask_handle <<= 16;
s_hash_mask_handle |= f_mt_rand(); s_hash_mask_handle <<= 16;
s_hash_mask_handle |= f_mt_rand();
s_inited = true;
}
}
char buf[33];
snprintf(buf, sizeof(buf), "%032" PRIx64,
s_hash_mask_handle ^ (int64_t)obj.get());
return String(buf, CopyString);
}
Variant f_hphp_get_this() {
return g_vmContext->getThis();
}
Variant f_class_implements(CVarRef obj, bool autoload /* = true */) {
String clsname;
if (obj.isString()) {
clsname = obj.toString();
} else if (obj.isObject()) {
clsname = obj.toObject()->o_getClassName();
} else {
return false;
}
const ClassInfo *info = ClassInfo::FindClassInterfaceOrTrait(clsname);
if (info == NULL) {
if (!autoload) return false;
AutoloadHandler::s_instance->invokeHandler(clsname);
return f_class_implements(clsname, false);
}
Array ret(Array::Create());
ClassInfo::InterfaceVec ifs;
info->getAllInterfacesVec(ifs);
for (unsigned int i = 0; i < ifs.size(); i++) {
ret.set(ifs[i], ifs[i]);
}
return ret;
}
Variant f_class_parents(CVarRef obj, bool autoload /* = true */) {
String clsname;
if (obj.isString()) {
clsname = obj.toString();
} else if (obj.isObject()) {
clsname = obj.toObject()->o_getClassName();
} else {
return false;
}
const ClassInfo *info = ClassInfo::FindClassInterfaceOrTrait(clsname);
if (info == NULL) {
if (!autoload) return false;
AutoloadHandler::s_instance->invokeHandler(clsname);
return f_class_parents(clsname, false);
}
Array ret(Array::Create());
ClassInfo::ClassVec parents;
info->getAllParentsVec(parents);
for (unsigned int i = 0; i < parents.size(); i++) {
ret.set(parents[i], parents[i]);
}
return ret;
}
Variant f_class_uses(CVarRef obj, bool autoload /* = true */) {
String clsname;
if (obj.isString()) {
clsname = obj.toString();
} else if (obj.isObject()) {
clsname = obj.toObject()->o_getClassName();
} else {
return false;
}
const ClassInfo *info = ClassInfo::FindClassInterfaceOrTrait(clsname);
if (!info) {
if (!autoload) return false;
AutoloadHandler::s_instance->invokeHandler(clsname);
return f_class_uses(clsname, false);
}
Array ret(Array::Create());
const ClassInfo::TraitVec &traits = info->getTraitsVec();
for (unsigned int i = 0; i < traits.size(); i++) {
ret.set(traits[i], traits[i]);
}
return ret;
}
Variant f_iterator_apply(CVarRef obj, CVarRef func,
CArrRef params /* = null_array */) {
if (!obj.instanceof(SystemLib::s_TraversableClass)) {
return false;
}
Object pobj = obj.toObject();
pobj->o_invoke("rewind", null_array, -1);
int64_t count = 0;
while (same(pobj->o_invoke("valid", null_array, -1), true)) {
if (!same(f_call_user_func_array(func, params), true)) {
break;
}
++count;
pobj->o_invoke("next", null_array, -1);
}
return count;
}
Variant f_iterator_count(CVarRef obj) {
if (!obj.instanceof(SystemLib::s_TraversableClass)) {
return false;
}
Object pobj = obj.toObject();
pobj->o_invoke("rewind", null_array, -1);
int64_t count = 0;
while (same(pobj->o_invoke("valid", null_array, -1), true)) {
++count;
pobj->o_invoke("next", null_array, -1);
}
return count;
}
Variant f_iterator_to_array(CVarRef obj, bool use_keys /* = true */) {
if (!obj.instanceof(SystemLib::s_TraversableClass)) {
return false;
}
Array ret(Array::Create());
Object pobj = obj.toObject();
pobj->o_invoke("rewind", null_array, -1);
while (same(pobj->o_invoke("valid", null_array, -1), true)) {
Variant val = pobj->o_invoke("current", null_array, -1);
if (use_keys) {
Variant key = pobj->o_invoke("key", null_array, -1);
ret.set(key, val);
} else {
ret.append(val);
}
pobj->o_invoke("next", null_array, -1);
}
return ret;
}
bool f_spl_autoload_register(CVarRef autoload_function /* = null_variant */,
bool throws /* = true */,
bool prepend /* = false */) {
if (autoload_function.same(s_spl_autoload_call)) {
if (throws) {
throw_spl_exception("Function spl_autoload_call()"
"cannot be registered");
}
return false;
}
CVarRef func = autoload_function.isNull() ?
s_spl_autoload : autoload_function;
bool res = AutoloadHandler::s_instance->addHandler(func, prepend);
if (!res && throws) {
throw_spl_exception("Invalid autoload_function specified");
}
return res;
}
bool f_spl_autoload_unregister(CVarRef autoload_function) {
if (autoload_function.same(s_spl_autoload_call)) {
AutoloadHandler::s_instance->removeAllHandlers();
} else {
AutoloadHandler::s_instance->removeHandler(autoload_function);
}
return true;
}
Variant f_spl_autoload_functions() {
CArrRef handlers = AutoloadHandler::s_instance->getHandlers();
if (handlers.isNull())
return false;
else
return handlers.values();
}
void f_spl_autoload_call(CStrRef class_name) {
AutoloadHandler::s_instance->invokeHandler(class_name, true);
}
namespace {
class ExtensionList : public RequestEventHandler {
public:
virtual void requestInit() {
extensions = CREATE_VECTOR2(String(".inc"), String(".php"));
}
virtual void requestShutdown() {
extensions.reset();
}
Array extensions;
};
IMPLEMENT_STATIC_REQUEST_LOCAL(ExtensionList, s_extension_list);
}
String f_spl_autoload_extensions(CStrRef file_extensions /* = null_string */) {
if (!file_extensions.isNull()) {
s_extension_list->extensions = StringUtil::Explode(file_extensions, ",")
.toArray();
return file_extensions;
}
return StringUtil::Implode(s_extension_list->extensions, ",");
}
void f_spl_autoload(CStrRef class_name,
CStrRef file_extensions /* = null_string */) {
Array ext = file_extensions.isNull()
? s_extension_list->extensions
: StringUtil::Explode(file_extensions, ",").toArray();
String lClass = StringUtil::ToLower(class_name);
bool found = false;
for (ArrayIter iter(ext); iter; ++iter) {
String fileName = lClass + iter.second();
include(fileName, true, "", false);
if (f_class_exists(class_name, false)) {
found = true;
break;
}
}
if (!found && !AutoloadHandler::s_instance->isRunning()) {
throw_spl_exception("Class %s could not be loaded", class_name.c_str());
}
}
///////////////////////////////////////////////////////////////////////////////
}