gnash-commit
[Top][All Lists]
Advanced

[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) \


reply via email to

[Prev in Thread] Current Thread [Next in Thread]