[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Gnash-commit] /srv/bzr/gnash/avm2 r9524: Rewrote CodeStream to inherit
From: |
Tom Stellard |
Subject: |
[Gnash-commit] /srv/bzr/gnash/avm2 r9524: Rewrote CodeStream to inherit from istream. Added unit tests and moved code from CodeStream.h to CodeStream.cpp |
Date: |
Sat, 23 Aug 2008 12:11:35 +0800 |
User-agent: |
Bazaar (1.5) |
------------------------------------------------------------
revno: 9524
committer: Tom Stellard <address@hidden>
branch nick: gnash_codestream
timestamp: Sat 2008-08-23 12:11:35 +0800
message:
Rewrote CodeStream to inherit from istream. Added unit tests and moved code
from CodeStream.h to CodeStream.cpp
added:
libcore/vm/CodeStream.cpp
testsuite/libcore.all/CodeStreamTest.cpp
modified:
libcore/parser/abc_block.cpp
libcore/vm/CodeStream.h
libcore/vm/Machine.cpp
libcore/vm/Makefile.am
testsuite/libcore.all/Makefile.am
=== modified file 'libcore/parser/abc_block.cpp'
--- a/libcore/parser/abc_block.cpp 2008-08-22 09:41:33 +0000
+++ b/libcore/parser/abc_block.cpp 2008-08-23 04:11:35 +0000
@@ -1082,7 +1082,7 @@
ERR((_("ABC: Only one body per method.\n")));
return false;
}
- mMethods[moffset]->setBody(new CodeStream);
+ //TODO: Read values.
// Maximum stack size.
mS->skip_V32();
@@ -1096,18 +1096,12 @@
boost::uint32_t clength = mS->read_V32();
mMethods[moffset]->setBodyLength(clength);
// The code.
- std::vector<char> body(clength);
- body.resize(clength);
- unsigned int got_length;
- if ((got_length = mS->read(&body.front(), clength)) != clength)
- {
- ERR((_("ABC: Not enough method body. Wanted %d but got
%d.\n"),
- clength, got_length));
- return false;
- }
- else{
-
mMethods[moffset]->getBody()->reInitialize(&body.front(), clength, true);
- }
+ //TODO: Clean this up.
+ std::string body;
+ mS->read_string_with_length(clength,body);
+
+ mMethods[moffset]->setBody(new CodeStream(body));
+
boost::uint32_t ecount = mS->read_V32();
for (unsigned int j = 0; j < ecount; ++j)
{
=== added file 'libcore/vm/CodeStream.cpp'
--- a/libcore/vm/CodeStream.cpp 1970-01-01 00:00:00 +0000
+++ b/libcore/vm/CodeStream.cpp 2008-08-23 04:11:35 +0000
@@ -0,0 +1,130 @@
+// CodeStream.cpp A class which allows bounds-checked reading from a char array
+//
+// Copyright (C) 2007, 2008 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+#include "CodeStream.h"
+#include <iostream>
+
+namespace gnash {
+
+/// Read a variable length encoded 32 bit unsigned integer
+boost::uint32_t
+CodeStream::read_V32()
+{
+ char data;
+
+ read(&data,1);
+ boost::uint32_t result = data;
+ if (!(result & 0x00000080)) return result;
+
+ read(&data,1);
+ result = (result & 0x0000007F) | data << 7;
+ if (!(result & 0x00004000)) return result;
+
+ read(&data,1);
+ result = (result & 0x00003FFF) | data << 14;
+ if (!(result & 0x00200000)) return result;
+
+ read(&data,1);
+ result = (result & 0x001FFFFF) | data << 21;
+ if (!(result & 0x10000000)) return result;
+
+ read(&data,1);
+ return (result & 0x0FFFFFFF) | data << 28;
+
+}
+
+/// Read an opcode for ActionScript 3
+boost::uint8_t
+CodeStream::read_as3op()
+{
+ char data;
+ read(&data,1);
+ if(eof()){
+ return 0;
+ }
+ else{
+ return static_cast<boost::uint8_t> (data);
+ }
+}
+
+/// Change the current position by a relative value.
+void
+CodeStream::seekBy(int change)
+{
+ seekg(change,ios_base::cur);
+}
+
+/// Set the current position to an absolute value (relative to the start)
+void
+CodeStream::seekTo(unsigned int set)
+{
+ seekg(set);
+}
+
+boost::int32_t
+CodeStream::read_S24()
+{
+ char buffer[3];
+ read(buffer,3);
+ uint32_t result = buffer[0];
+ result |= buffer[1] << 8;
+ result |= buffer[2] << 8;
+
+ if (result & (1 << 23)) {
+ result |= -1 << 23;
+ }
+
+ return static_cast<boost::int32_t>(result);
+}
+
+/// Read a signed 8-bit character.
+int8_t
+CodeStream::read_s8()
+{
+ char data;
+ read(&data,1);
+ return static_cast<int8_t> (data);
+}
+
+/// Read an unsigned 8-bit character.
+boost::uint8_t
+CodeStream::read_u8()
+{
+ char data;
+ read(&data,1);
+ return static_cast<boost::uint8_t> (data);
+}
+
+/// Same as read_V32(), but doesn't bother with the arithmetic for
+/// calculating the value.
+void
+CodeStream::skip_V32()
+{
+ // shortcut evalution is mandated as standard.
+ //TODO: Make this more efficient.
+// if ((*mCurrent++ & 0x80) && (*mCurrent++ & 0x80) && (*mCurrent++ &0x80)
+// && (*mCurrent++ & 0x80) && (*mCurrent++ & 0x80)){
+// return;
+// }
+ read_V32();
+ return;
+
+}
+
+} // namespace gnash
+
=== modified file 'libcore/vm/CodeStream.h'
--- a/libcore/vm/CodeStream.h 2008-08-17 13:53:33 +0000
+++ b/libcore/vm/CodeStream.h 2008-08-23 04:11:35 +0000
@@ -20,6 +20,9 @@
#define GNASH_CODESTREAM_H
#include <boost/utility.hpp>
+#include <boost/cstdint.hpp>
+#include <istream>
+#include <sstream>
namespace gnash {
@@ -32,232 +35,38 @@
/// CodeStream provides a safe interface to read various things from a
/// character array of known size. Any attempt to access memory outside
/// of the given array will throw an exception of type CodeStreamException
-class CodeStream : private boost::noncopyable
+class CodeStream : public std::istream, private boost::noncopyable
{
public:
- /// Construct a CodeStream
- ///
- /// @param pStart
- /// The beginning of the character array
- ///
- /// @param length
- /// The length of the array. Memory in [pStart, pStart + length) may
- /// be accessed. It is not an error to send a length of 0.
- ///
- /// @param own
- /// If true, the given memory will be copied. Otherwise, the caller
- /// retains ownership and should not delete the memory before this
- /// is invalid.
- CodeStream(const char *pStart, std::size_t length, bool own = false) :
- mRaw(pStart), mRawEnd(pStart + length), mEnd(pStart + length),
- mOwn(false)
- {
- if (own && length > 0)
- {
- mCurrent = mRaw = new char[length];
- memcpy(const_cast<char*>(mRaw), pStart, length);
- mRawEnd = mEnd = mRaw + length;
- mOwn = true;
- }
- }
-
- /// Construct an empty CodeStream. Call reInitialize to fill it.
- CodeStream() : mRaw(NULL), mRawEnd(NULL), mEnd(NULL), mOwn(false)
- {/**/}
-
- /// Destruct a CodeStream
- ///
- /// If the stream owns the memory, it will destroy it.
- ~CodeStream()
- { if (mOwn) delete [] mRaw; }
-
- /// Pseudo-construct a CodeStream
- ///
- /// This has the same parameters as the non-default constructor,
- /// but it can be used to re-initialize the CodeStream object.
- void reInitialize(const char *pStart, std::size_t length,
- bool own = false)
- {
- if (own)
- {
- // Delete mRaw if it's not large enough and it's ours.
- if (mOwn && length > static_cast<unsigned int> (mRawEnd
- mRaw))
- {
- mOwn = false;
- delete [] mRaw;
- }
- if (!mOwn)
- mRaw = new char [length];
- memcpy(const_cast<char *>(mRaw), pStart, length);
- mEnd = mRawEnd = pStart + length;
- mCurrent = mRaw;
- return;
- }
-
- if (mOwn)
- {
- // We own now, but don't want to.
- delete [] mRaw;
- }
- mCurrent = mRaw = pStart;
- mEnd = mRawEnd = pStart + length;
- }
-
- /// Read a variable length encoded 32 bit unsigned integer
- boost::uint32_t read_V32()
- {
- if (mCurrent == mEnd) throw CodeStreamException();
-
- // We can do an unchecked read in these cases.
- if (mEnd - mCurrent > 4 || !(*(mEnd - 1) & 0x80))
- {
- boost::uint32_t result = *mCurrent++;
- if (!(result & 0x00000080)) return result;
- result = (result & 0x0000007F) | *mCurrent++ << 7;
- if (!(result & 0x00004000)) return result;
- result = (result & 0x00003FFF) | *mCurrent++ << 14;
- if (!(result & 0x00200000)) return result;
- result = (result & 0x001FFFFF) | *mCurrent++ << 21;
- if (!(result & 0x10000000)) return result;
- return (result & 0x0FFFFFFF) | *mCurrent++ << 28;
- }
- boost::uint32_t result = *mCurrent++;
- if (!(result & 0x00000080)) return result;
- if (mCurrent == mEnd) throw CodeStreamException();
- result = (result & 0x0000007F) | *mCurrent++ << 7;
- if (!(result & 0x00004000)) return result;
- if (mCurrent == mEnd) throw CodeStreamException();
- result = (result & 0x00003FFF) | *mCurrent++ << 14;
- if (!(result & 0x00200000)) return result;
- if (mCurrent == mEnd) throw CodeStreamException();
- result = (result & 0x001FFFFF) | *mCurrent++ << 21;
- if (!(result & 0x10000000)) return result;
- if (mCurrent == mEnd) throw CodeStreamException();
- return (result & 0x0FFFFFFF) | *mCurrent++ << 28;
- }
-
- /// Read an opcode for ActionScript 3
- boost::uint8_t read_as3op()
- {
- if (mCurrent == mEnd)
- return 0;
- return static_cast<boost::uint8_t> (*mCurrent++);
- }
-
- /// Provide the offset into the stream of the current position. Can be
- /// used for seeking.
- std::size_t tell()
- { return mCurrent - mRaw; }
-
- /// Change the current position by a relative value.
- void seekBy(int change)
- {
- //This is ugly, but I don't think we have any way of knowing
what index of the stream we are at,
- //so the only way to make sure we don't go past the end of the
stream is to jump one byte at a
- //time.
- for(int i=0;i<change;i++){
- if (mCurrent == mEnd){
- throw CodeStreamException();
- }
- mCurrent ++;
- }
- }
-
- /// Set the current position to an absolute value (relative to the
start)
- void seekTo(unsigned int set)
- {
- if (set > static_cast<unsigned int> (mEnd - mRaw))
- throw CodeStreamException();
- mCurrent = mRaw + set;
- }
-
- /// Read a signed integer encoded in 24 bits.
- boost::int32_t read_S24()
- {
- if (mEnd == mCurrent)
- throw CodeStreamException();
- int result = *mCurrent++;
- if(mEnd == mCurrent)
- throw CodeStreamException();
- result += (*mCurrent++ << 8);
- if(mEnd== mCurrent)
- throw CodeStreamException();
- result += (*mCurrent ++ << 16);
- if (result & (1 << 23)) // Negative result, adjust
appropriately.
- result = -(result & ~(1 << 23));
- return static_cast<boost::int32_t>(result);
- }
-
- /// Read a signed 8-bit character.
- int8_t read_s8()
- {
- if (mCurrent == mEnd)
- throw CodeStreamException();
- return static_cast<int8_t> (*mCurrent++);
- }
-
- /// Read an unsigned 8-bit character.
- boost::uint8_t read_u8()
- {
- if (mCurrent == mEnd)
- throw CodeStreamException();
- return static_cast<boost::uint8_t> (*mCurrent++);
- }
-
- /// Set a stop at position bytes from the start. This becomes the new
- /// effective end of the code stream, but the end may be unstopped or
- /// set to different length. In no case can the end be set to a point
- /// beyond the original end of the stream.
- void set_end(unsigned int position)
- {
- if (position > static_cast<unsigned int>(mRawEnd - mRaw))
- throw CodeStreamException();
- mEnd = mRaw + position;
- if (mCurrent > mEnd)
- mCurrent = mEnd;
- }
-
- /// Unset any stop placed on the stream.
- void unset_end()
- { mEnd = mRawEnd; }
-
- /// Take ownership of mRaw. mRaw should be a block which can be
- /// de-allocated by calling delete [] mRaw
- void takeMemoryOwnership()
- { mOwn = true; }
-
- /// Same as read_V32(), but doesn't bother with the arithmetic for
- /// calculating the value.
- void skip_V32()
- {
- if (mCurrent == mEnd) throw CodeStreamException();
-
- // We can do an unchecked read in these cases.
- if (mEnd - mCurrent > 4 || !(*(mEnd - 1) & 0x80))
- {
- // shortcut evalution is mandated as standard.
- if ((*mCurrent++ & 0x80) && (*mCurrent++ & 0x80) &&
(*mCurrent++ &0x80)
- && (*mCurrent++ & 0x80) && (*mCurrent++ & 0x80))
- return;
- return;
- }
- if (!(*mCurrent++ & 0x80)) return;
- if (mCurrent == mEnd) throw CodeStreamException();
- if (!(*mCurrent++ & 0x80)) return;
- if (mCurrent == mEnd) throw CodeStreamException();
- if (!(*mCurrent++ & 0x80)) return;
- if (mCurrent == mEnd) throw CodeStreamException();
- if (!(*mCurrent++ & 0x80)) return;
- if (mCurrent == mEnd) throw CodeStreamException();
- ++mCurrent;
- }
-
-private:
- const char *mRaw; // Nobody may write into this, and we handle all
access.
- const char *mRawEnd; // We own the memory in [mRaw, mRawEnd)
- const char *mEnd; // We may not read this or beyond.
- const char *mCurrent; // Our current read pointer.
- bool mOwn; // Do we own the memory?
+ CodeStream(std::string data): std::istream(new std::stringbuf(data)){
+
+ }
+
+/// Read a variable length encoded 32 bit unsigned integer
+boost::uint32_t read_V32();
+
+/// Read an opcode for ActionScript 3
+boost::uint8_t read_as3op();
+
+/// Change the current position by a relative value.
+void seekBy(int change);
+
+/// Set the current position to an absolute value (relative to the start)
+void seekTo(unsigned int set);
+
+///Read a signed 24 bit interger.
+boost::int32_t read_S24();
+
+/// Read a signed 8-bit character.
+int8_t read_s8();
+
+/// Read an unsigned 8-bit character.
+boost::uint8_t read_u8();
+
+/// Same as read_V32(), but doesn't bother with the arithmetic for
+/// calculating the value.
+void skip_V32();
+
};
} // namespace gnash
=== modified file 'libcore/vm/Machine.cpp'
--- a/libcore/vm/Machine.cpp 2008-08-22 15:57:06 +0000
+++ b/libcore/vm/Machine.cpp 2008-08-23 04:11:35 +0000
@@ -270,7 +270,7 @@
for ( ; ; )
{
- std::size_t opStart = mStream->tell();
+ std::size_t opStart = mStream->tellg();
// std::size_t opStart = mStreamStack.top(0)->tell();
if (1/*mIsAS3*/)
{
@@ -672,7 +672,7 @@
/// Otherwise, move by cases[index] - 1 from stream position on op entry.
case SWF::ABC_ACTION_LOOKUPSWITCH:
{
- std::size_t npos = mStream->tell();
+ std::size_t npos = mStream->tellg();
if (!mStack.top(0).is_number())
throw ASException();
=== modified file 'libcore/vm/Makefile.am'
--- a/libcore/vm/Makefile.am 2008-07-22 21:24:49 +0000
+++ b/libcore/vm/Makefile.am 2008-08-23 04:11:35 +0000
@@ -45,6 +45,7 @@
ActionExec.cpp \
VM.cpp \
action.cpp \
+ CodeStream.cpp \
$(NULL)
noinst_HEADERS = \
=== added file 'testsuite/libcore.all/CodeStreamTest.cpp'
--- a/testsuite/libcore.all/CodeStreamTest.cpp 1970-01-01 00:00:00 +0000
+++ b/testsuite/libcore.all/CodeStreamTest.cpp 2008-08-23 04:11:35 +0000
@@ -0,0 +1,92 @@
+//
+// Copyright (C) 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+#ifdef HAVE_CONFIG_H
+#include "gnashconfig.h"
+#endif
+
+#include "CodeStream.h"
+#include "log.h"
+
+#include <iostream>
+#include <sstream>
+#include <cassert>
+#include <cmath>
+#include <string>
+
+#include "check.h"
+
+#include "utility.h"
+
+using namespace gnash;
+using std::cout;
+using std::endl;
+
+int
+main(int /*argc*/, char** /*argv*/)
+{
+ char data[10] = {0x4,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9};
+
+ CodeStream* stream = new CodeStream(std::string(data,10));
+
+ //Test read_as30p()
+ boost::uint8_t opcode;
+ int i = 0;
+ while(opcode = stream->read_as3op()){
+ check_equals(opcode,data[i]);
+ i++;
+ }
+
+ //Make sure we stopped at the right spot.
+ check_equals(i,10);
+
+ //Reset stream.
+ stream->seekTo(0);
+ stream->clear();
+
+ //Test seekTo
+ stream->seekTo(5);
+
+ opcode = stream->read_as3op();
+ check_equals(opcode,data[5]);
+
+ //Reset stream.
+ stream->seekTo(0);
+ stream->clear();
+
+ //Test read_u8.
+ i=0;
+ while(i<10){
+ opcode = stream->read_u8();
+ check_equals(opcode,data[i]);
+ i++;
+ }
+
+ char newData[6] = {0x5,0xC5,0x0,0x0,0x1,0x2};
+ CodeStream* streamA = new CodeStream(std::string(newData,6));
+
+ boost::uint8_t byteA = streamA->read_u8();
+ check_equals(byteA,newData[0]);
+
+ //Test read_S24.
+ boost::int32_t byteB = streamA->read_S24();
+ check_equals(byteB,newData[1]);
+
+
+
+
+}
\ No newline at end of file
=== modified file 'testsuite/libcore.all/Makefile.am'
--- a/testsuite/libcore.all/Makefile.am 2008-08-05 03:45:40 +0000
+++ b/testsuite/libcore.all/Makefile.am 2008-08-23 04:11:35 +0000
@@ -40,6 +40,7 @@
AsValueTest \
ClassSizes \
SafeStackTest \
+ CodeStreamTest \
$(NULL)
CLEANFILES = \
@@ -115,6 +116,11 @@
$(GNASH_LIBS) \
$(NULL)
+CodeStreamTest_SOURCES = CodeStreamTest.cpp
+CodeStreamTest_LDADD = \
+ $(GNASH_LIBS) \
+ $(NULL)
+
TEST_DRIVERS = ../simple.exp
TEST_CASES = \
$(check_PROGRAMS) \
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Gnash-commit] /srv/bzr/gnash/avm2 r9524: Rewrote CodeStream to inherit from istream. Added unit tests and moved code from CodeStream.h to CodeStream.cpp,
Tom Stellard <=