703 lines
17 KiB
C++
703 lines
17 KiB
C++
/* ***** BEGIN LICENSE BLOCK *****
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
*
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
* the License. You may obtain a copy of the License at
|
|
* http://www.mozilla.org/MPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
* for the specific language governing rights and limitations under the
|
|
* License.
|
|
*
|
|
* The Original Code is [Open Source Virtual Machine.].
|
|
*
|
|
* The Initial Developer of the Original Code is
|
|
* Adobe System Incorporated.
|
|
* Portions created by the Initial Developer are Copyright (C) 2004-2006
|
|
* the Initial Developer. All Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
* Adobe AS3 Team
|
|
*
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
* use your version of this file under the terms of the MPL, indicate your
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
* the provisions above, a recipient may use your version of this file under
|
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
*
|
|
* ***** END LICENSE BLOCK ***** */
|
|
|
|
|
|
|
|
#include "avmshell.h"
|
|
#include "genericzlib.h"
|
|
|
|
namespace avmshell
|
|
{
|
|
BEGIN_NATIVE_MAP(ByteArrayClass)
|
|
NATIVE_METHOD(flash_utils_ByteArray_toString, ByteArrayObject::_toString)
|
|
NATIVE_METHOD(flash_utils_ByteArray_length_get, ByteArrayObject::get_length)
|
|
NATIVE_METHOD(flash_utils_ByteArray_length_set, ByteArrayObject::set_length)
|
|
|
|
NATIVE_METHOD(flash_utils_ByteArray_readBytes, ByteArrayObject::readBytes)
|
|
NATIVE_METHOD(flash_utils_ByteArray_writeBytes, ByteArrayObject::writeBytes)
|
|
|
|
NATIVE_METHOD(flash_utils_ByteArray_writeBoolean, ByteArrayObject::writeBoolean)
|
|
NATIVE_METHOD(flash_utils_ByteArray_writeByte, ByteArrayObject::writeByte)
|
|
NATIVE_METHOD(flash_utils_ByteArray_writeShort, ByteArrayObject::writeShort)
|
|
NATIVE_METHOD(flash_utils_ByteArray_writeInt, ByteArrayObject::writeInt)
|
|
NATIVE_METHOD(flash_utils_ByteArray_writeUnsignedInt, ByteArrayObject::writeUnsignedInt)
|
|
NATIVE_METHOD(flash_utils_ByteArray_writeFloat, ByteArrayObject::writeFloat)
|
|
NATIVE_METHOD(flash_utils_ByteArray_writeDouble, ByteArrayObject::writeDouble)
|
|
NATIVE_METHOD(flash_utils_ByteArray_writeUTF, ByteArrayObject::writeUTF)
|
|
NATIVE_METHOD(flash_utils_ByteArray_writeUTFBytes, ByteArrayObject::writeUTFBytes)
|
|
|
|
NATIVE_METHOD(flash_utils_ByteArray_readBoolean, ByteArrayObject::readBoolean)
|
|
NATIVE_METHOD(flash_utils_ByteArray_readByte, ByteArrayObject::readByte)
|
|
NATIVE_METHOD(flash_utils_ByteArray_readUnsignedByte, ByteArrayObject::readUnsignedByte)
|
|
NATIVE_METHOD(flash_utils_ByteArray_readShort, ByteArrayObject::readShort)
|
|
NATIVE_METHOD(flash_utils_ByteArray_readUnsignedShort, ByteArrayObject::readUnsignedShort)
|
|
NATIVE_METHOD(flash_utils_ByteArray_readInt, ByteArrayObject::readInt)
|
|
NATIVE_METHOD(flash_utils_ByteArray_readUnsignedInt, ByteArrayObject::readUnsignedInt)
|
|
NATIVE_METHOD(flash_utils_ByteArray_readFloat, ByteArrayObject::readFloat)
|
|
NATIVE_METHOD(flash_utils_ByteArray_readDouble, ByteArrayObject::readDouble)
|
|
NATIVE_METHOD(flash_utils_ByteArray_readUTF, ByteArrayObject::readUTF)
|
|
NATIVE_METHOD(flash_utils_ByteArray_readUTFBytes, ByteArrayObject::readUTFBytes)
|
|
|
|
NATIVE_METHOD(flash_utils_ByteArray_bytesAvailable_get, ByteArrayObject::available)
|
|
NATIVE_METHOD(flash_utils_ByteArray_position_get, ByteArrayObject::getFilePointer)
|
|
NATIVE_METHOD(flash_utils_ByteArray_position_set, ByteArrayObject::seek)
|
|
NATIVE_METHOD(flash_utils_ByteArray_compress, ByteArrayObject::zlib_compress)
|
|
NATIVE_METHOD(flash_utils_ByteArray_uncompress, ByteArrayObject::zlib_uncompress)
|
|
NATIVE_METHOD(flash_utils_ByteArray_endian_get, ByteArrayObject::get_endian)
|
|
NATIVE_METHOD(flash_utils_ByteArray_endian_set, ByteArrayObject::set_endian)
|
|
NATIVE_METHOD(flash_utils_ByteArray_writeFile, ByteArrayObject::writeFile)
|
|
|
|
NATIVE_METHOD(flash_utils_ByteArray_readFile, ByteArrayClass::readFile)
|
|
END_NATIVE_MAP()
|
|
|
|
//
|
|
// ByteArray
|
|
//
|
|
|
|
ByteArray::ByteArray()
|
|
{
|
|
m_capacity = 0;
|
|
m_length = 0;
|
|
m_array = NULL;
|
|
}
|
|
|
|
ByteArray::ByteArray(const ByteArray &lhs)
|
|
{
|
|
m_array = new U8[lhs.m_length];
|
|
if (!m_array)
|
|
{
|
|
ThrowMemoryError();
|
|
return;
|
|
}
|
|
|
|
m_capacity = lhs.m_length;
|
|
m_length = lhs.m_length;
|
|
|
|
memcpy(m_array, lhs.m_array, m_length);
|
|
}
|
|
|
|
ByteArray::~ByteArray()
|
|
{
|
|
if (m_array)
|
|
{
|
|
delete [] m_array;
|
|
m_array = NULL;
|
|
}
|
|
m_capacity = 0;
|
|
m_length = 0;
|
|
}
|
|
|
|
void ByteArray::ThrowMemoryError()
|
|
{
|
|
// todo throw out of memory exception
|
|
// m_toplevel->memoryError->throwError(kOutOfMemoryError);
|
|
}
|
|
|
|
bool ByteArray::Grow(uint32 minimumCapacity)
|
|
{
|
|
if (minimumCapacity > m_capacity)
|
|
{
|
|
uint32 newCapacity = m_capacity << 1;
|
|
if (newCapacity < minimumCapacity)
|
|
{
|
|
newCapacity = minimumCapacity;
|
|
}
|
|
if (newCapacity < kGrowthIncr)
|
|
{
|
|
newCapacity = kGrowthIncr;
|
|
}
|
|
U8 *newArray = new U8[newCapacity];
|
|
if (!newArray)
|
|
{
|
|
return false;
|
|
}
|
|
if (m_array)
|
|
{
|
|
memcpy(newArray, m_array, m_length);
|
|
delete [] m_array;
|
|
}
|
|
memset(newArray+m_length, 0, newCapacity-m_capacity);
|
|
m_array = newArray;
|
|
m_capacity = newCapacity;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
U8 ByteArray::operator[] (uint32 index) const
|
|
{
|
|
if (m_length <= index)
|
|
{
|
|
return 0;
|
|
}
|
|
return m_array[index];
|
|
}
|
|
|
|
U8& ByteArray::operator[] (uint32 index)
|
|
{
|
|
if (m_length <= index)
|
|
{
|
|
Grow(index+1);
|
|
m_length = index+1;
|
|
}
|
|
return m_array[index];
|
|
}
|
|
|
|
void ByteArray::Push(U8 value)
|
|
{
|
|
if (m_length >= m_capacity)
|
|
{
|
|
Grow(m_length + 1);
|
|
}
|
|
m_array[m_length++] = value;
|
|
}
|
|
|
|
void ByteArray::Push(const U8 *data, uint32 count)
|
|
{
|
|
Grow(m_length + count);
|
|
memcpy(m_array + m_length, data, count);
|
|
m_length += count;
|
|
}
|
|
|
|
void ByteArray::SetLength(uint32 newLength)
|
|
{
|
|
if (newLength > m_capacity)
|
|
{
|
|
if (!Grow(newLength))
|
|
{
|
|
ThrowMemoryError();
|
|
return;
|
|
}
|
|
}
|
|
m_length = newLength;
|
|
}
|
|
|
|
//
|
|
// ByteArrayFile
|
|
//
|
|
|
|
ByteArrayFile::ByteArrayFile(Toplevel *toplevel)
|
|
: DataInput(toplevel),
|
|
DataOutput(toplevel)
|
|
{
|
|
m_filePointer = 0;
|
|
}
|
|
|
|
uint32 ByteArrayFile::Available()
|
|
{
|
|
if (m_filePointer <= m_length) {
|
|
return m_length - m_filePointer;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
void ByteArrayFile::SetLength(uint32 newLength)
|
|
{
|
|
ByteArray::SetLength(newLength);
|
|
if (m_filePointer > newLength) {
|
|
m_filePointer = newLength;
|
|
}
|
|
}
|
|
|
|
void ByteArrayFile::Read(void *buffer, uint32 count)
|
|
{
|
|
CheckEOF(count);
|
|
|
|
if (count > 0)
|
|
{
|
|
memcpy(buffer, m_array+m_filePointer, count);
|
|
m_filePointer += count;
|
|
}
|
|
}
|
|
|
|
void ByteArrayFile::Write(const void *buffer, uint32 count)
|
|
{
|
|
if (m_filePointer+count >= m_length) {
|
|
Grow(m_filePointer+count);
|
|
m_length = m_filePointer+count;
|
|
}
|
|
memcpy(m_array+m_filePointer, buffer, count);
|
|
m_filePointer += count;
|
|
}
|
|
|
|
//
|
|
// ByteArrayObject
|
|
//
|
|
|
|
ByteArrayObject::ByteArrayObject(VTable *ivtable,
|
|
ScriptObject *delegate)
|
|
: ScriptObject(ivtable, delegate),
|
|
m_byteArray(toplevel())
|
|
{
|
|
c.set(&m_byteArray, sizeof(ByteArrayFile));
|
|
}
|
|
|
|
Atom ByteArrayObject::getUintProperty(uint32 i) const
|
|
{
|
|
if (i < (uint32)m_byteArray.GetLength()) {
|
|
return core()->intToAtom(m_byteArray[i]);
|
|
} else {
|
|
return undefinedAtom;
|
|
}
|
|
}
|
|
|
|
void ByteArrayObject::setUintProperty(uint32 i, Atom value)
|
|
{
|
|
m_byteArray[i] = (U8)(core()->integer(value));
|
|
}
|
|
|
|
Atom ByteArrayObject::getAtomProperty(Atom name) const
|
|
{
|
|
AvmCore *core = this->core();
|
|
uint32 index;
|
|
if (core->getIndexFromAtom(name, &index)) {
|
|
if (index < (uint32) m_byteArray.GetLength()) {
|
|
return core->intToAtom(m_byteArray[index]);
|
|
} else {
|
|
return undefinedAtom;
|
|
}
|
|
}
|
|
|
|
return ScriptObject::getAtomProperty(name);
|
|
}
|
|
|
|
void ByteArrayObject::setAtomProperty(Atom name, Atom value)
|
|
{
|
|
AvmCore *core = this->core();
|
|
uint32 index;
|
|
if (core->getIndexFromAtom(name, &index)) {
|
|
int intValue = core->integer(value);
|
|
m_byteArray[index] = (U8)(intValue);
|
|
} else {
|
|
ScriptObject::setAtomProperty(name, value);
|
|
}
|
|
}
|
|
|
|
bool ByteArrayObject::hasAtomProperty(Atom name) const
|
|
{
|
|
return ScriptObject::hasAtomProperty(name) || getAtomProperty(name) != undefinedAtom;
|
|
}
|
|
|
|
void ByteArrayObject::setLength(uint32 newLength)
|
|
{
|
|
m_byteArray.SetLength(newLength);
|
|
}
|
|
|
|
uint32 ByteArrayObject::get_length()
|
|
{
|
|
return m_byteArray.GetLength();
|
|
}
|
|
|
|
void ByteArrayObject::set_length(uint32 value)
|
|
{
|
|
setLength(value);
|
|
}
|
|
|
|
int ByteArrayObject::getFilePointer()
|
|
{
|
|
return m_byteArray.GetFilePointer();
|
|
}
|
|
|
|
int ByteArrayObject::available()
|
|
{
|
|
return m_byteArray.Available();
|
|
}
|
|
|
|
void ByteArrayObject::seek(int offset)
|
|
{
|
|
if (offset >= 0) {
|
|
m_byteArray.Seek(offset);
|
|
}
|
|
}
|
|
|
|
String* ByteArrayObject::_toString()
|
|
{
|
|
unsigned char *c = (unsigned char*)m_byteArray.GetBuffer();
|
|
uint32 len = m_byteArray.GetLength();
|
|
|
|
if (len >= 3)
|
|
{
|
|
// UTF8 BOM
|
|
if ((c[0] == 0xef) && (c[1] == 0xbb) && (c[2] == 0xbf))
|
|
{
|
|
return core()->newString(((char *)c) + 3, len - 3);
|
|
}
|
|
else if ((c[0] == 0xfe) && (c[1] == 0xff))
|
|
{
|
|
//UTF-16 big endian
|
|
c += 2;
|
|
len = (len - 2) >> 1;
|
|
Stringp out = new (core()->GetGC()) String(len);
|
|
wchar *buffer = out->lockBuffer();
|
|
for (uint32 i = 0; i < len; i++)
|
|
{
|
|
buffer[i] = (c[0] << 8) + c[1];
|
|
c += 2;
|
|
}
|
|
out->unlockBuffer();
|
|
|
|
return out;
|
|
}
|
|
else if ((c[0] == 0xff) && (c[1] == 0xfe))
|
|
{
|
|
//UTF-16 little endian
|
|
c += 2;
|
|
len = (len - 2) >> 1;
|
|
Stringp out = new (core()->GetGC()) String(len);
|
|
wchar *buffer = out->lockBuffer();
|
|
for (uint32 i = 0; i < len; i++)
|
|
{
|
|
buffer[i] = (c[1] << 8) + c[0];
|
|
c += 2;
|
|
}
|
|
out->unlockBuffer();
|
|
return out;
|
|
}
|
|
}
|
|
|
|
return core()->newString(((char *)c), len);
|
|
}
|
|
|
|
int ByteArrayObject::readByte()
|
|
{
|
|
return (signed char)m_byteArray.ReadU8();
|
|
}
|
|
|
|
int ByteArrayObject::readUnsignedByte()
|
|
{
|
|
return m_byteArray.ReadU8();
|
|
}
|
|
|
|
int ByteArrayObject::readShort()
|
|
{
|
|
return (short)m_byteArray.ReadU16();
|
|
}
|
|
|
|
int ByteArrayObject::readUnsignedShort()
|
|
{
|
|
return m_byteArray.ReadU16();
|
|
}
|
|
|
|
int ByteArrayObject::readInt()
|
|
{
|
|
return (int)m_byteArray.ReadU32();
|
|
}
|
|
|
|
uint32 ByteArrayObject::readUnsignedInt()
|
|
{
|
|
return m_byteArray.ReadU32();
|
|
}
|
|
|
|
double ByteArrayObject::readFloat()
|
|
{
|
|
return m_byteArray.ReadFloat();
|
|
}
|
|
|
|
double ByteArrayObject::readDouble()
|
|
{
|
|
return m_byteArray.ReadDouble();
|
|
}
|
|
|
|
bool ByteArrayObject::readBoolean()
|
|
{
|
|
return m_byteArray.ReadBoolean();
|
|
}
|
|
|
|
void ByteArrayObject::writeBoolean(bool value)
|
|
{
|
|
m_byteArray.WriteBoolean(value);
|
|
}
|
|
|
|
void ByteArrayObject::writeByte(int value)
|
|
{
|
|
m_byteArray.WriteU8((U8)value);
|
|
}
|
|
|
|
void ByteArrayObject::writeShort(int value)
|
|
{
|
|
m_byteArray.WriteU16((unsigned short)value);
|
|
}
|
|
|
|
void ByteArrayObject::writeInt(int value)
|
|
{
|
|
m_byteArray.WriteU32((uint32)value);
|
|
}
|
|
|
|
void ByteArrayObject::writeUnsignedInt(uint32 value)
|
|
{
|
|
m_byteArray.WriteU32(value);
|
|
}
|
|
|
|
void ByteArrayObject::writeFloat(double value)
|
|
{
|
|
m_byteArray.WriteFloat((float)value);
|
|
}
|
|
|
|
void ByteArrayObject::writeDouble(double value)
|
|
{
|
|
m_byteArray.WriteDouble(value);
|
|
}
|
|
|
|
void ByteArrayObject::zlib_compress()
|
|
{
|
|
int len = m_byteArray.GetLength();
|
|
if (!len) // empty buffer should give us a empty result
|
|
return;
|
|
unsigned long gzlen = len * 3/2 + 32; // enough for growth plus zlib headers
|
|
U8 *gzdata = new U8[gzlen];
|
|
|
|
// Use zlib to compress the data
|
|
compress2((U8*)gzdata, (unsigned long*)&gzlen,
|
|
m_byteArray.GetBuffer(), len, 9);
|
|
|
|
// Replace the byte array with the compressed data
|
|
m_byteArray.SetLength(0);
|
|
//m_byteArray.WriteU32((U32)len);
|
|
m_byteArray.Write(gzdata, gzlen);
|
|
|
|
delete [] gzdata;
|
|
}
|
|
|
|
void ByteArrayObject::zlib_uncompress()
|
|
{
|
|
// Snapshot the compressed data.
|
|
unsigned long gzlen = m_byteArray.GetLength();
|
|
if (!gzlen) // empty buffer should give us a empty result
|
|
return;
|
|
|
|
U8 *gzdata = new U8[gzlen];
|
|
memcpy(gzdata, m_byteArray.GetBuffer(), gzlen);
|
|
|
|
// Clear the buffer
|
|
m_byteArray.Seek(0);
|
|
m_byteArray.SetLength(0);
|
|
|
|
// The following block is to force destruction
|
|
// of zstream before potential exception throw.
|
|
int error = Z_OK;
|
|
{
|
|
// Decompress the data
|
|
PlatformZlibStream zstream;
|
|
zstream.SetNextIn(gzdata);
|
|
zstream.SetAvailIn(gzlen);
|
|
|
|
const int kBufferSize = 8192;
|
|
U8 *buffer = new U8 [kBufferSize];
|
|
|
|
do {
|
|
zstream.SetNextOut(buffer);
|
|
zstream.SetAvailOut(kBufferSize);
|
|
error = zstream.InflateWithStatus();
|
|
m_byteArray.Write(buffer, kBufferSize-zstream.AvailOut());
|
|
} while (error == Z_OK);
|
|
|
|
delete [] buffer;
|
|
delete [] gzdata;
|
|
}
|
|
|
|
// position byte array at the beginning
|
|
m_byteArray.Seek(0);
|
|
|
|
if (error != Z_OK && error != Z_STREAM_END) {
|
|
toplevel()->throwError(kShellCompressedDataError);
|
|
}
|
|
}
|
|
|
|
void ByteArrayObject::checkNull(void *instance, const char *name)
|
|
{
|
|
if (instance == NULL) {
|
|
toplevel()->throwTypeError(kNullArgumentError, core()->toErrorString(name));
|
|
}
|
|
}
|
|
void ByteArrayObject::writeBytes(ByteArrayObject *bytes,
|
|
uint32 offset,
|
|
uint32 length)
|
|
{
|
|
checkNull(bytes, "bytes");
|
|
|
|
if (length == 0) {
|
|
length = bytes->getLength() - offset;
|
|
}
|
|
|
|
m_byteArray.WriteByteArray(bytes->GetByteArray(),
|
|
offset,
|
|
length);
|
|
}
|
|
|
|
void ByteArrayObject::readBytes(ByteArrayObject *bytes,
|
|
uint32 offset,
|
|
uint32 length)
|
|
{
|
|
checkNull(bytes, "bytes");
|
|
|
|
if (length == 0) {
|
|
length = m_byteArray.Available();
|
|
}
|
|
|
|
m_byteArray.ReadByteArray(bytes->GetByteArray(),
|
|
offset,
|
|
length);
|
|
}
|
|
|
|
String* ByteArrayObject::readUTF()
|
|
{
|
|
return m_byteArray.ReadUTF();
|
|
}
|
|
|
|
String* ByteArrayObject::readUTFBytes(uint32 length)
|
|
{
|
|
return m_byteArray.ReadUTFBytes(length);
|
|
}
|
|
|
|
void ByteArrayObject::writeUTF(String *value)
|
|
{
|
|
checkNull(value, "value");
|
|
m_byteArray.WriteUTF(value);
|
|
}
|
|
|
|
void ByteArrayObject::writeUTFBytes(String *value)
|
|
{
|
|
checkNull(value, "value");
|
|
m_byteArray.WriteUTFBytes(value);
|
|
}
|
|
|
|
void ByteArrayObject::fill(const void *b, int len)
|
|
{
|
|
m_byteArray.Write(b, len);
|
|
}
|
|
|
|
//
|
|
// ByteArrayClass
|
|
//
|
|
|
|
ByteArrayClass::ByteArrayClass(VTable *vtable)
|
|
: ClassClosure(vtable)
|
|
{
|
|
prototype = toplevel()->objectClass->construct();
|
|
}
|
|
|
|
ScriptObject* ByteArrayClass::createInstance(VTable *ivtable,
|
|
ScriptObject *prototype)
|
|
{
|
|
return new (core()->GetGC(), ivtable->getExtraSize()) ByteArrayObject(ivtable, prototype);
|
|
}
|
|
|
|
|
|
ByteArrayObject * ByteArrayClass::readFile(Stringp filename)
|
|
{
|
|
Toplevel* toplevel = this->toplevel();
|
|
if (!filename) {
|
|
toplevel->throwArgumentError(kNullArgumentError, "filename");
|
|
}
|
|
UTF8String* filenameUTF8 = filename->toUTF8String();
|
|
FILE *fp = fopen(filenameUTF8->c_str(), "rb");
|
|
if (fp == NULL) {
|
|
toplevel->throwError(kFileOpenError, filename);
|
|
}
|
|
fseek(fp, 0L, SEEK_END);
|
|
long len = ftell(fp);
|
|
rewind(fp);
|
|
|
|
unsigned char *c = new unsigned char[len+1];
|
|
|
|
Atom args[1] = {nullObjectAtom};
|
|
ByteArrayObject *b = (ByteArrayObject*)AvmCore::atomToScriptObject(construct(0,args));
|
|
b->setLength(0);
|
|
|
|
while (len > 0)
|
|
{
|
|
int actual = fread(c, 1, len, fp);
|
|
if (actual > 0)
|
|
{
|
|
b->fill(c, actual);
|
|
len -= actual;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
b->seek(0);
|
|
|
|
delete [] c;
|
|
return b;
|
|
}
|
|
|
|
Stringp ByteArrayObject::get_endian()
|
|
{
|
|
return (m_byteArray.GetEndian() == kBigEndian) ? core()->constantString("bigEndian") : core()->constantString("littleEndian");
|
|
}
|
|
|
|
void ByteArrayObject::set_endian(Stringp type)
|
|
{
|
|
AvmCore* core = this->core();
|
|
type = core->internString(type);
|
|
if (type == core->constantString("bigEndian"))
|
|
{
|
|
m_byteArray.SetEndian(kBigEndian);
|
|
}
|
|
else if (type == core->constantString("littleEndian"))
|
|
{
|
|
m_byteArray.SetEndian(kLittleEndian);
|
|
}
|
|
else
|
|
{
|
|
toplevel()->throwArgumentError(kInvalidArgumentError, "type");
|
|
}
|
|
}
|
|
|
|
void ByteArrayObject::writeFile(Stringp filename)
|
|
{
|
|
Toplevel* toplevel = this->toplevel();
|
|
if (!filename) {
|
|
toplevel->throwArgumentError(kNullArgumentError, "filename");
|
|
}
|
|
|
|
UTF8String* filenameUTF8 = filename->toUTF8String();
|
|
FILE *fp = fopen(filenameUTF8->c_str(), "wb");
|
|
if (fp == NULL) {
|
|
toplevel->throwError(kFileWriteError, filename);
|
|
}
|
|
|
|
fwrite(&(this->GetByteArray())[0], this->get_length(), 1, fp);
|
|
fclose(fp);
|
|
}
|
|
|
|
}
|
|
|
|
|