📄 vxi.cpp
字号:
// be sufficently fast. ExecutionContext::STRINGDEQUE::iterator j; ExecutionContext::STRINGDEQUE & formitems = exe->formitems; for (j = formitems.begin(); j != formitems.end(); ++j) if (*i == *j) break; if (j == formitems.end()) { log->StartDiagnostic(0) << L"VXI::clear_element - user attempted to " L"clear '" << (*i) << L"', but this is not a form item."; log->EndDiagnostic(); continue; } // (3.2) Clear associated counters. exe->promptcounts.Clear(*i); exe->eventcounts.ClearIf(*i, true); exe->script.ClearVar(*i); }}// This implementation returns the values as VXIObjects.//void VXI::exit_element(const VXMLElement & doc){ log->LogDiagnostic(2, L"VXI::exit_element()"); VXIMapHolder exprMap(NULL); vxistring namelist; doc.GetAttribute(ATTRIBUTE_NAMELIST, namelist); if (!namelist.empty()) { exprMap.Acquire(VXIMapCreate()); if (exprMap.GetValue() == NULL) throw VXIException::OutOfMemory(); STRINGDEQUE names; ProcessNameList(namelist, names); STRINGDEQUE::const_iterator i; for (i = names.begin(); i != names.end(); ++i) { VXIValue * val = exe->script.GetValue(*i); if (val != NULL) VXIMapSetProperty(exprMap.GetValue(), (*i).c_str(), val); } } VXIValue * exprResult = NULL; vxistring expr; doc.GetAttribute(ATTRIBUTE_EXPR, expr); if (!expr.empty()) { // To evaluate expressions is a bit more ugly. Because any object may be // returned by the expression, we create a new variable, evaluate it, and // return the result. vxistring variable; VXMLDocumentModel::CreateHiddenVariable(variable); exe->script.MakeVar(variable, expr); exprResult = exe->script.GetValue(variable); } // Now combine the two into one result (if necessary) if (exprMap.GetValue() != NULL && exprResult != NULL) { // We insert the exprResult into the exprMap. VXIMapSetProperty(exprMap.GetValue(), L"Attribute_expr_value", exprResult); exprResult = NULL; } if (exprResult == NULL) exprResult = reinterpret_cast<VXIValue *>(exprMap.Release()); if (log->IsLogging(2)) { log->StartDiagnostic(2) << L"exit_element got \"" << exprResult << L"\""; log->EndDiagnostic(); } pm->PlayAll(); throw VXIException::Exit(exprResult); // Stuff exprResult in here.}void VXI::disconnect_element(const VXMLElement & doc){ log->LogDiagnostic(2, L"VXI::disconnect_element()"); pm->PlayAll(); if (tel->Disconnect(tel) != VXItel_RESULT_SUCCESS) log->LogError(213); throw VXIException::InterpreterEvent(EV_TELEPHONE_HANGUP);}void VXI::reprompt_element(const VXMLElement & doc){ log->LogDiagnostic(2, L"VXI::reprompt_element()"); // set a flag enabling prompting exe->playingPrompts = true;}void VXI::throw_element(const VXMLElement & elem){ vxistring event; elem.GetAttribute(ATTRIBUTE_EVENT, event); if (event.empty()) { elem.GetAttribute(ATTRIBUTE_EVENTEXPR, event); if (!event.empty()) exe->script.EvalScriptToString(event, event); } if (event.empty()) { // This should be caught by the DTD, but just in case... log->LogDiagnostic(0, L"VXI::throw_element - failure, no event to throw"); throw VXIException::InterpreterEvent(EV_ERROR_BAD_THROW); } vxistring message; elem.GetAttribute(ATTRIBUTE_MESSAGE, message); if (message.empty()) { elem.GetAttribute(ATTRIBUTE_MESSAGEEXPR, message); if (!message.empty()) exe->script.EvalScriptToString(message, message); } if (log->IsLogging(2)) { log->StartDiagnostic(2) << L"VXI::throw_element - throwing (" << event << L", " << message << L")"; log->EndDiagnostic(); } throw VXIException::InterpreterEvent(event, message);}// The log element is handled in a slihtly odd manner. The expressions in// attributes are evaluated first because "expressions must be evaluated in// document order". And even if no output is being generated, the expressions// must still be generated.//void VXI::log_element(const VXMLElement & doc){ bool logging = log->IsLogging(1); // (1) Evaluate expressions in attributes first. vxistring attr; VXIValue * expr = NULL; if (doc.GetAttribute(ATTRIBUTE_EXPR, attr)) expr = exe->script.EvalScriptToValue(attr); // (2) Handle main text. bool first = true; std::basic_ostringstream<wchar_t> out; const VXIchar * const SPACE = L" "; for (VXMLNodeIterator it(doc); it; ++it) { VXMLNode child = *it; switch (child.GetType()) { case VXMLNode::Type_VXMLContent: if (first) first = false; else out << SPACE; out << reinterpret_cast<const VXMLContent&>(child).GetValue(); break; case VXMLNode::Type_VXMLElement: { const VXMLElement & elem = reinterpret_cast<const VXMLElement &>(child); if (elem.GetName() == NODE_VALUE) { vxistring value; elem.GetAttribute(ATTRIBUTE_EXPR, value); if (value.empty()) break; try { VXIValue * val = exe->script.EvalScriptToValue(value); if (val != NULL) { if (first) first = false; else out << SPACE; out << val; VXIValueDestroy(&val); } } catch (...) { log->LogEvent(VXIlog_EVENT_LOG_ELEMENT, SimpleLogger::CONTENT, out.str().c_str()); if (logging) log->LogDiagnostic(1, out.str().c_str()); throw; } } break; } default: break; } } if (!out.str().empty()) { log->LogEvent(VXIlog_EVENT_LOG_ELEMENT, SimpleLogger::CONTENT, out.str().c_str()); if (logging) log->LogDiagnostic(1, out.str().c_str()); } // (3) Handle label attribute. if (doc.GetAttribute(ATTRIBUTE_LABEL, attr)) { log->LogEvent(VXIlog_EVENT_LOG_ELEMENT, SimpleLogger::LABEL, attr.c_str()); if (logging) log->LogDiagnostic(1, attr.c_str()); } // (4) Handle expr attribute (if defined) if (expr != NULL) { out.str(L""); out << expr; log->LogEvent(VXIlog_EVENT_LOG_ELEMENT, SimpleLogger::EXPR, out.str().c_str()); if (logging) log->LogDiagnostic(1, out.str().c_str()); VXIValueDestroy(&expr); }}void VXI::if_element(const VXMLElement & doc){ log->LogDiagnostic(2, L"VXI::if_element()"); vxistring cond; doc.GetAttribute(ATTRIBUTE_COND, cond); bool executing = !cond.empty() && exe->script.TestCondition(cond); // Loop through children. // If cond == true, execute until <else> or <elseif> // If cond == false, continue until <else> or <elseif> // and test condition where <else> === <elseif cond="true"> // Control is a little strange since intuitive body of <if> // and <else> are actually siblings of <else> and <elseif>, // not descendants for (VXMLNodeIterator it(doc); it; ++it) { VXMLNode child = *it; // Handle PCDATA as TTS prompts VXMLNode::VXMLNodeType type = child.GetType(); if (type == VXMLNode::Type_VXMLContent) { if (executing) executable_prompt(child); continue; } if (type != VXMLNode::Type_VXMLElement) continue; const VXMLElement & elem = reinterpret_cast<VXMLElement &>(child); VXMLElementType nodeName = elem.GetName(); if (nodeName == NODE_ELSE) { if (executing) return; else executing = true; } else if (nodeName == NODE_ELSEIF) { if (executing) return; vxistring cond; elem.GetAttribute(ATTRIBUTE_COND, cond); executing = !cond.empty() && exe->script.TestCondition(cond); } else if (executing) executable_element(elem); }}// <goto> is identical to submit except// - it can transition to internal items// - doesn't have a namelist//void VXI::goto_element(const VXMLElement & elem){ log->LogDiagnostic(2, L"VXI::goto_element()"); // Clear any information from unprocessed jumps. if (sdParams != NULL) { VXIMapDestroy(&sdParams); sdParams = NULL; } if (sdResult != NULL) { VXIValueDestroy(&sdResult); sdResult = NULL; } // According to the spec, the attributes follow the priority sequence: // next, expr, nextitem, expritem vxistring uri; elem.GetAttribute(ATTRIBUTE_NEXT, uri); if (uri.empty()) { elem.GetAttribute(ATTRIBUTE_EXPR, uri); if (!uri.empty()) exe->script.EvalScriptToString(uri, uri); } if (uri.empty()) { vxistring target; elem.GetAttribute(ATTRIBUTE_NEXTITEM, target); if (target.empty()) { elem.GetAttribute(ATTRIBUTE_EXPRITEM, target); if (!target.empty()) exe->script.EvalScriptToString(target, target); } if (!target.empty()) { DoInnerJump(elem, target); throw VXIException::InterpreterEvent(EV_ERROR_BADFETCH); } } if (uri.empty()) throw VXIException::InterpreterEvent(EV_ERROR_SEMANTIC); DoOuterJump(elem, uri);}void VXI::submit_element(const VXMLElement & elem){ log->LogDiagnostic(2, L"VXI::submit_element()"); // Clear any information from unprocessed jumps. if (sdParams != NULL) { VXIMapDestroy(&sdParams); sdParams = NULL; } if (sdResult != NULL) { VXIValueDestroy(&sdResult); sdResult = NULL; } // Get Submit-specific properties. VXIMapHolder submitData; if (submitData.GetValue() == NULL) throw VXIException::OutOfMemory(); vxistring att; elem.GetAttribute(ATTRIBUTE_NAMELIST, att); if (att.empty()) { ExecutionContext::STRINGDEQUE::const_iterator i; for (i = exe->formitems.begin(); i != exe->formitems.end(); ++i) { // Check for and ignore hidden variables. if (VXMLDocumentModel::IsHiddenVariable(*i)) continue; // Otherwise, add it. VXIValue * val = exe->script.GetValue(*i); if (val != NULL) VXIMapSetProperty(submitData.GetValue(), (*i).c_str(), val); } } else { STRINGDEQUE names; ProcessNameList(att, names); STRINGDEQUE::const_iterator i; for (i = names.begin(); i != names.end(); ++i) { VXIValue * val = exe->script.GetValue(*i); if (val != NULL) VXIMapSetProperty(submitData.GetValue(), (*i).c_str(), val); } } vxistring uri; elem.GetAttribute(ATTRIBUTE_NEXT, uri); if (uri.empty()) { elem.GetAttribute(ATTRIBUTE_EXPR, uri); if (!uri.empty()) exe->script.EvalScriptToString(uri, uri); } // DoOuterJump now owns the submitData. DoOuterJump(elem, uri, submitData.Release(), false);}void VXI::script_element(const VXMLElement & elem){ log->LogDiagnostic(2, L"VXI::script_element()"); // (1) Is the source specified? vxistring uri; elem.GetAttribute(ATTRIBUTE_SRC, uri); // (2) If not, use the content of the script. if (uri.empty()) { for (VXMLNodeIterator it(elem); it; ++it) { VXMLNode child = *it; if (child.GetType() != VXMLNode::Type_VXMLContent) { log->LogDiagnostic(0, L"VXI::script_element - unexpected element"); continue; } VXMLContent & content = reinterpret_cast<VXMLContent &>(child); vxistring str = content.GetValue(); if (!str.empty()) exe->script.EvalScript(str); return; } } // (3) Otherwise, we must retrieve the document. // (3.1) Get the cache attributes and document base. VXIMapHolder fetchobj; exe->properties.GetFetchobjBase(fetchobj); exe->properties.GetFetchobjCacheAttrs(elem, PropertyList::Script, fetchobj); // (3.2) Get the character encoding. vxistring encoding; elem.GetAttribute(ATTRIBUTE_CHARSET, encoding); // (3.3) Get the content. vxistring content; switch (parser->FetchContent(uri.c_str(), fetchobj, inet, *log, encoding, content)) { case -1: // Out of memory throw VXIException::OutOfMemory(); case 0: // Success break; case 1: // Invalid parameter case 2: // Unable to open URI log->LogError(203, SimpleLogger::URI, uri.c_str()); throw VXIException::InterpreterEvent(EV_ERROR_BADFETCH); case 3: // Unable to read from URI log->LogError(204, SimpleLogger::URI, uri.c_str()); throw VXIException::InterpreterEvent(EV_ERROR_BADFETCH); case 4: // Unsupported encoding log->
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -