NS_IMETHODIMP nsSaveAsCharset::DoConversionFallBack(PRUint32 inUCS4, char *outString, PRInt32 bufferLength) { NS_ASSERTION(outString, "invalid input"); if(nullptr == outString ) return NS_ERROR_NULL_POINTER; *outString = '\0'; nsresult rv = NS_OK; if (ATTR_NO_FALLBACK(mAttribute)) { return NS_OK; } if (attr_EntityAfterCharsetConv == MASK_ENTITY(mAttribute)) { char *entity = NULL; rv = mEntityConverter->ConvertUTF32ToEntity(inUCS4, mEntityVersion, &entity); if (NS_SUCCEEDED(rv)) { if (NULL == entity || (PRInt32)strlen(entity) > bufferLength) { return NS_ERROR_OUT_OF_MEMORY; } PL_strcpy(outString, entity); nsMemory::Free(entity); return rv; } } switch (MASK_FALLBACK(mAttribute)) { case attr_FallbackQuestionMark: if(bufferLength>=2) { *outString++='?'; *outString='\0'; rv = NS_OK; } else { rv = NS_ERROR_FAILURE; } break; case attr_FallbackEscapeU: if (inUCS4 & 0xff0000) rv = (PR_snprintf(outString, bufferLength, "\\u%.6x", inUCS4) > 0) ? NS_OK : NS_ERROR_FAILURE; else rv = (PR_snprintf(outString, bufferLength, "\\u%.4x", inUCS4) > 0) ? NS_OK : NS_ERROR_FAILURE; break; case attr_FallbackDecimalNCR: rv = ( PR_snprintf(outString, bufferLength, "&#%u;", inUCS4) > 0) ? NS_OK : NS_ERROR_FAILURE; break; case attr_FallbackHexNCR: rv = (PR_snprintf(outString, bufferLength, "&#x%x;", inUCS4) > 0) ? NS_OK : NS_ERROR_FAILURE; break; case attr_FallbackNone: rv = NS_OK; break; default: rv = NS_ERROR_ILLEGAL_VALUE; break; } return rv; }
NS_IMETHODIMP nsSaveAsCharset::Convert(const PRUnichar *inString, char **_retval) { if (nullptr == _retval) return NS_ERROR_NULL_POINTER; if (nullptr == inString) return NS_ERROR_NULL_POINTER; if (0 == *inString) return NS_ERROR_ILLEGAL_VALUE; nsresult rv = NS_OK; NS_ASSERTION(mEncoder, "need to call Init() before Convert()"); NS_ENSURE_TRUE(mEncoder, NS_ERROR_FAILURE); *_retval = nullptr; // make sure to start from the first charset in the list if (mCharsetListIndex > 0) { mCharsetListIndex = -1; rv = SetupUnicodeEncoder(GetNextCharset()); NS_ENSURE_SUCCESS(rv, rv); } do { // fallback to the next charset in the list if the last conversion failed by an unmapped character if (MASK_CHARSET_FALLBACK(mAttribute) && NS_ERROR_UENC_NOMAPPING == rv) { const char * charset = GetNextCharset(); if (!charset) break; rv = SetupUnicodeEncoder(charset); NS_ENSURE_SUCCESS(rv, rv); PR_FREEIF(*_retval); } if (attr_EntityBeforeCharsetConv == MASK_ENTITY(mAttribute)) { NS_ASSERTION(mEntityConverter, "need to call Init() before Convert()"); NS_ENSURE_TRUE(mEntityConverter, NS_ERROR_FAILURE); PRUnichar *entity = nullptr; // do the entity conversion first rv = mEntityConverter->ConvertToEntities(inString, mEntityVersion, &entity); if(NS_SUCCEEDED(rv)) { rv = DoCharsetConversion(entity, _retval); nsMemory::Free(entity); } } else rv = DoCharsetConversion(inString, _retval); } while (MASK_CHARSET_FALLBACK(mAttribute) && NS_ERROR_UENC_NOMAPPING == rv); return rv; }
NS_IMETHODIMP nsSaveAsCharset::Init(const char *charset, uint32_t attr, uint32_t entityVersion) { nsresult rv = NS_OK; mAttribute = attr; mEntityVersion = entityVersion; rv = SetupCharsetList(charset); NS_ENSURE_SUCCESS(rv, rv); // set up unicode encoder rv = SetupUnicodeEncoder(GetNextCharset()); NS_ENSURE_SUCCESS(rv, rv); // set up entity converter if (attr_EntityNone != MASK_ENTITY(mAttribute) && !mEntityConverter) mEntityConverter = do_CreateInstance(NS_ENTITYCONVERTER_CONTRACTID, &rv); return rv; }