diff options
author | mstrydom@google.com <mstrydom@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-09-02 22:21:31 +0000 |
---|---|---|
committer | mstrydom@google.com <mstrydom@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-09-02 22:21:31 +0000 |
commit | 8607f6dae7f80f494d55cb6701234ca7be18738b (patch) | |
tree | 2121ef79ee8402d5ada98b5c634c76c30263af1a /o3d | |
parent | 74d7f63a55085f2d7badff916b08ebe459184b9b (diff) | |
download | chromium_src-8607f6dae7f80f494d55cb6701234ca7be18738b.zip chromium_src-8607f6dae7f80f494d55cb6701234ca7be18738b.tar.gz chromium_src-8607f6dae7f80f494d55cb6701234ca7be18738b.tar.bz2 |
This CL adds the createRawDataFromDataURL function to o3d.Pack. The function
takes as input a data URL, decodes the data, and returns the raw data in a
RawData object. If the data URL has an invalid format, an error message is
displayed. Currently only data URL's encoded in base64 are supported. The mime
type is ignored.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@25252 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'o3d')
-rw-r--r-- | o3d/core/cross/pack.cc | 11 | ||||
-rw-r--r-- | o3d/core/cross/pack.h | 7 | ||||
-rw-r--r-- | o3d/core/cross/pack_test.cc | 16 | ||||
-rw-r--r-- | o3d/import/cross/raw_data.cc | 26 | ||||
-rw-r--r-- | o3d/import/cross/raw_data.h | 9 | ||||
-rw-r--r-- | o3d/import/cross/raw_data_test.cc | 18 | ||||
-rw-r--r-- | o3d/plugin/idl/pack.idl | 7 | ||||
-rw-r--r-- | o3d/utils/cross/base64.cc | 128 | ||||
-rw-r--r-- | o3d/utils/cross/base64.h | 34 | ||||
-rw-r--r-- | o3d/utils/cross/base64_test.cc | 105 | ||||
-rw-r--r-- | o3d/utils/cross/dataurl.cc | 60 | ||||
-rw-r--r-- | o3d/utils/cross/dataurl.h | 18 | ||||
-rw-r--r-- | o3d/utils/cross/dataurl_test.cc | 69 |
13 files changed, 506 insertions, 2 deletions
diff --git a/o3d/core/cross/pack.cc b/o3d/core/cross/pack.cc index bcc5c06..fb3af89 100644 --- a/o3d/core/cross/pack.cc +++ b/o3d/core/cross/pack.cc @@ -309,6 +309,17 @@ std::vector<Bitmap*> Pack::CreateBitmapsFromRawData(RawData* raw_data) { return bitmaps; } +// Creates a new RawData from a data URL. +RawData* Pack::CreateRawDataFromDataURL(const String& data_url) { + RawData::Ref raw_data = RawData::CreateFromDataURL(service_locator(), + data_url); + + if (!raw_data.IsNull()) { + RegisterObject(raw_data); + } + return raw_data.Get(); +} + // Creates a Texture2D object and allocates the necessary resources for it. Texture2D* Pack::CreateTexture2D(int width, int height, diff --git a/o3d/core/cross/pack.h b/o3d/core/cross/pack.h index ce7be0f..1d17c83 100644 --- a/o3d/core/cross/pack.h +++ b/o3d/core/cross/pack.h @@ -235,6 +235,13 @@ class Pack : public NamedObject { // bitmaps: A vector of pointers to bitmaps. If empty there was an error. std::vector<Bitmap*> CreateBitmapsFromRawData(RawData* raw_data); + // Creates a new RawData from a String containing a data URL. + // Parameters: + // data_url: Contains the data URL that is to be decoded. + // Returns: + // A pointer to the RawData that contains the data URL's data. + RawData* CreateRawDataFromDataURL(const String& data_url); + // Creates a new Texture2D object of the specified size and format and // reserves the necessary resources for it. // Parameters: diff --git a/o3d/core/cross/pack_test.cc b/o3d/core/cross/pack_test.cc index 5aca47f..0b637ec 100644 --- a/o3d/core/cross/pack_test.cc +++ b/o3d/core/cross/pack_test.cc @@ -162,4 +162,20 @@ TEST_F(PackTest, RemoveObject) { EXPECT_TRUE(pack->Destroy()); } +TEST_F(PackTest, CreateRawDataFromDataURL) { + Pack* pack = object_manager()->CreatePack(); + RawData* raw_data = pack->CreateRawDataFromDataURL("data:;base64,YWJj"); + + EXPECT_FALSE(raw_data == NULL); + EXPECT_FALSE(CheckErrorExists()); +} + +TEST_F(PackTest, CreateRawDataFromDataURLFail) { + Pack* pack = object_manager()->CreatePack(); + RawData* raw_data = pack->CreateRawDataFromDataURL("data:;base64,Y"); + + EXPECT_TRUE(raw_data == NULL); + EXPECT_TRUE(CheckErrorExists()); +} + } // namespace o3d diff --git a/o3d/import/cross/raw_data.cc b/o3d/import/cross/raw_data.cc index 66e0109..91e2bc6 100644 --- a/o3d/import/cross/raw_data.cc +++ b/o3d/import/cross/raw_data.cc @@ -38,6 +38,7 @@ #include "utils/cross/file_path_utils.h" #include "base/file_path.h" #include "base/file_util.h" +#include "utils/cross/dataurl.h" #ifdef OS_MACOSX #include <CoreFoundation/CoreFoundation.h> @@ -92,7 +93,16 @@ RawData::Ref RawData::CreateFromFile(ServiceLocator* service_locator, return data; } +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +RawData::Ref RawData::CreateFromDataURL(ServiceLocator* service_locator, + const String& data_url) { + RawData::Ref raw_data(Create(service_locator, "", NULL, 0)); + if (!raw_data->SetFromDataURL(data_url)) { + raw_data.Reset(); + } + return raw_data; +} // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ RawData::~RawData() { Discard(); @@ -137,7 +147,21 @@ bool RawData::SetFromFile(const String& filename) { return result; } - +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +bool RawData::SetFromDataURL(const String& data_url) { + String error_string; + size_t data_length = 0; + bool no_errors = dataurl::FromDataURL(data_url, + &data_, + &data_length, + &error_string); + length_ = data_length; + if (!no_errors) { + O3D_ERROR(service_locator()) << error_string; + return false; + } + return true; +} // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ const uint8 *RawData::GetData() const { // Return data immediately if we have it diff --git a/o3d/import/cross/raw_data.h b/o3d/import/cross/raw_data.h index 092c800..96ea3f4 100644 --- a/o3d/import/cross/raw_data.h +++ b/o3d/import/cross/raw_data.h @@ -62,6 +62,11 @@ class RawData : public ParamObject { const String &uri, const String& filename); + // Creates a RawData object, taking as input a string containing a + // data URL. + static RawData::Ref CreateFromDataURL(ServiceLocator* service_locator, + const String& data_url); + virtual ~RawData(); const uint8 *GetData() const; @@ -110,6 +115,10 @@ class RawData : public ParamObject { bool SetFromFile(const String& filename); + // Decodes data from a data URL and stores that data in this + // RawData object. Returns false on error, true otherwise + bool SetFromDataURL(const String& data_url); + friend class IClassManager; friend class Pack; diff --git a/o3d/import/cross/raw_data_test.cc b/o3d/import/cross/raw_data_test.cc index b4c5f86..fe0f212 100644 --- a/o3d/import/cross/raw_data_test.cc +++ b/o3d/import/cross/raw_data_test.cc @@ -157,7 +157,7 @@ struct TestData { size_t offset; }; -} // anonymous namespace +} // anonymous namespace TEST_F(RawDataTest, StringValue) { // A BOM in the front (valid) @@ -266,4 +266,20 @@ TEST_F(RawDataTest, StringValue) { } } +TEST_F(RawDataTest, CreateFromDataURL) { + RawData::Ref ref = RawData::CreateFromDataURL(g_service_locator, + "data:;base64,YWJj"); + ASSERT_FALSE(ref.IsNull()); + EXPECT_EQ(3u, ref->GetLength()); + EXPECT_FALSE(CheckErrorExists(error_status())); + EXPECT_EQ(0, memcmp(ref->GetData(), "abc", 3)); +} + +TEST_F(RawDataTest, CreateFromDataURLFail) { + RawData::Ref ref = RawData::CreateFromDataURL(g_service_locator, + "data:;base64,Y"); + EXPECT_TRUE(ref.IsNull()); + EXPECT_TRUE(CheckErrorExists(error_status())); +} + } // namespace o3d diff --git a/o3d/plugin/idl/pack.idl b/o3d/plugin/idl/pack.idl index 3d63f6b..3fd5b6d 100644 --- a/o3d/plugin/idl/pack.idl +++ b/o3d/plugin/idl/pack.idl @@ -325,6 +325,13 @@ typedef Bitmap[] BitmapArray; \return An Array of Bitmaps object. %] BitmapArray CreateBitmapsFromRawData(RawData raw_data); + + %[ + Create RawData given a data URL. + \param data_url The data URL from which to create the RawData. + \return The RawData. + %] + RawData CreateRawDataFromDataURL(String data_url); }; // Pack } // namespace o3d diff --git a/o3d/utils/cross/base64.cc b/o3d/utils/cross/base64.cc index 3662258..7e688b0 100644 --- a/o3d/utils/cross/base64.cc +++ b/o3d/utils/cross/base64.cc @@ -85,6 +85,134 @@ void Encode(const void* src_ptr, size_t length, void* dst_ptr) { }
}
+// This function actually does the decoding.
+// Parameters:
+// src_ptr: pointer to the source data
+// input_length: The length in bytes of the source data.
+// dst_ptr: pointer to where the output data should be stored.
+// dst_buffer_length: the size in bytes of the dst_ptr buffer. This
+// is used to check for overflow. Not used if write_destination is
+// false.
+// output_length: The output length (in bytes) will be stored here if
+// it is not null.
+// write_destination: If true, actually write to the output. Otherwise,
+// the length of the output will be determined only.
+DecodeStatus PerformDecode(const void* src_ptr,
+ size_t input_length,
+ void* dst_ptr,
+ size_t dst_buffer_length,
+ size_t* output_length,
+ bool write_destination) {
+ const int kDecodePad = -2;
+
+ static const int8 kDecodeData[] = {
+ 62, -1, -1, -1, 63,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, kDecodePad, -1, -1,
+ -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
+ -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
+ };
+
+ uint8* dst = reinterpret_cast<uint8*>(dst_ptr);
+ const uint8* dst_start = reinterpret_cast<const uint8*>(dst_ptr);
+ const uint8* dst_end = dst_start + dst_buffer_length;
+ const uint8* src = reinterpret_cast<const uint8*>(src_ptr);
+ bool pad_two = false;
+ bool pad_three = false;
+ const uint8* end = src + input_length;
+ while (src < end) {
+ uint8 bytes[4];
+ int byte = 0;
+ do {
+ uint8 src_byte = *src++;
+ if (src_byte == 0)
+ goto goHome;
+ if (src_byte <= ' ')
+ continue; // treat as white space
+ if (src_byte < '+' || src_byte > 'z')
+ return kBadCharError;
+ int8 decoded = kDecodeData[src_byte - '+'];
+ bytes[byte] = decoded;
+ if (decoded < 0) {
+ if (decoded == kDecodePad)
+ goto handlePad;
+ return kBadCharError;
+ } else {
+ byte++;
+ }
+ if (*src)
+ continue;
+ if (byte == 0)
+ goto goHome;
+ if (byte == 4)
+ break;
+ handlePad:
+ if (byte < 2)
+ return kPadError;
+ pad_three = true;
+ if (byte == 2)
+ pad_two = true;
+ break;
+ } while (byte < 4);
+ int two, three;
+ if (write_destination) {
+ int one = (bytes[0] << 2) & 0xFF;
+ two = bytes[1];
+ one |= two >> 4;
+ two = (two << 4) & 0xFF;
+ three = bytes[2];
+ two |= three >> 2;
+ three = (three << 6) & 0xFF;
+ three |= bytes[3];
+ O3D_ASSERT(one < 256 && two < 256 && three < 256);
+ if (dst >= dst_end) {
+ return kOutputOverflowError;
+ }
+ *dst = one;
+ }
+ dst++;
+ if (pad_two)
+ break;
+ if (write_destination) {
+ if (dst >= dst_end) {
+ return kOutputOverflowError;
+ }
+ *dst = two;
+ }
+ dst++;
+ if (pad_three)
+ break;
+ if (write_destination) {
+ if (dst >= dst_end) {
+ return kOutputOverflowError;
+ }
+ *dst = three;
+ }
+ dst++;
+ }
+ goHome:
+ if (output_length) {
+ *output_length = dst - dst_start;
+ }
+ return kSuccess;
+}
+
+// Returns the number of bytes of output data after decoding from base64.
+DecodeStatus GetDecodeLength(const void* src,
+ size_t input_length,
+ size_t* decode_length) {
+ return PerformDecode(src, input_length, NULL, 0, decode_length, false);
+}
+
+// Decodes the src data from base64 and stores the result in dst.
+DecodeStatus Decode(const void* src,
+ size_t input_length,
+ void* dst,
+ size_t dst_buffer_length) {
+ return PerformDecode(src, input_length, dst, dst_buffer_length, NULL, true);
+}
+
} // namespace base64
} // namespace o3d
diff --git a/o3d/utils/cross/base64.h b/o3d/utils/cross/base64.h index d56ad4f..6cc7762 100644 --- a/o3d/utils/cross/base64.h +++ b/o3d/utils/cross/base64.h @@ -40,6 +40,14 @@ namespace o3d {
namespace base64 {
+// The possible error codes that can occur during a decoding.
+enum DecodeStatus {
+ kSuccess,
+ kPadError,
+ kBadCharError,
+ kOutputOverflowError
+};
+
// Returns the number of bytes needed to encode length bytes in base64.
size_t GetEncodeLength(size_t length);
@@ -51,6 +59,32 @@ size_t GetEncodeLength(size_t length); // dst: pointer to place to store result.
void Encode(const void* src, size_t length, void* dst);
+// Used to obtain the number of bytes needed to decode the src data
+// from base64.
+// Parameters:
+// src: pointer to the source data.
+// input_length: the length of the source data
+// decode_length: the length in bytes of the decoded data will be
+// placed here.
+DecodeStatus GetDecodeLength(const void* src,
+ size_t input_length,
+ size_t* decode_length);
+
+// Decodes the src, which should be encoded in base64, into the dst.
+// dst must have enough space to hold the result. The number of bytes
+// necessary can be obtained by calling GetDecodeLength()
+// Parameters:
+// src: pointer to the source data
+// input_length: the length of the source data
+// dst: pointer to where the result should be stored.
+// dst_buffer_length: the size in bytes of the dst buffer. This is
+// used to check for buffer overflow.
+// Returns an error code (of type DecodeStatus)
+DecodeStatus Decode(const void* src,
+ size_t input_length,
+ void* dst,
+ size_t dst_buffer_length);
+
} // namespace base64
} // namespace o3d
diff --git a/o3d/utils/cross/base64_test.cc b/o3d/utils/cross/base64_test.cc index b6d3aea..9eacd69 100644 --- a/o3d/utils/cross/base64_test.cc +++ b/o3d/utils/cross/base64_test.cc @@ -60,6 +60,111 @@ TEST_F(Base64Test, Encode) { EXPECT_EQ(0xFF, buffer[8]);
}
+TEST_F(Base64Test, GetDecodeLength) {
+ size_t length = 256u;
+ base64::GetDecodeLength("", 0, &length);
+ EXPECT_EQ(0u, length);
+
+ length = 256u;
+ base64::GetDecodeLength("YQ==", 4, &length);
+ EXPECT_EQ(1u, length);
+
+ length = 256u;
+ base64::GetDecodeLength("YWI=", 4, &length);
+ EXPECT_EQ(2u, length);
+
+ length = 256u;
+ base64::GetDecodeLength("YWJj", 4, &length);
+ EXPECT_EQ(3u, length);
+
+ length = 256u;
+ base64::GetDecodeLength("YWJjZA==", 8, &length);
+ EXPECT_EQ(4u, length);
+
+ length = 256u;
+ base64::GetDecodeLength("YWJjZGU=", 8, &length);
+ EXPECT_EQ(5u, length);
+}
+
+TEST_F(Base64Test, GetDecodeLengthInputError) {
+ base64::DecodeStatus status = base64::kSuccess;
+ size_t length = 256u;
+ status = base64::GetDecodeLength("Y@==", 4, &length);
+ EXPECT_EQ(base64::kBadCharError, status);
+
+ status = base64::GetDecodeLength("Y Q==", 4, &length);
+ EXPECT_EQ(base64::kSuccess, status);
+
+ status = base64::GetDecodeLength("Y", 1, &length);
+ EXPECT_EQ(base64::kPadError, status);
+}
+
+TEST_F(Base64Test, Decode) {
+ unsigned char buffer[10];
+ memset(buffer, 0xFF, sizeof(buffer));
+ unsigned char result_buffer[10];
+ memset(result_buffer, 0xFF, sizeof(result_buffer));
+ base64::DecodeStatus status = base64::kSuccess;
+
+ status = base64::Decode("", 0, buffer, 10);
+ EXPECT_EQ(base64::kSuccess, status);
+ EXPECT_EQ(0, memcmp(buffer, result_buffer, 10));
+
+ result_buffer[0] = 'a';
+ status = base64::Decode("YQ==", 4, buffer, 10);
+ EXPECT_EQ(base64::kSuccess, status);
+ EXPECT_EQ(0, memcmp(buffer, result_buffer, 10));
+
+ result_buffer[1] = 'b';
+ status = base64::Decode("YWI=", 4, buffer, 10);
+ EXPECT_EQ(base64::kSuccess, status);
+ EXPECT_EQ(0, memcmp(buffer, result_buffer, 10));
+
+ result_buffer[2] = 'c';
+ status = base64::Decode("YWJj", 4, buffer, 10);
+ EXPECT_EQ(base64::kSuccess, status);
+ EXPECT_EQ(0, memcmp(buffer, result_buffer, 10));
+
+ result_buffer[3] = 'd';
+ status = base64::Decode("YWJjZA==", 8, buffer, 10);
+ EXPECT_EQ(base64::kSuccess, status);
+ EXPECT_EQ(0, memcmp(buffer, result_buffer, 10));
+
+ result_buffer[4] = 'e';
+ status = base64::Decode("YWJjZGU=", 8, buffer, 10);
+ EXPECT_EQ(base64::kSuccess, status);
+ EXPECT_EQ(0, memcmp(buffer, result_buffer, 10));
+}
+
+TEST_F(Base64Test, DecodeInputError) {
+ unsigned char buffer[10];
+ base64::DecodeStatus status = base64::kSuccess;
+ status = base64::Decode("Y@==", 4, buffer, 10);
+ EXPECT_EQ(base64::kBadCharError, status);
+
+ status = base64::Decode("Y Q==", 4, buffer, 10);
+ EXPECT_EQ(base64::kSuccess, status);
+
+ status = base64::Decode("Y", 1, buffer, 10);
+ EXPECT_EQ(base64::kPadError, status);
+}
+
+TEST_F(Base64Test, DecodeOverflowError) {
+ unsigned char buffer[10];
+ base64::DecodeStatus status = base64::kSuccess;
+ status = base64::Decode("YWJjZA==", 8, buffer, 3);
+ EXPECT_EQ(base64::kOutputOverflowError, status);
+
+ status = base64::Decode("YWJjZA==", 8, buffer, 4);
+ EXPECT_EQ(base64::kSuccess, status);
+
+ status = base64::Decode("YQ==", 8, buffer, 0);
+ EXPECT_EQ(base64::kOutputOverflowError, status);
+
+ status = base64::Decode("YQ==", 8, buffer, 1);
+ EXPECT_EQ(base64::kSuccess, status);
+}
+
} // namespace o3d
diff --git a/o3d/utils/cross/dataurl.cc b/o3d/utils/cross/dataurl.cc index 8334b8d..f796719 100644 --- a/o3d/utils/cross/dataurl.cc +++ b/o3d/utils/cross/dataurl.cc @@ -48,6 +48,66 @@ String ToDataURL(const String& mime_type, const void* data, size_t length) { return result;
}
+// Decodes the data URL and stores a pointer to the data in dst_buffer
+bool FromDataURL(const String& data_url,
+ scoped_array<uint8>* dst_buffer,
+ size_t* output_length,
+ String* error_string) {
+ // First parse the data_url
+ const String kDataHeader("data:");
+ const String kBase64Header(";base64,");
+ // The string has to be long enough.
+ if (data_url.size() <= kDataHeader.size() + kBase64Header.size()) {
+ *error_string = "Invalid formatting: The data URL is not long enough.";
+ return false;
+ }
+ // it must start with "data:"
+ if (data_url.compare(0, kDataHeader.size(), kDataHeader) != 0) {
+ *error_string
+ = "Invalid formatting: The data URL must start with 'data:'";
+ return false;
+ }
+ // we only support base64 data URL's
+ String::size_type data_index = data_url.find(kBase64Header);
+ if (data_index == String::npos) {
+ *error_string
+ = "Invalid formatting: The data URL have ';base64,' in the header.";
+ return false;
+ }
+ // The start of the data.
+ data_index += kBase64Header.size();
+ if (data_index >= data_url.size()) {
+ *error_string
+ = "Invalid formatting: There must be data in the body of the data URL.";
+ return false;
+ }
+
+ // Get the length of the decoded data
+ size_t input_length = data_url.size() - data_index;
+ base64::DecodeStatus return_code = base64::GetDecodeLength(
+ &data_url[data_index],
+ input_length,
+ output_length);
+ if (return_code != base64::kSuccess) {
+ if (return_code == base64::kPadError) {
+ *error_string
+ = "Invalid formatting: Padding error in the data URL data.";
+ } else {
+ *error_string
+ = "Invalid formatting: Bad character error in the data URL data.";
+ }
+ return false;
+ }
+
+ dst_buffer->reset(new uint8[*output_length]);
+ base64::Decode(&data_url[data_index],
+ input_length,
+ dst_buffer->get(),
+ (*output_length));
+
+ return true;
+}
+
} // namespace dataurl
} // namespace o3d
diff --git a/o3d/utils/cross/dataurl.h b/o3d/utils/cross/dataurl.h index cc46e01..7cb979a 100644 --- a/o3d/utils/cross/dataurl.h +++ b/o3d/utils/cross/dataurl.h @@ -35,6 +35,7 @@ #define O3D_UTILS_CROSS_DATAURL_H_
#include "core/cross/types.h"
+#include "base/scoped_ptr.h"
namespace o3d {
namespace dataurl {
@@ -45,6 +46,23 @@ extern const char* const kEmptyDataURL; // Creates a data URL for the given data.
String ToDataURL(const String& mime_type, const void* data, size_t length);
+// Decodes the data from a data URL and stores a pointer to the data in
+// dst_buffer. If an error occurs in decoding, it returns false and
+// error_string will contain an error message. Otherwise, returns true.
+// Parameters:
+// data_url: The data URL from which to extract the data.
+// dst_buffer: A pointer to the output data will be stored in this
+// scoped_array.
+// output_length: The length of the output data will be stored at this
+// address.
+// error_string: This will contain the error message, if an error occurs.
+// Returns:
+// False if an error occurs in decoding, true otherwise.
+bool FromDataURL(const String& data_url,
+ scoped_array<uint8>* dst_buffer,
+ size_t* output_length,
+ String* error_string);
+
} // namespace dataurl
} // namespace o3d
diff --git a/o3d/utils/cross/dataurl_test.cc b/o3d/utils/cross/dataurl_test.cc index 8404650..4095859 100644 --- a/o3d/utils/cross/dataurl_test.cc +++ b/o3d/utils/cross/dataurl_test.cc @@ -51,6 +51,75 @@ TEST_F(DataURLTest, ToDataURL) { dataurl::ToDataURL("de/ej", "ab\0c", 4).c_str());
}
+TEST_F(DataURLTest, FromDataURL) {
+ String data_url("data:a/b;base64,YWJj");
+ scoped_array<uint8> output;
+ size_t output_length;
+ String error_string;
+
+ EXPECT_TRUE(dataurl::FromDataURL(data_url,
+ &output,
+ &output_length,
+ &error_string));
+ EXPECT_EQ(3, output_length);
+ EXPECT_EQ(0, memcmp("abc", output.get(), 3));
+}
+
+TEST_F(DataURLTest, FromDataURLFormatErrors) {
+ scoped_array<uint8> output;
+ size_t output_length;
+ String error_string("");
+ // Not long enough
+ EXPECT_FALSE(dataurl::FromDataURL("",
+ &output,
+ &output_length,
+ &error_string));
+ EXPECT_LT(0u, error_string.size());
+ // Does not start with "data:"
+ error_string = "";
+ EXPECT_FALSE(dataurl::FromDataURL("aaaaaaaaaaaaaaaa",
+ &output,
+ &output_length,
+ &error_string));
+ EXPECT_LT(0u, error_string.size());
+ // Must contain base64
+ error_string = "";
+ EXPECT_FALSE(dataurl::FromDataURL("data:aaaaaaaaaaa",
+ &output,
+ &output_length,
+ &error_string));
+ EXPECT_LT(0u, error_string.size());
+ // Must contain data.
+ error_string = "";
+ EXPECT_FALSE(dataurl::FromDataURL("data:aa;base64,",
+ &output,
+ &output_length,
+ &error_string));
+ EXPECT_LT(0u, error_string.size());
+
+ // Bad character in data.
+ error_string = "";
+ EXPECT_FALSE(dataurl::FromDataURL("data:;base64,@",
+ &output,
+ &output_length,
+ &error_string));
+ EXPECT_LT(0u, error_string.size());
+ // Padding error in data.
+ error_string = "";
+ EXPECT_FALSE(dataurl::FromDataURL("data:;base64,Y",
+ &output,
+ &output_length,
+ &error_string));
+ EXPECT_LT(0u, error_string.size());
+ // Correct.
+ error_string = "";
+ EXPECT_TRUE(dataurl::FromDataURL("data:;base64,YWJj",
+ &output,
+ &output_length,
+ &error_string));
+ EXPECT_EQ(0u, error_string.size());
+}
+
} // namespace o3d
|