//------------------------------------------------------------------------ bool StringListParameter::fromString (const TChar* string, ParamValue& _valueNormalized) const { int32 index = 0; for (StringVector::const_iterator it = strings.begin (), end = strings.end (); it != end; ++it, ++index) { if (strcmp16 (*it, string) == 0) { _valueNormalized = toNormalized ((ParamValue)index); return true; } } return false; }
status_t parseStyledString(Bundle* bundle, const char* fileName, ResXMLTree* inXml, const String16& endTag, String16* outString, Vector<StringPool::entry_style_span>* outSpans, bool pseudolocalize) { Vector<StringPool::entry_style_span> spanStack; String16 curString; String16 rawString; const char* errorMsg; int xliffDepth = 0; bool firstTime = true; size_t len; ResXMLTree::event_code_t code; while ((code=inXml->next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) { if (code == ResXMLTree::TEXT) { String16 text(inXml->getText(&len)); if (firstTime && text.size() > 0) { firstTime = false; if (text.string()[0] == '@') { // If this is a resource reference, don't do the pseudoloc. pseudolocalize = false; } } if (xliffDepth == 0 && pseudolocalize) { std::string orig(String8(text).string()); std::string pseudo = pseudolocalize_string(orig); curString.append(String16(String8(pseudo.c_str()))); } else { curString.append(text); } } else if (code == ResXMLTree::START_TAG) { const String16 element16(inXml->getElementName(&len)); const String8 element8(element16); size_t nslen; const uint16_t* ns = inXml->getElementNamespace(&nslen); if (ns == NULL) { ns = (const uint16_t*)"\0\0"; nslen = 0; } const String8 nspace(String16(ns, nslen)); if (nspace == XLIFF_XMLNS) { const int N = sizeof(ALLOWED_XLIFF_ELEMENTS)/sizeof(ALLOWED_XLIFF_ELEMENTS[0]); for (int i=0; i<N; i++) { if (element8 == ALLOWED_XLIFF_ELEMENTS[i]) { xliffDepth++; // in this case, treat it like it was just text, in other words, do nothing // here and silently drop this element goto moveon; } } { SourcePos(String8(fileName), inXml->getLineNumber()).error( "Found unsupported XLIFF tag <%s>\n", element8.string()); return UNKNOWN_ERROR; } moveon: continue; } if (outSpans == NULL) { SourcePos(String8(fileName), inXml->getLineNumber()).error( "Found style tag <%s> where styles are not allowed\n", element8.string()); return UNKNOWN_ERROR; } if (!ResTable::collectString(outString, curString.string(), curString.size(), false, &errorMsg, true)) { SourcePos(String8(fileName), inXml->getLineNumber()).error("%s (in %s)\n", errorMsg, String8(curString).string()); return UNKNOWN_ERROR; } rawString.append(curString); curString = String16(); StringPool::entry_style_span span; span.name = element16; for (size_t ai=0; ai<inXml->getAttributeCount(); ai++) { span.name.append(String16(";")); const char16_t* str = inXml->getAttributeName(ai, &len); span.name.append(str, len); span.name.append(String16("=")); str = inXml->getAttributeStringValue(ai, &len); span.name.append(str, len); } //printf("Span: %s\n", String8(span.name).string()); span.span.firstChar = span.span.lastChar = outString->size(); spanStack.push(span); } else if (code == ResXMLTree::END_TAG) { size_t nslen; const uint16_t* ns = inXml->getElementNamespace(&nslen); if (ns == NULL) { ns = (const uint16_t*)"\0\0"; nslen = 0; } const String8 nspace(String16(ns, nslen)); if (nspace == XLIFF_XMLNS) { xliffDepth--; continue; } if (!ResTable::collectString(outString, curString.string(), curString.size(), false, &errorMsg, true)) { SourcePos(String8(fileName), inXml->getLineNumber()).error("%s (in %s)\n", errorMsg, String8(curString).string()); return UNKNOWN_ERROR; } rawString.append(curString); curString = String16(); if (spanStack.size() == 0) { if (strcmp16(inXml->getElementName(&len), endTag.string()) != 0) { SourcePos(String8(fileName), inXml->getLineNumber()).error( "Found tag %s where <%s> close is expected\n", String8(inXml->getElementName(&len)).string(), String8(endTag).string()); return UNKNOWN_ERROR; } break; } StringPool::entry_style_span span = spanStack.top(); String16 spanTag; ssize_t semi = span.name.findFirst(';'); if (semi >= 0) { spanTag.setTo(span.name.string(), semi); } else { spanTag.setTo(span.name); } if (strcmp16(inXml->getElementName(&len), spanTag.string()) != 0) { SourcePos(String8(fileName), inXml->getLineNumber()).error( "Found close tag %s where close tag %s is expected\n", String8(inXml->getElementName(&len)).string(), String8(spanTag).string()); return UNKNOWN_ERROR; } bool empty = true; if (outString->size() > 0) { span.span.lastChar = outString->size()-1; if (span.span.lastChar >= span.span.firstChar) { empty = false; outSpans->add(span); } } spanStack.pop(); /* * This warning seems to be just an irritation to most people, * since it is typically introduced by translators who then never * see the warning. */ if (0 && empty) { fprintf(stderr, "%s:%d: warning: empty '%s' span found in text '%s'\n", fileName, inXml->getLineNumber(), String8(spanTag).string(), String8(*outString).string()); } } else if (code == ResXMLTree::START_NAMESPACE) { // nothing } } if (code == ResXMLTree::BAD_DOCUMENT) { SourcePos(String8(fileName), inXml->getLineNumber()).error( "Error parsing XML\n"); } if (outSpans != NULL && outSpans->size() > 0) { if (curString.size() > 0) { if (!ResTable::collectString(outString, curString.string(), curString.size(), false, &errorMsg, true)) { SourcePos(String8(fileName), inXml->getLineNumber()).error( "%s (in %s)\n", errorMsg, String8(curString).string()); return UNKNOWN_ERROR; } } } else { // There is no style information, so string processing will happen // later as part of the overall type conversion. Return to the // client the raw unprocessed text. rawString.append(curString); outString->setTo(rawString); } return NO_ERROR; }