Bug 770215 - [OS.File] Utilities for strings - Native code. r=froydnj

This commit is contained in:
David Rajchenbach-Teller 2012-08-10 11:52:55 -04:00
parent 7417a56a21
commit 53d7d9861a
2 changed files with 259 additions and 0 deletions

View File

@ -0,0 +1,194 @@
#include "mozilla/Scoped.h"
#include "osfileutils.h"
#include "nsICharsetConverterManager.h"
#include "nsServiceManagerUtils.h"
#include "nsCOMPtr.h"
#include "nsCRTGlue.h"
// Utilities for handling errors
namespace {
#if defined(XP_WIN)
#include <Windows.h>
/**
* Set the OS-specific error to inform the OS that
* the last operation failed because it is not supported.
*/
void error_not_supported() {
SetLastError(ERROR_NOT_SUPPORTED);
}
/**
* Set the OS-specific error to inform the OS that
* the last operation failed because of an invalid
* argument.
*/
void error_invalid_argument() {
SetLastError(ERROR_INVALID_DATA);
}
/**
* Set the OS-specific error to inform the OS that
* the last operation failed because of insufficient
* memory.
*/
void error_no_memory() {
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
}
#else
#include "errno.h"
/**
* Set the OS-specific error to inform the OS that
* the last operation failed because it is not supported.
*/
void error_not_supported() {
errno = ENOTSUP;
}
/**
* Set the OS-specific error to inform the OS that
* the last operation failed because of an invalid
* argument.
*/
void error_invalid_argument() {
errno = EINVAL;
}
/**
* Set the OS-specific error to inform the OS that
* the last operation failed because of insufficient
* memory.
*/
void error_no_memory() {
errno = ENOMEM;
}
#endif // defined(XP_WIN)
}
extern "C" {
// Memory utilities
MOZ_EXPORT_API(void) osfile_ns_free(void* buf) {
NS_Free(buf);
}
// Unicode utilities
MOZ_EXPORT_API(PRUnichar*) osfile_wstrdup(PRUnichar* string) {
return NS_strdup(string);
}
MOZ_EXPORT_API(PRUnichar*) osfile_DecodeAll(
const char* aEncoding,
const char* aSource,
const int32_t aBytesToDecode)
{
if (!aEncoding || !aSource) {
error_invalid_argument();
return nsnull;
}
nsresult rv;
nsCOMPtr<nsICharsetConverterManager> manager =
do_GetService(NS_CHARSETCONVERTERMANAGER_CONTRACTID, &rv);
if (NS_FAILED(rv)) {
error_not_supported();
return nsnull;
}
nsCOMPtr<nsIUnicodeDecoder> decoder;
rv = manager->GetUnicodeDecoder(aEncoding, getter_AddRefs(decoder));
if (NS_FAILED(rv)) {
error_invalid_argument();
return nsnull;
}
// Compute an upper bound to the number of chars, allocate buffer
int32_t srcBytes = aBytesToDecode;
int32_t upperBoundChars = 0;
rv = decoder->GetMaxLength(aSource, srcBytes, &upperBoundChars);
MOZ_ASSERT(NS_SUCCEEDED(rv));
int32_t bufSize = (upperBoundChars + 1) * sizeof (PRUnichar);
mozilla::ScopedFreePtr<PRUnichar> dest((PRUnichar*)NS_Alloc(bufSize));
if (dest.get() == nsnull) {
error_no_memory();
return nsnull;
}
// Convert, add trailing \0
rv = decoder->Convert(aSource, &srcBytes, dest.rwget(), &upperBoundChars);
if (NS_FAILED(rv)) {
error_invalid_argument();
return nsnull;
}
dest.rwget()[upperBoundChars] = '\0';
return dest.forget();
}
MOZ_EXPORT_API(char*) osfile_EncodeAll(
const char* aEncoding,
const PRUnichar* aSource,
int32_t* aBytesProduced)
{
if (!aEncoding || !aSource || !aBytesProduced) {
error_invalid_argument();
return nsnull;
}
nsresult rv;
nsCOMPtr<nsICharsetConverterManager> manager =
do_GetService(NS_CHARSETCONVERTERMANAGER_CONTRACTID, &rv);
if (NS_FAILED(rv)) {
error_not_supported();
return nsnull;
}
nsCOMPtr<nsIUnicodeEncoder> encoder;
rv = manager->GetUnicodeEncoder(aEncoding, getter_AddRefs(encoder));
if (NS_FAILED(rv)) {
error_invalid_argument();
return nsnull;
}
int32_t srcChars = NS_strlen(aSource);
int32_t upperBoundBytes = 0;
rv = encoder->GetMaxLength(aSource, srcChars, &upperBoundBytes);
MOZ_ASSERT(NS_SUCCEEDED(rv));
printf_stderr("Encoding %d chars into at up to %d bytes\n", srcChars, upperBoundBytes);
int32_t bufSize = upperBoundBytes;
mozilla::ScopedFreePtr<char> dest((char*)NS_Alloc(bufSize));
if (dest.get() == nsnull) {
error_no_memory();
return nsnull;
}
rv = encoder->Convert(aSource, &srcChars, dest.rwget(), &upperBoundBytes);
if (NS_FAILED(rv)) {
error_invalid_argument();
return nsnull;
}
*aBytesProduced = upperBoundBytes;
return dest.forget();
}
} // extern "C"

View File

@ -0,0 +1,65 @@
#ifndef mozilla_osfileutils_h__
#define mozilla_osfileutils_h__
#include "mozilla/Types.h"
#include "nsIUnicodeDecoder.h"
#include "nsIUnicodeEncoder.h"
extern "C" {
// Memory utilities
/**
* As |NS_Free|, but exported.
*/
MOZ_EXPORT_API(void) osfile_ns_free(void* buf);
// Unicode utilities
/**
* Duplicate a Unicode string, as per wpcpy/StrDupW.
*
* @param source A well-formed, nul-terminated, Unicode string.
*
* @return Either |NULL| if there was not enough memory to copy the
* string, or a new string with the same contents as |source|.
* Memory MUST be released with |osfile_ns_free|.
*/
MOZ_EXPORT_API(PRUnichar*) osfile_wstrdup(PRUnichar* source);
/**
* Decode a nul-terminated C string into a Unicode string.
*
* @param aEncoding The encoding to use.
* @param aSource The C string to decode.
* @param aBytesToDecode The number of bytes to decode from |aSource|.
*
* @return null in case of error, otherwise a sequence of Unicode
* chars, representing |aSource|. This memory MUST be released with
* |NS_Free|/|osfile_ns_free|.
*/
MOZ_EXPORT_API(PRUnichar*) osfile_DecodeAll(
const char* aEncoding,
const char* aSource,
const int32_t aBytesToDecode);
/**
* Encode a complete Unicode string into a set of bytes.
*
* @param aEncoding The encoding to use.
* @param aSource The Unicode string to encode. Must be nul-terminated.
* @param aBytesWritten (out) The number of bytes encoded.
*
* @return null in case of error, otherwise a new buffer. The
* number of bytes actually allocated may be higher than
* |aBytesWritten|. The buffer MUST be released with
* |NS_Free|/|osfile_ns_free|.
*/
MOZ_EXPORT_API(char*) osfile_EncodeAll(
const char* aEncoding,
const PRUnichar* aSource,
int32_t* aBytesWritten);
} // extern "C"
#endif // mozilla_osfileutils_h__