Variant c_Collator::t_compare(CStrRef str1, CStrRef str2) { INSTANCE_METHOD_INJECTION_BUILTIN(Collator, Collator::compare); if (!m_ucoll) { raise_warning("compare called on uninitialized Collator object"); return 0; } UChar* ustr1 = NULL; UChar* ustr2 = NULL; int ustr1_len = 0; int ustr2_len = 0; m_errcode.clear(); intl_convert_utf8_to_utf16(&ustr1, &ustr1_len, str1.data(), str1.length(), &(m_errcode.code)); if (U_FAILURE(m_errcode.code)) { free(ustr1); return false; } intl_convert_utf8_to_utf16(&ustr2, &ustr2_len, str2.data(), str2.length(), &(m_errcode.code)); if (U_FAILURE(m_errcode.code)) { free(ustr1); free(ustr2); return false; } int64 ret = ucol_strcoll(m_ucoll, ustr1, ustr1_len, ustr2, ustr2_len); free(ustr1); free(ustr2); return ret; }
Variant f_bzcompress(CStrRef source, int blocksize /* = 4 */, int workfactor /* = 0 */) { char *dest = NULL; int error; unsigned int source_len, dest_len; source_len = source.length(); dest_len = source.length() + (0.01*source.length()) + 600; if (!(dest = (char *)malloc(dest_len + 1))) { return BZ_MEM_ERROR; } error = BZ2_bzBuffToBuffCompress(dest, &dest_len, (char *) source.c_str(), source_len, blocksize, 0, workfactor); if (error != BZ_OK) { free(dest); return error; } else { // this is to shrink the allocation, since we probably over allocated dest = (char *)realloc(dest, dest_len + 1); dest[dest_len] = '\0'; String ret = String(dest, dest_len, AttachString); return ret; } }
String f_icu_transliterate(CStrRef str, bool remove_accents) { #if HAVE_OLD_LIBICU // inspired by the UnicodeString::setToUTF8 implementation int32_t length = str.length(); int32_t bytesWritten=0; UnicodeString u_str; u_strFromUTF8WithSub(u_str.getBuffer(length+1), length+1, &bytesWritten, str.data(), length, 0xfffd, NULL, NULL); u_str.releaseBuffer(bytesWritten); #else UnicodeString u_str = UnicodeString::fromUTF8(str.data()); #endif if (remove_accents) { s_transliterator->transliterate(u_str); } else { s_transliterator->transliterate_with_accents(u_str); } // Convert the UnicodeString back into a UTF8 String. #if HAVE_OLD_LIBICU return icuStringToUTF8(u_str); #else int32_t capacity = u_str.countChar32() * sizeof(UChar) + 1; char* out = (char *)malloc(capacity); CheckedArrayByteSink bs(out, capacity); u_str.toUTF8(bs); return String(out, AttachString); #endif }
bool f_defined(CStrRef name, bool autoload /* = true */) { if (!name.get()) return false; const char *data = name.data(); int len = name.length(); // slice off starting backslash bool hadInitialBackslash = false; if (len > 0 && data[0] == '\\') { data += 1; len -= 1; hadInitialBackslash = true; } char *colon; if ((colon = (char*)memchr(data, ':', len)) && colon[1] == ':') { // class constant int classNameLen = colon - data; char *constantName = colon + 2; Class* cls = getClassByName(data, classNameLen); if (cls) { String cnsName(constantName, data + len - constantName, CopyString); return cls->clsCnsGet(cnsName.get()); } return false; } else { auto* cb = autoload ? Unit::loadCns : Unit::lookupCns; if (hadInitialBackslash) { String s(data, len, CopyString); return cb(s.get()); } else { return cb(name.get()); } } }
Variant f_constant(CStrRef name) { if (!name.get()) return uninit_null(); const char *data = name.data(); int len = name.length(); char *colon; if ((colon = (char*)memchr(data, ':', len)) && colon[1] == ':') { // class constant int classNameLen = colon - data; char *constantName = colon + 2; VM::Class* cls = getClassByName(data, classNameLen); if (cls) { String cnsName(constantName, data + len - constantName, CopyString); TypedValue* tv = cls->clsCnsGet(cnsName.get()); if (tv) { return tvAsCVarRef(tv); } } raise_warning("Couldn't find constant %s", data); return uninit_null(); } else { TypedValue* cns = VM::Unit::loadCns(name.get()); if (cns) return tvAsVariant(cns); return uninit_null(); } }
bool c_Memcached::getMultiImpl(CStrRef server_key, CArrRef keys, bool enableCas, Array *returnValue) { vector<const char*> keysCopy; keysCopy.reserve(keys.size()); vector<size_t> keysLengthCopy; keysLengthCopy.reserve(keys.size()); for (ArrayIter iter(keys); iter; ++iter) { Variant vKey = iter.second(); if (!vKey.isString()) continue; StringData *key = vKey.getStringData(); if (key->empty()) continue; keysCopy.push_back(key->data()); keysLengthCopy.push_back(key->size()); if (returnValue) returnValue->set(String(key), null_variant, true); } if (keysCopy.size() == 0) { m_impl->rescode = q_Memcached_RES_BAD_KEY_PROVIDED; return false; } memcached_behavior_set(&m_impl->memcached, MEMCACHED_BEHAVIOR_SUPPORT_CAS, enableCas ? 1 : 0); const char *myServerKey = server_key.empty() ? NULL : server_key.c_str(); size_t myServerKeyLen = server_key.length(); return handleError(memcached_mget_by_key(&m_impl->memcached, myServerKey, myServerKeyLen, keysCopy.data(), keysLengthCopy.data(), keysCopy.size())); }
bool RequestURI::virtualFileExists(const VirtualHost *vhost, const string &sourceRoot, const string &pathTranslation, CStrRef filename) { if (filename.empty() || filename.charAt(filename.length() - 1) == '/') { return false; } if (!vhost->getDocumentRoot().empty()) { string fullname = filename.data(); if (fullname[0] == '/') { fullname = fullname.substr(1); } else { fullname = pathTranslation + fullname; } m_path = fullname; m_absolutePath = String(sourceRoot) + m_path; if (StaticContentCache::TheFileCache && !fullname.empty() && StaticContentCache::TheFileCache->fileExists(fullname.c_str())) { return true; } struct stat st; return RuntimeOption::AllowedFiles.find(fullname.c_str()) != RuntimeOption::AllowedFiles.end() || (stat(m_absolutePath.c_str(), &st) == 0 && (st.st_mode & S_IFMT) == S_IFREG); } m_path = filename; m_absolutePath = String(sourceRoot) + filename; return true; }
Variant f_constant(CStrRef name) { if (!name.get()) return null; const char *data = name.data(); int len = name.length(); char *colon; if ((colon = (char*)memchr(data, ':', len)) && colon[1] == ':') { // class constant int classNameLen = colon - data; char *constantName = colon + 2; String className(data, classNameLen, CopyString); // translate "self" or "parent" if (className == "self") { String this_class = hhvm ? g_vmContext->getContextClassName() : FrameInjection::GetClassName(true); if (this_class.empty()) { throw FatalErrorException("Cannot access self:: " "when no class scope is active"); } else { className = this_class; } } else if (className == "parent") { String parent_class = hhvm ? g_vmContext->getParentContextClassName() : FrameInjection::GetParentClassName(true); if (parent_class.empty()) { throw FatalErrorException("Cannot access parent"); } else { className = parent_class; } } // taking care of volatile class if (class_exists(className)) { return get_class_constant(className, constantName, false); } else { return null; } } else { if (hhvm) { TypedValue* cns = g_vmContext->getCns(name.get()); if (cns == NULL) { if (AutoloadHandler::s_instance->autoloadConstant(name)) { cns = g_vmContext->getCns(name.get()); } } if (cns) return tvAsVariant(cns); return null; } else { const ClassInfo::ConstantInfo *cinfo = ClassInfo::FindConstant(name); // system/uniquely defined scalar constant (must be valid) if (cinfo) return cinfo->getValue(); if (!((Globals*)get_global_variables())->defined(name)) { AutoloadHandler::s_instance->autoloadConstant(name); } // dynamic/redeclared constant return ((Globals*)get_global_variables())->getConstant(name.data()); } } }
String StringUtil::Trim(CStrRef input, TrimType type /* = TrimBoth */, CStrRef charlist /* = k_HPHP_TRIM_CHARLIST */) { if (input.empty()) return input; int len = input.size(); char *ret = string_trim(input.data(), len, charlist.data(), charlist.length(), type); return String(ret, len, AttachString); }
bool c_Memcached::t_casbykey(double cas_token, CStrRef server_key, CStrRef key, CVarRef value, int expiration /*= 0*/) { INSTANCE_METHOD_INJECTION_BUILTIN(Memcached, Memcached::casbykey); m_impl->rescode = q_Memcached_RES_SUCCESS; if (key.empty()) { m_impl->rescode = q_Memcached_RES_BAD_KEY_PROVIDED; return false; } vector<char> payload; uint32 flags; toPayload(value, payload, flags); CStrRef myServerKey = server_key.empty() ? key : server_key; return handleError(memcached_cas_by_key(&m_impl->memcached, myServerKey.c_str(), myServerKey.length(), key.c_str(), key.length(), payload.data(), payload.size(), expiration, flags, (uint64)cas_token)); }
bool c_Memcached::setOperationImpl(SetOperation op, CStrRef server_key, CStrRef key, CVarRef value, int expiration) { m_impl->rescode = q_Memcached_RES_SUCCESS; if (key.empty()) { m_impl->rescode = q_Memcached_RES_BAD_KEY_PROVIDED; return false; } vector<char> payload; uint32 flags; toPayload(value, payload, flags); CStrRef myServerKey = server_key.empty() ? key : server_key; return handleError(op(&m_impl->memcached, myServerKey.c_str(), myServerKey.length(), key.c_str(), key.length(), payload.data(), payload.size(), expiration, flags)); }
String c_DateInterval::t_format(CStrRef format) { INSTANCE_METHOD_INJECTION_BUILTIN(DateInterval, DateInterval::format); StringBuffer s; const int LENGTH = 33; char buf[LENGTH]; int l; bool hasFormatSpec = false; for (int i = 0; i < format.length(); ++i) { char c = format.charAt(i); if (!hasFormatSpec) { if (c == '%') { hasFormatSpec = true; } else { s.append(c); } } else { switch (c) { case 'Y': l = snprintf(buf, LENGTH, "%02lld", m_y); break; case 'y': l = snprintf(buf, LENGTH, "%lld", m_y); break; case 'M': l = snprintf(buf, LENGTH, "%02lld", m_m); break; case 'm': l = snprintf(buf, LENGTH, "%lld", m_m); break; case 'D': l = snprintf(buf, LENGTH, "%02lld", m_d); break; case 'd': l = snprintf(buf, LENGTH, "%lld", m_d); break; case 'H': l = snprintf(buf, LENGTH, "%02lld", m_h); break; case 'h': l = snprintf(buf, LENGTH, "%lld", m_h); break; case 'I': l = snprintf(buf, LENGTH, "%02lld", m_i); break; case 'i': l = snprintf(buf, LENGTH, "%lld", m_i); break; case 'S': l = snprintf(buf, LENGTH, "%02lld", m_s); break; case 's': l = snprintf(buf, LENGTH, "%lld", m_s); break; case 'a': { if (m_days.isInteger()) { l = snprintf(buf, LENGTH, "%lld", m_days.toInt64()); } else { l = snprintf(buf, LENGTH, "(unknown)"); } break; } case 'r': l = snprintf(buf, LENGTH, "%s", m_invert ? "-" : ""); break; case 'R': l = snprintf(buf, LENGTH, "%c", m_invert ? '-' : '+'); break; case '%': l = snprintf(buf, 32, "%%"); break; default: buf[0] = '%'; buf[1] = c; buf[2] = '\0'; l = 2; break; } s.append(buf, std::min(l, LENGTH - 1)); hasFormatSpec = false; } } return s.detach(); }
Variant c_Memcached::t_getbykey(CStrRef server_key, CStrRef key, CVarRef cache_cb /*= null_variant*/, VRefParam cas_token /*= null_variant*/) { INSTANCE_METHOD_INJECTION_BUILTIN(Memcached, Memcached::getbykey); m_impl->rescode = q_Memcached_RES_SUCCESS; if (key.empty()) { m_impl->rescode = q_Memcached_RES_BAD_KEY_PROVIDED; return false; } memcached_behavior_set(&m_impl->memcached, MEMCACHED_BEHAVIOR_SUPPORT_CAS, cas_token.isReferenced() ? 1 : 0); const char *myServerKey = server_key.empty() ? NULL : server_key.c_str(); size_t myServerKeyLen = server_key.length(); const char *myKey = key.c_str(); size_t myKeyLen = key.length(); memcached_return status = memcached_mget_by_key(&m_impl->memcached, myServerKey, myServerKeyLen, &myKey, &myKeyLen, 1); if (!handleError(status)) return false; Variant returnValue; MemcachedResultWrapper result(&m_impl->memcached); if (!memcached_fetch_result(&m_impl->memcached, &result.value, &status)) { if (status == MEMCACHED_END) status = MEMCACHED_NOTFOUND; if (status == MEMCACHED_NOTFOUND && !cache_cb.isNull()) { status = doCacheCallback(cache_cb, key, returnValue); if (!handleError(status)) return false; if (cas_token.isReferenced()) cas_token = 0.0; return returnValue; } handleError(status); return false; } if (!toObject(returnValue, result.value)) { m_impl->rescode = q_Memcached_RES_PAYLOAD_FAILURE; return false; } if (cas_token.isReferenced()) { cas_token = (double) memcached_result_cas(&result.value); } return returnValue; }
bool f_defined(CStrRef name, bool autoload /* = true */) { if (!name.get()) return false; const char *data = name.data(); int len = name.length(); char *colon; if ((colon = (char*)memchr(data, ':', len)) && colon[1] == ':') { // class constant int classNameLen = colon - data; char *constantName = colon + 2; String className(data, classNameLen, CopyString); // translate "self" or "parent" if (className == "self") { String this_class = g_vmContext->getContextClassName(); if (this_class.empty()) { throw FatalErrorException("Cannot access self:: " "when no class scope is active"); } else { className = this_class; } } else if (className == "parent") { String parent_class = g_vmContext->getParentContextClassName(); if (parent_class.empty()) { throw FatalErrorException("Cannot access parent"); } else { className = parent_class; } } if (class_exists(className)) { // taking care of volatile class const ClassInfo *info; for (String parentClass = className; !parentClass.empty(); parentClass = info->getParentClass()) { info = ClassInfo::FindClass(parentClass); if (!info) { assert(false); } if (info->hasConstant(constantName)) return true; } return false; } else { return false; } } else { // system/uniquely defined scalar constant if (ClassInfo::FindConstant(name)) return true; if (g_vmContext->defined(name)) { return true; } if (!autoload || !AutoloadHandler::s_instance->autoloadConstant(name)) { return false; } return g_vmContext->defined(name); } }
bool c_Memcache::t_delete(CStrRef key, int expire /*= 0*/) { if (key.empty()) { raise_warning("Key cannot be empty"); return false; } memcached_return_t ret = memcached_delete(&m_memcache, key.c_str(), key.length(), expire); return (ret == MEMCACHED_SUCCESS); }
bool c_SpoofChecker::t_areconfusable( CStrRef s1, CStrRef s2, VRefParam issuesFound) { UErrorCode status = U_ZERO_ERROR; int32_t ret = uspoof_areConfusableUTF8( m_spoof_checker, s1.data(), s1.length(), s2.data(), s2.length(), &status); if (U_FAILURE(status)) { throw Exception( "Could not check [%s] and [%s] for confusability, error %d (%s)", s1.c_str(), s2.c_str(), status, u_errorName(status)); } issuesFound = ret; return ret != 0; }
static String intl_convert_str_utf8_to_utf16(CStrRef utf8_str, UErrorCode * status) { UChar* ustr = nullptr; int ustr_len = 0; intl_convert_utf8_to_utf16(&ustr, &ustr_len, utf8_str.data(), utf8_str.length(), status); if (U_FAILURE(*status)) { return (const char *)(L""); } return String((char*)ustr, UBYTES(ustr_len), AttachString); }
static String intl_convert_str_utf16_to_utf8(CStrRef utf16_str, UErrorCode * status) { char* str = nullptr; int str_len = 0; intl_convert_utf16_to_utf8(&str, &str_len, (UChar*)(utf16_str.data()), UCHARS(utf16_str.length()), status); if (U_FAILURE(*status)) { return ""; } return String(str, str_len, AttachString); }
void c_EncodingDetector::t_setdeclaredencoding(CStrRef text) { INSTANCE_METHOD_INJECTION_BUILTIN(EncodingDetector, EncodingDetector::setdeclaredencoding); UErrorCode status = U_ZERO_ERROR; ucsdet_setDeclaredEncoding( m_encoding_detector, text.data(), text.length(), &status); if (U_FAILURE(status)) { throw Exception( "Could not set encoding detector declared encoding to [%s], error %d (%s)", text.c_str(), status, u_errorName(status)); } }
Variant f_constant(CStrRef name) { if (!name.get()) return null; const char *data = name.data(); int len = name.length(); char *colon; if ((colon = (char*)memchr(data, ':', len)) && colon[1] == ':') { // class constant int classNameLen = colon - data; char *constantName = colon + 2; String className(data, classNameLen, CopyString); // translate "self" or "parent" if (className == "self") { String this_class = g_vmContext->getContextClassName(); if (this_class.empty()) { throw FatalErrorException("Cannot access self:: " "when no class scope is active"); } else { className = this_class; } } else if (className == "parent") { String parent_class =g_vmContext->getParentContextClassName(); if (parent_class.empty()) { throw FatalErrorException("Cannot access parent"); } else { className = parent_class; } } VM::Class* cls = VM::Unit::loadClass(className.get()); if (cls) { String cnsName(constantName, data + len - constantName, CopyString); TypedValue* tv = cls->clsCnsGet(cnsName.get()); if (tv) { return tvAsCVarRef(tv); } } raise_warning("Couldn't find constant %s", data); return null; } else { TypedValue* cns = g_vmContext->getCns(name.get()); if (cns == NULL) { if (AutoloadHandler::s_instance->autoloadConstant(name)) { cns = g_vmContext->getCns(name.get()); } } if (cns) return tvAsVariant(cns); return null; } }
bool f_defined(CStrRef name) { const char *data = name.data(); int len = name.length(); char *colon; if ((colon = (char*)memchr(data, ':', len)) && colon[1] == ':') { // class constant int classNameLen = colon - data; char *constantName = colon + 2; String className(data, classNameLen, CopyString); // translate "self" or "parent" if (className == "self") { String this_class = FrameInjection::GetClassName(true); if (this_class.empty()) { throw FatalErrorException("Cannot access self:: " "when no class scope is active"); } else { className = this_class; } } else if (className == "parent") { CStrRef parent_class = FrameInjection::GetParentClassName(true); if (parent_class.empty()) { throw FatalErrorException("Cannot access parent"); } else { className = parent_class; } } if (class_exists(className)) { // taking care of volatile class const ClassInfo *info; for (String parentClass = className; !parentClass.empty(); parentClass = info->getParentClass()) { info = ClassInfo::FindClass(parentClass); if (!info) { ASSERT(false); } if (info->hasConstant(constantName)) return true; } return false; } else { return false; } } else { // system/uniquely defined scalar constant if (ClassInfo::FindConstant(name)) return true; // dynamic/redeclared constant return ((Globals*)get_global_variables())->defined(name); } }
bool c_SpoofChecker::t_issuspicious(CStrRef text, VRefParam issuesFound) { UErrorCode status = U_ZERO_ERROR; int32_t ret = uspoof_checkUTF8( m_spoof_checker, text.data(), text.length(), NULL, &status); if (U_FAILURE(status)) { throw Exception( "Could not check [%s] for security issues, error %d (%s)", text.c_str(), status, u_errorName(status)); } issuesFound = ret; return ret != 0; }
int64_t c_Memcache::t_decrement(CStrRef key, int offset /*= 1*/) { if (key.empty()) { raise_warning("Key cannot be empty"); return false; } uint64_t value; memcached_return_t ret = memcached_decrement(&m_memcache, key.c_str(), key.length(), offset, &value); if (ret == MEMCACHED_SUCCESS) { return (int64_t)value; } return false; }
/* * trim a string left & right space * buf = " expires = 3000; " return "expires = 3000;" */ string TrimString(CStrRef buf) { LPCSTR p = buf.c_str(); LPCSTR q = p + buf.length(); for(; isspace(*p) && p <= q;) ++ p; for(; (*q == '\0' || isspace(*q)) && p <= q;) -- q; ++ q; string res; if(p < q) res.assign(p, q); return res; }
bool c_Memcache::t_replace(CStrRef key, CVarRef var, int flag /*= 0*/, int expire /*= 0*/) { if (key.empty()) { raise_warning("Key cannot be empty"); return false; } String serialized = memcache_prepare_for_storage(var, flag); memcached_return_t ret = memcached_replace(&m_memcache, key.c_str(), key.length(), serialized.c_str(), serialized.length(), expire, flag); return (ret == MEMCACHED_SUCCESS); }
Variant f_bzdecompress(CStrRef source, int small /* = 0 */) { char *dest; int source_len = source.length(); int error; uint64 size = 0; bz_stream bzs; bzs.bzalloc = NULL; bzs.bzfree = NULL; if (BZ2_bzDecompressInit(&bzs, 0, small) != BZ_OK) { return false; } bzs.next_in = (char *) source.c_str(); bzs.avail_in = source_len; /* in most cases bz2 offers at least 2:1 compression, so we use that as our base */ bzs.avail_out = source_len * 2; bzs.next_out = dest = (char *) malloc(bzs.avail_out + 1); if (!dest) { return BZ_MEM_ERROR; } while ((error = BZ2_bzDecompress(&bzs)) == BZ_OK && bzs.avail_in > 0) { /* compression is better then 2:1, need to allocate more memory */ bzs.avail_out = source_len; size = (bzs.total_out_hi32 * (unsigned int) -1) + bzs.total_out_lo32; dest = (char *) Util::safe_realloc(dest, bzs.avail_out + 1); bzs.next_out = dest + size; } if (error == BZ_STREAM_END || error == BZ_OK) { size = (bzs.total_out_hi32 * (unsigned int) -1) + bzs.total_out_lo32; dest = (char *)Util::safe_realloc(dest, size + 1); dest[size] = '\0'; String ret = String(dest, size, AttachString); BZ2_bzDecompressEnd(&bzs); return ret; } else { free(dest); BZ2_bzDecompressEnd(&bzs); return error; } }
bool c_Memcache::t_add(CStrRef key, CVarRef var, int flag /*= 0*/, int expire /*= 0*/) { INSTANCE_METHOD_INJECTION_BUILTIN(Memcache, Memcache::add); if (key.empty()) { raise_warning("Key cannot be empty"); return false; } String serialized = memcache_prepare_for_storage(var, flag); memcached_return_t ret = memcached_add(&m_memcache, key.c_str(), key.length(), serialized.c_str(), serialized.length(), expire, flag); return (ret == MEMCACHED_SUCCESS); }
Variant f_constant(CStrRef name) { const char *data = name.data(); int len = name.length(); char *colon; if ((colon = (char*)memchr(data, ':', len)) && colon[1] == ':') { // class constant int classNameLen = colon - data; char *constantName = colon + 2; String className(data, classNameLen, CopyString); // translate "self" or "parent" if (className == "self") { String this_class = FrameInjection::GetClassName(true); if (this_class.empty()) { throw FatalErrorException("Cannot access self:: " "when no class scope is active"); } else { className = this_class; } } else if (className == "parent") { String parent_class = FrameInjection::GetParentClassName("constant"); if (parent_class.empty()) { throw FatalErrorException("Cannot access parent"); } else { className = parent_class; } } // taking care of volatile class if (class_exists(className)) { return get_class_constant(className.c_str(), constantName, false); } else { return null; } } else { const ClassInfo::ConstantInfo *cinfo = ClassInfo::FindConstant(name.data()); // system/uniquely defined scalar constant (must be valid) if (cinfo) return cinfo->value; // dynamic/redeclared constant return ((Globals*)get_global_variables())->getConstant(name.data()); } }
bool f_defined(CStrRef name, bool autoload /* = true */) { if (!name.get()) return false; const char *data = name.data(); int len = name.length(); char *colon; if ((colon = (char*)memchr(data, ':', len)) && colon[1] == ':') { // class constant int classNameLen = colon - data; char *constantName = colon + 2; VM::Class* cls = getClassByName(data, classNameLen); if (cls) { String cnsName(constantName, data + len - constantName, CopyString); return cls->clsCnsGet(cnsName.get()); } return false; } else { return autoload ? VM::Unit::loadCns(name.get()) : VM::Unit::lookupCns(name.get()); } }
Variant f_constant(CStrRef name) { if (!name.get()) return uninit_null(); const char *data = name.data(); int len = name.length(); // slice off starting backslash bool hadInitialBackslash = false; if (len > 0 && data[0] == '\\') { data += 1; len -= 1; hadInitialBackslash = true; } char *colon; if ((colon = (char*)memchr(data, ':', len)) && colon[1] == ':') { // class constant int classNameLen = colon - data; char *constantName = colon + 2; Class* cls = getClassByName(data, classNameLen); if (cls) { String cnsName(constantName, data + len - constantName, CopyString); TypedValue* tv = cls->clsCnsGet(cnsName.get()); if (tv) { return tvAsCVarRef(tv); } } raise_warning("Couldn't find constant %s", data); } else { TypedValue* cns; if (hadInitialBackslash) { String s(data, len, CopyString); cns = Unit::loadCns(s.get()); } else { cns = Unit::loadCns(name.get()); } if (cns) return tvAsVariant(cns); } return uninit_null(); }