VError VJSONWriter::StringifyArray( const VJSONArray *inArray, VString& outString) { VError err = VE_OK; if (inArray == NULL) { outString = VJSONValue::sUndefinedString; } else if (inArray->IsEmpty()) { outString = "[]"; } else { IncrementLevel(); VectorOfVString array; size_t count = inArray->GetCount(); try { array.resize( count); } catch(...) { err = vThrowError( VE_MEMORY_FULL); } VectorOfVString::iterator j = array.begin(); for( size_t i = 0 ; (i < count) && (err == VE_OK) ; ++i, ++j) { err = StringifyValue( (*inArray)[i], *j); InsertIndentString( *j); } DecrementLevel(); if (err == VE_OK) { array.front().Insert( '[', 1); AppendIndentString( array.back()); array.back().AppendUniChar( ']'); err = outString.Join( array, ',') ? VE_OK : vThrowError( VE_STRING_ALLOC_FAILED); } } return err; }
VError VJSONWriter::StringifyObject( const VJSONObject *inObject, VString& outString) { if (inObject == NULL) { outString = VJSONValue::sUndefinedString; return VE_OK; } if (std::find( fStack.begin(), fStack.end(), inObject) != fStack.end()) { return vThrowError( VE_JSON_STRINGIFY_CIRCULAR); } VError err = VE_OK; fStack.push_back( inObject); if (!inObject->DoStringify( outString, *this, &err)) { if (inObject->fMap.empty()) { outString = "{}"; } else { IncrementLevel(); VectorOfVString array; array.resize( inObject->fMap.size()); VectorOfVString::iterator j = array.begin(); for( VJSONPropertyConstIterator i( inObject) ; i.IsValid() && (err == VE_OK) ; ++i, ++j) { err = i.GetName().GetJSONString( *j, GetOptions()); if (err == VE_OK) { InsertIndentString( *j); VString value; err = StringifyValue( i.GetValue(), value); if (err == VE_OK) { j->AppendUniChar( ':'); j->AppendString( value); } } } DecrementLevel(); if (err == VE_OK) { array.front().Insert( '{', 1); AppendIndentString( array.back()); array.back().AppendUniChar( '}'); err = outString.Join( array, ',') ? VE_OK : vThrowError( VE_STRING_ALLOC_FAILED); } } } fStack.pop_back(); return err; }
bool HTMLLexer::ConsumePossibleEntity( VString &outEntityConsumed, UniChar &outCharacterToAdd ) { if (!fLexerInput->HasMoreChars()) return false; xbox_assert( fLexerInput->PeekAtNextChar() == CHAR_AMPERSAND ); // In HTML, escape sequences come in one of three forms: // &#DDDD; (where D is decimal number) // &#xHHHH; (where H is hexidecimal number -- case insensitive) // &entity; (where entity is a common entity reference) // We've already read the ampersand, so now we want to figure out which of // the three cases we're dealing with. If we don't match any of the three // cases, then we just assume we really had regular text and the user just // screwed up. // Consume the current character to see what sort of escape sequence we're dealing with fLexerInput->MoveToNextChar(); // Eat the & if (!fLexerInput->HasMoreChars()) { fLexerInput->MoveToPreviousChar(); return false; } UniChar escapeType = fLexerInput->MoveToNextChar(); sLONG charactersToRevert = 2; outEntityConsumed = "&"; outEntityConsumed.AppendUniChar( escapeType ); switch (escapeType) { case CHAR_NUMBER_SIGN: { // We either have a hex literal or a decimal literal following the # sign. So we // will check to see which we've got and go from there if (!fLexerInput->HasMoreChars()) break; UniChar literalType = fLexerInput->MoveToNextChar(); outEntityConsumed.AppendUniChar( literalType ); charactersToRevert++; switch (literalType) { case CHAR_LATIN_CAPITAL_LETTER_X: case CHAR_LATIN_SMALL_LETTER_X: { // We now want to add any number of hex digits to the stream. Though, if we go over // four hex digits, then we're outside of the range of any legal unicode code point, and // so I am going to do a hard-coded stop there. unsigned short value = 0; for (sLONG i = 0; i < 4; i++) { UniChar c = CHAR_CONTROL_0000; if (fLexerInput->HasMoreChars()) { c = fLexerInput->MoveToNextChar(); charactersToRevert++; if (!isHexDigit( c )) break; // Now we want to add the hex digit we got into our ultimate value value += sixteenToThePowerOf( i ) * getHexValueFromCharacter( c ); outEntityConsumed.AppendUniChar( c ); } else break; } // The last character needs to be a semi-colon, or else it's not a legal entity if (!fLexerInput->HasMoreChars()) break; if (fLexerInput->MoveToNextChar() != CHAR_SEMICOLON) { charactersToRevert++; break; } outEntityConsumed.AppendUniChar( ';' ); // Add the value as a UniChar to our stream outCharacterToAdd = (UniChar)value; return true; } break; default: { // We want to test to see whether the character we read is a legal decimal digit. If it // is, then we have a character literal. If not, the user screwed up and we can just bail. if (isDecimalDigit( literalType )) { // We're going to put the character back just to parse it again. It makes the logic easier fLexerInput->MoveToPreviousChar(); // We know that we've got some digits we care about. Now we need to find out how many, // and we'll put the cap at something sensible, like 5 characters (which can cover all of // the unicode code points in existence). unsigned short value = 0; for (sLONG i = 0; i < 5; i++) { UniChar c = CHAR_CONTROL_0000; if (fLexerInput->HasMoreChars()) { c = fLexerInput->MoveToNextChar(); charactersToRevert++; if (!isDecimalDigit( c )) break; // Now we want to add the decimal digit we got into our ultimate value value += tenToThePowerOf( i ) * (c - '0'); outEntityConsumed.AppendUniChar( c ); } else break; } // The last character needs to be a semi-colon, or else it's not a legal entity if (!fLexerInput->HasMoreChars()) break; if (fLexerInput->MoveToNextChar() != CHAR_SEMICOLON) { charactersToRevert++; break; } outEntityConsumed.AppendUniChar( ';' ); // Add the value as a UniChar to our stream outCharacterToAdd = (UniChar)value; return true; } else break; } break; } } break; default: { // We found an ampersand and know it's not a numeric literal. Now we need to see whether it's an // entity made to be a bit more human readable. We're going to grab a bunch of characters from the // stream without actually shifting them in. We cut them off at the semi-colon because all entities // must end with one to be legal. Then, if it matches a known entity, we're set -- otherwise it's just // a stream of random characters. We need a whopping nine character to be able to support ϑ VString entityName; fLexerInput->GetSubString( fLexerInput->GetCurrentPosition(), 9, entityName ); // Now, let's see where the semi-colon is, and strip it off (as well as everything past it). If we don't // find a semi-colon, then we know we don't have an entity VectorOfVString subStrs; if (!entityName.GetSubStrings( CHAR_SEMICOLON, subStrs )) break; // The first sub string is the entity name we care about if (GetEntityValue( subStrs.front(), outCharacterToAdd )) { // We want to eat up as many characters as the entity was consuming VIndex size = subStrs.front().GetLength(); for (VIndex i = 0; i < size; i++) { outEntityConsumed.AppendUniChar( fLexerInput->MoveToNextChar() ); } return true; } } break; } // Put back the characters we screwed up on for (sLONG i = 0; i < charactersToRevert; i++) fLexerInput->MoveToPreviousChar(); return false; }