Stringp ProgramClass::readLine() { AvmCore* core = this->core(); Stringp s = core->kEmptyString; wchar wc[64]; int i=0; for( int c = getchar(); c != '\n' && c != EOF; c = getchar() ) { wc[i++] = (wchar)c; if( i == 63 ) { wc[i] = 0; s = s->append16(wc); i = 0; } } if( i > 0 ) { wc[i] = 0; s = s->append16(wc); } return s; }
ArrayObject* HTTPFormClass::convertForm(std::vector<FormEntry>& vec) { AvmCore *core = this->core(); ArrayObject *out = this->toplevel()->arrayClass->newArray(); for (std::vector<FormEntry>::iterator it=vec.begin(); it!=vec.end(); it++) { ArrayObject* arr; Stringp key = core->internStringUTF8((*it).name.data(), (*it).name.length()); Stringp value = core->internStringUTF8((*it).value.data(), (*it).value.length()); //we have it, append if (out->hasStringProperty(key)) { arr = (ArrayObject*) core->atomToScriptObject(out->getStringProperty(key)); arr->setUintProperty(arr->get_length(), value->atom()); } //create array else { arr = this->toplevel()->arrayClass->newArray(); arr->setUintProperty(0, value->atom()); out->setStringProperty(key, arr->atom()); } } return out; }
Atom ScriptObject::getAtomPropertyFromProtoChain(Atom name, ScriptObject* o, Traits *origObjTraits) const { // todo will delegate always be non-null here? if (o != NULL) { Atom searchname = name; Stringp s = core()->atomToString(name); AvmAssert(s->isInterned()); Atom ival = s->getIntAtom(); if (ival) { searchname = ival; } do { // ensure prototype is dynamic if (!o->vtable->traits->getHashtableOffset()) continue; Atom const value = o->getTable()->getNonEmpty(searchname); if (!InlineHashtable::isEmpty(value)) return value; } while ((o = o->delegate) != NULL); } // NOTE use default public since name is not used Multiname multiname(core()->getAnyPublicNamespace(), AvmCore::atomToString(name)); toplevel()->throwReferenceError(kReadSealedError, &multiname, origObjTraits); // unreached return undefinedAtom; }
Stringp StringClass::AS3_fromCharCode(Atom *argv, int argc) { AvmCore* core = this->core(); Stringp out = core->kEmptyString; for (int i=0; i<argc; i++) { wchar c = wchar(AvmCore::integer(argv[i])); if (c <= 0xff) { // append16 will always append as k16, forcing the string // to be widened, as String::_append doesn't understand kAuto. // That can/should probably be smarted, but for now, // improve the smarts here: uint8_t c8 = uint8_t(c); out = out->appendLatin1((char*)&c8, 1); } else { // note: this code is allowed to construct a string // containing illegal UTF16 sequences! // (eg, String.fromCharCode(0xD800).charCodeAt(0) -> 0xD800). out = out->append16(&c, 1); } } return out; }
void ST_avmplus_basics::test5() { Stringp s = core->newConstantStringLatin1("ev\xADident"); bool matches1 = s->matchesLatin1("\xADi", 2, 2); #line 73 "ST_avmplus_basics.st" verifyPass(matches1 == true, "matches1 == true", __FILE__, __LINE__); }
/** * traverse the delegate chain looking for a value. * [ed] it's okay to look only at the HT's in the delegate chain because * delegate values may only be instances of Object. They cannot be objects * with slots. We don't need to look at traits at each step. * todo - enforce this rule * @param name * @return */ Atom ScriptObject::getAtomProperty(Atom name) const { if (!traits()->needsHashtable()) { return getAtomPropertyFromProtoChain(name, delegate, traits()); } else { Stringp s = core()->atomToString(name); AvmAssert(s->isInterned()); Atom ival = s->getIntAtom(); if (ival) { name = ival; } // dynamic lookup on this object const ScriptObject *o = this; do { // ensure prototype is dynamic if (!o->vtable->traits->getHashtableOffset()) continue; Atom const value = o->getTable()->getNonEmpty(name); if (!InlineHashtable::isEmpty(value)) return value; } while ((o = o->delegate) != NULL); return undefinedAtom; } }
void SystemClass::trace(ArrayObject* a) { if (!a) toplevel()->throwArgumentError(kNullArgumentError, "array"); AvmCore* core = this->core(); PrintWriter& console = core->console; for (int i=0, n = a->getLength(); i < n; i++) { if (i > 0) console << ' '; Stringp s = core->string(a->getUintProperty(i)); for (int j = 0; j < s->length(); j++) { wchar c = (*s)[j]; // '\r' gets converted into '\n' // '\n' is left alone // '\r\n' is left alone if (c == '\r') { if (((j+1) < s->length()) && (*s)[j+1] == '\n') { console << '\r'; j++; } console << '\n'; } else { console << c; } } } console << '\n'; }
void ST_avmplus_basics::test4() { Stringp s = core->newConstantStringLatin1("ev\xADident"); int index = s->indexOfLatin1("\xAD"); #line 68 "ST_avmplus_basics.st" verifyPass(index == 2, "index == 2", __FILE__, __LINE__); }
void Debugger::traceMethod(MethodInfo* fnc, bool ignoreArgs) { if (in_trace) return; in_trace = true; // callback trace if (trace_callback && fnc && astrace_callback > TRACE_OFF) traceCallback(0); if (astrace_console > TRACE_OFF) { if (fnc) { // WARNING: don't change the format of output since outside utils depend on it uint64_t delta = VMPI_getTime() - astraceStartTime; core->console << (uint32)(delta) << " AVMINF: MTHD "; Stringp fname = fnc->getMethodName(); if (fname && (fname->length() > 0) ) core->console << fname; else core->console << "<unknown>"; core->console << " ("; if (!ignoreArgs && core->callStack && (astrace_console == TRACE_METHODS_WITH_ARGS || astrace_console == TRACE_METHODS_AND_LINES_WITH_ARGS)) core->console << traceArgumentsString(); core->console << ")\n"; } } in_trace = false; }
void Debugger::traceCallback(int line) { if (!(core->callStack && core->callStack->env())) return; Stringp file = ( core->callStack->filename() ) ? Stringp(core->callStack->filename()) : Stringp(core->kEmptyString); Stringp name = core->kEmptyString; Stringp args = core->kEmptyString; MethodEnv* env = core->callStack->env(); if (env->method) { // normally, getMethodName omits nonpublic namespaces, but for this purpose, // we want to include all namespaces. const bool includeAllNamespaces = true; name = env->method->getMethodName(includeAllNamespaces); if (!name) name = core->kEmptyString; if ((line == 0) && (astrace_callback == TRACE_METHODS_WITH_ARGS || astrace_callback == TRACE_METHODS_AND_LINES_WITH_ARGS)) args = traceArgumentsString(); } Atom argv[5] = { trace_callback->atom(), file->atom(), core->intToAtom(line), name->atom(), args->atom() }; int argc = 4; TRY(core, kCatchAction_ReportAsError) { trace_callback->call(argc, argv); }
Stringp ProgramClass::_popenRead(Stringp command) { if( !command ) { toplevel()->throwArgumentError(kNullArgumentError, "command"); } StUTF8String commandUTF8(command); FILE *read_fp; char buffer[BUFSIZ + 1]; int chars_read; VMPI_memset(buffer, '\0', sizeof(buffer)); read_fp = VMPI_popen(commandUTF8.c_str(), "r"); Stringp output = core()->newStringUTF8( "" ); if (read_fp != NULL) { chars_read = (int) fread(buffer, sizeof(char), BUFSIZ, read_fp); output = output->append( core()->newStringUTF8(buffer, chars_read) ); while(chars_read > 0) { buffer[chars_read - 1] = '\0'; chars_read = (int) fread(buffer, sizeof(char), BUFSIZ, read_fp); output = output->append( core()->newStringUTF8(buffer, chars_read) ); } VMPI_pclose(read_fp); return output; } return NULL; }
int RegExpObject::Utf16ToUtf8Index(Stringp utf16String, UTF8String *utf8String, int utf16Index) { int utf16Length = utf16String->length(); int utf8Length = utf8String->length(); // If the UTF-16 and UTF-8 strings contain the same number of // characters, the string is plain ASCII and no conversion is needed. if (utf16Length == utf8Length) { return utf16Index; } // If the UTF-16 index is out of range, do nothing. if (utf16Index < 0 || utf16Index > utf16Length) { return utf16Index; } return UnicodeUtils::Utf16ToUtf8(utf16String->c_str(), utf16Index, NULL, 0); }
void ST_avmplus_basics::test3() { Stringp s = core->newConstantStringLatin1("ev\xADident"); bool found = s->containsLatin1("\xAD"); #line 63 "ST_avmplus_basics.st" verifyPass(found == true, "found == true", __FILE__, __LINE__); }
/*static*/ Stringp VectorClass::makeVectorClassName(AvmCore* core, Traits* t) { Stringp s = core->newConstantStringLatin1("Vector.<"); s = s->append(t->formatClassName()); s = s->append(core->newConstantStringLatin1(">")); // all callers want it interned, so let's do it here return core->internString(s); }
Atom ScriptObject::getUintProperty(uint32_t i) const { // N.B.: a key present in ScriptObject must be interned string; // thus uninterned implies absent (cf. bugzilla 556023). AvmCore* core = this->core(); if (!(i&MAX_INTEGER_MASK)) { if (!traits()->needsHashtable()) { Stringp interned; bool present = core->isInternedUint(i, &interned); if (present) { Atom name = interned->atom(); return getAtomPropertyFromProtoChain(name, delegate, traits()); } else { return undefinedAtom; } } else { // dynamic lookup on this object Atom name = core->uintToAtom (i); const ScriptObject *o = this; do { // ensure prototype is dynamic if (!o->vtable->traits->getHashtableOffset()) continue; Atom const value = o->getTable()->getNonEmpty(name); if (!InlineHashtable::isEmpty(value)) return value; } while ((o = o->delegate) != NULL); return undefinedAtom; } } else { Stringp interned; bool present; present = core->isInternedUint(i, &interned); if (present) { return getAtomProperty(interned->atom()); } else { return undefinedAtom; } } }
void ST_avmplus_basics::test6() { Stringp s = core->newConstantStringLatin1("ev\xADident"); bool matches2 = s->matchesLatin1_caseless("\xADIDENT", 2, 2); #line 78 "ST_avmplus_basics.st" verifyPass(matches2 == true, "matches2 == true", __FILE__, __LINE__); }
/* This provides backwards-compatibility for a rather obscure case: The old XMLParser considered any null terminator to end the parse, regardless of actual string length. Some buggy SWFs take a random ByteArray and try to convert it to XML. The old parser would stop parsing at the first null, but the new one won't, and thus is much likely to throw an exception (since random binary rarely parses as XML), while the old one would return quietly if there happened to be a null character before the first '<' character. Rather than add null-char checking back into the parser, let's just do a quick pre-check for a null char, and if one is found, truncate the string there. (Watson #2471228) */ static Stringp truncateAtFirstNullChar(AvmCore* core, Stringp in) { int32_t const pos = in->indexOfCharCode(0); if (pos > 0) { in = in->substr(0, pos); } else if (pos == 0) { in = core->kEmptyString; } return in; }
// !!@ I'm not sure what this was supposed to do originally but I've rewritten it // to remove the leading and trailing white space for text elements. // " 5 4 3 " becomes "5 4 3" // This is to simulate the E4X XML parser static Stringp _condenseWhitespace(Stringp text) { StringIndexer str(text); // leading space int32_t start = 0; while (start < text->length() && String::isSpace(str[start])) start++; // trailing space int32_t end = text->length() - 1; while ((end > start) && String::isSpace(str[end])) end--; return text->substring(start, end + 1); }
static Stringp getStackTraceLine(MethodInfo* method, Stringp filename) { AvmCore *core = method->pool()->core; Stringp s = core->newStringLatin1("\tat "); s = core->concatStrings(s, method->format(core)); if (filename) { s = s->appendLatin1("["); s = s->append(filename); s = s->appendLatin1(":"); } return s; }
Stringp FileClass::read(Stringp filename) { Toplevel* toplevel = this->toplevel(); AvmCore* core = this->core(); if (!filename) { toplevel->throwArgumentError(kNullArgumentError, "filename"); } UTF8String* filenameUTF8 = filename->toUTF8String(); FILE *fp = fopen(filenameUTF8->c_str(), "r"); if (fp == NULL) { toplevel->throwError(kFileOpenError, filename); } fseek(fp, 0L, SEEK_END); long len = ftell(fp); #ifdef UNDER_CE fseek (fp, 0L, SEEK_SET); #else rewind(fp); #endif unsigned char *c = new unsigned char[len+1]; len = (long)fread(c, 1, len, fp); c[len] = 0; fclose(fp); if (len >= 3) { // UTF8 BOM if ((c[0] == 0xef) && (c[1] == 0xbb) && (c[2] == 0xbf)) { return core->newString(((char *)c) + 3, len - 3); } else if ((c[0] == 0xfe) && (c[1] == 0xff)) { //UTF-16 big endian c += 2; len = (len - 2) >> 1; Stringp out = new (core->GetGC()) String(len); wchar *buffer = out->lockBuffer(); for (long i = 0; i < len; i++) { buffer[i] = (c[0] << 8) + c[1]; c += 2; } out->unlockBuffer(); return out; } else if ((c[0] == 0xff) && (c[1] == 0xfe))
short TextFormatAlignClass::StringToID(Stringp s) { if(s->equals(getSlotLEFT())) return stextAlignLeft; else if(s->equals(getSlotRIGHT())) return stextAlignRight; else if(s->equals(getSlotCENTER())) return stextAlignCenter; else if(s->equals(getSlotJUSTIFY())) return stextAlignJustify; else if(s->equals(getSlotEND())) return stextAlignEnd; else return stextAlignStart; }
// Dump a filename. The incoming filename is of the form // "C:\path\to\package\root;package/package;filename". The path format // will depend on the platform on which the movie was originally // compiled, NOT the platform the the player is running in. // // We want to replace the semicolons with path separators. We'll take // a guess at the appropriate path separator of the compilation // platform by looking for any backslashes in the path. If there are // any, then we'll assume backslash is the path separator. If not, // we'll use forward slash. void StackTrace::dumpFilename(Stringp filename, PrintWriter& out) const { wchar semicolonReplacement = '/'; int length = filename->length(); wchar ch; int i; // look for backslashes; if there are any, then semicolons will be // replaced with backslashes, not forward slashes for (i=0; i<length; ++i) { ch = (*filename)[i]; if (ch == '\\') { semicolonReplacement = '\\'; break; } } // output the entire path bool previousWasSlash = false; for (i=0; i<length; ++i) { ch = (*filename)[i]; if (ch == ';') { if (previousWasSlash) continue; ch = semicolonReplacement; previousWasSlash = true; } else if (ch == '/' || ch == '\\') { previousWasSlash = true; } else { previousWasSlash = false; } out << ch; } }
void DebugCLI::setCurrentSource(Stringp file) { if (!file) return; currentFile = file; if (currentSource) { delete [] currentSource; currentSource = NULL; currentSourceLen = 0; } // Open this file and suck it into memory StUTF8String currentFileUTF8(currentFile); FileInputStream f(currentFileUTF8.c_str()); if (f.valid() && ((uint64_t)file->length() < UINT32_T_MAX)) { //cannot handle files > 4GB currentSourceLen = (uint32_t) f.available(); currentSource = new char[currentSourceLen+1]; f.read(currentSource, currentSourceLen); currentSource[currentSourceLen] = 0; // whip through converting \r\n to space \n for(int64_t i=0; i<currentSourceLen-1;i++) { if (currentSource[i] == '\r' && currentSource[i+1] == '\n') currentSource[i] = ' '; } } else if (warnMissingSource) { core->console << "Could not find '" << currentFile << "'. Try running in the same directory as the .as file.\n"; warnMissingSource = false; } }
ScriptObject* TypeDescriber::describeMetadataInfo(PoolObject* pool, uint32_t metadata_index) { AvmCore* core = m_toplevel->core(); const uint8_t* metadata_pos = pool->metadata_infos[metadata_index]; const uint32_t name_index = (metadata_pos) ? AvmCore::readU30(metadata_pos) : 0; // A bit of a hack: if the pool is builtin, always omit metadata chunks with names of "Version" // or "native", since these are used for reserved purposes internally. Stringp name = poolstr(pool, name_index); AvmAssert(name->isInterned() && core->kVersion->isInterned() && str(kstrid_native)->isInterned()); if (pool->isBuiltin && (name == core->kVersion || name == str(kstrid_native))) return NULL; const uint32_t val_count = (metadata_pos) ? AvmCore::readU30(metadata_pos) : 0; ScriptObject* o = new_object(); ArrayObject* a = new_array(); if (val_count > 0) { GC* gc = core->GetGC(); List<uint32_t> key_indexes(gc); List<uint32_t> val_indexes(gc); read_u30_list(key_indexes, val_count, metadata_pos); read_u30_list(val_indexes, val_count, metadata_pos); for (uint32_t i = 0; i < val_count; ++i) { ScriptObject* v = new_object(); const KVPair props[] = { { kstrid_key, strAtom(poolstr(pool, key_indexes.get(i))) }, { kstrid_value, strAtom(poolstr(pool, val_indexes.get(i))) }, }; setpropmulti(v, props, elem_count(props)); pushobj(a, v); } } const KVPair props[] = { { kstrid_name, strAtom(name) }, { kstrid_value, objAtom(a) }, }; setpropmulti(o, props, elem_count(props)); return o; }
PrintWriter& PrintWriter::operator<< (percent value) { if (value.getPercent() < 10) { *this << ' '; } Stringp s = MathUtils::convertDoubleToString(m_core, value.getPercent()); StringIndexer str(s); for (int32_t i = 0; i < s->length(); i++) { wchar ch = str[i]; *this << ch; if (ch == '.' && i < s->length() - 1) { *this << str[++i]; break; } } return *this; }
void ScriptObject::setAtomPropertyIsEnumerable(Atom name, bool enumerable) { if (traits()->needsHashtable()) { Stringp s = core()->atomToString(name); AvmAssert(s->isInterned()); Atom ival = s->getIntAtom(); if (ival) { name = ival; } getTable()->setAtomPropertyIsEnumerable(name, enumerable); } else { throwWriteSealedError(name); } }
Atom VectorClass::applyTypeArgs(int argc, Atom* argv) { //Vector only takes 1 type argument AvmAssert(argc==1); if (argc != 1) { toplevel()->typeErrorClass()->throwError(kWrongTypeArgCountError, traits()->formatClassName(), core()->toErrorString(1), core()->toErrorString(argc)); } Atom type = argv[0]; AvmCore* core = this->core(); if (ISNULL(type)) return toplevel()->objectVectorClass->atom(); if (atomKind(type) != kObjectType) toplevel()->throwVerifyError(kCorruptABCError); ScriptObject* so = AvmCore::atomToScriptObject(type); if (so == toplevel()->intClass) return toplevel()->intVectorClass->atom(); else if (so == toplevel()->numberClass) return toplevel()->doubleVectorClass->atom(); else if (so == toplevel()->uintClass) return toplevel()->uintVectorClass->atom(); Traits* param_traits = so->vtable->ivtable->traits; Stringp fullname = VectorClass::makeVectorClassName(core, param_traits); if (!instantiated_types->contains(fullname->atom())) { VTable* vtab = this->vtable->newParameterizedVTable(param_traits, fullname); ObjectVectorClass* new_type = new (vtab->gc(), vtab->getExtraSize()) ObjectVectorClass(vtab); new_type->index_type = (ClassClosure*)AvmCore::atomToScriptObject(type); new_type->setDelegate(toplevel()->classClass->prototype); // Is this right? Should each instantiation get its own prototype? new_type->prototype = toplevel()->objectVectorClass->prototype; instantiated_types->add(fullname->atom(), new_type->atom()); } return (Atom)instantiated_types->get(fullname->atom()); }
bool ScriptObject::deleteAtomProperty(Atom name) { if (traits()->needsHashtable()) { Stringp s = core()->atomToString(name); AvmAssert(s->isInterned()); Atom ival = s->getIntAtom(); if (ival) { name = ival; } getTable()->remove(name); return true; } else { return false; } }
bool ScriptObject::getAtomPropertyIsEnumerable(Atom name) const { if (traits()->needsHashtable()) { Stringp s = core()->atomToString(name); AvmAssert(s->isInterned()); Atom ival = s->getIntAtom(); if (ival) { name = ival; } return getTable()->getAtomPropertyIsEnumerable(name); } else { // ISSUE should this walk the proto chain? return false; } }
Stringp ScopeChain::format(AvmCore* core) const { Stringp r = core->kEmptyString; r = r->appendLatin1("SC:{dxns=("); r = r->append(_defaultXmlNamespace->format(core)); r = r->appendLatin1("),"); r = r->append(_scopeTraits->format(core)); r = r->appendLatin1(",V:["); for (int i = 0; i < _scopeTraits->size; i++) { if (i > 0) r = r->appendLatin1(","); r = r->append(core->format(_scopes[i])); } r = r->appendLatin1("]}"); return r; }