swfmill 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +23 -0
- data/.swfmill +240 -0
- data/LICENSE +340 -0
- data/README.rdoc +37 -0
- data/Rakefile +59 -0
- data/VERSION +1 -0
- data/ext/.gitignore +5 -0
- data/ext/extconf.rb +86 -0
- data/ext/swfmill/.gitignore +27 -0
- data/ext/swfmill/AUTHORS +9 -0
- data/ext/swfmill/COPYING +340 -0
- data/ext/swfmill/Makefile.am +14 -0
- data/ext/swfmill/Makefile.in +635 -0
- data/ext/swfmill/NEWS +189 -0
- data/ext/swfmill/README +170 -0
- data/ext/swfmill/TODO +33 -0
- data/ext/swfmill/aclocal.m4 +7712 -0
- data/ext/swfmill/autogen.sh +7 -0
- data/ext/swfmill/compile +142 -0
- data/ext/swfmill/config.guess +1516 -0
- data/ext/swfmill/config.sub +1626 -0
- data/ext/swfmill/configure +21868 -0
- data/ext/swfmill/configure.ac +55 -0
- data/ext/swfmill/depcomp +589 -0
- data/ext/swfmill/install-sh +519 -0
- data/ext/swfmill/ltmain.sh +6964 -0
- data/ext/swfmill/missing +367 -0
- data/ext/swfmill/src/Geom.cpp +107 -0
- data/ext/swfmill/src/Geom.h +100 -0
- data/ext/swfmill/src/Makefile.am +86 -0
- data/ext/swfmill/src/Makefile.in +1025 -0
- data/ext/swfmill/src/SWF.h +11941 -0
- data/ext/swfmill/src/SWFAction.cpp +41 -0
- data/ext/swfmill/src/SWFAction.h +19 -0
- data/ext/swfmill/src/SWFBasic.h +7 -0
- data/ext/swfmill/src/SWFFile.cpp +406 -0
- data/ext/swfmill/src/SWFFile.h +34 -0
- data/ext/swfmill/src/SWFFilter.cpp +25 -0
- data/ext/swfmill/src/SWFFilter.h +15 -0
- data/ext/swfmill/src/SWFGlyphList.cpp +262 -0
- data/ext/swfmill/src/SWFGlyphList.h +34 -0
- data/ext/swfmill/src/SWFIdItem.h +85 -0
- data/ext/swfmill/src/SWFIdItems.h +16 -0
- data/ext/swfmill/src/SWFItem.cpp +235 -0
- data/ext/swfmill/src/SWFItem.h +60 -0
- data/ext/swfmill/src/SWFList.h +179 -0
- data/ext/swfmill/src/SWFReader.cpp +352 -0
- data/ext/swfmill/src/SWFReader.h +73 -0
- data/ext/swfmill/src/SWFShapeItem.cpp +220 -0
- data/ext/swfmill/src/SWFShapeItem.h +45 -0
- data/ext/swfmill/src/SWFShapeMaker.cpp +401 -0
- data/ext/swfmill/src/SWFShapeMaker.h +128 -0
- data/ext/swfmill/src/SWFTag.cpp +49 -0
- data/ext/swfmill/src/SWFTag.h +20 -0
- data/ext/swfmill/src/SWFTrait.cpp +35 -0
- data/ext/swfmill/src/SWFTrait.h +22 -0
- data/ext/swfmill/src/SWFWriter.cpp +312 -0
- data/ext/swfmill/src/SWFWriter.h +84 -0
- data/ext/swfmill/src/base64.c +110 -0
- data/ext/swfmill/src/base64.h +15 -0
- data/ext/swfmill/src/codegen/Makefile.am +15 -0
- data/ext/swfmill/src/codegen/Makefile.in +346 -0
- data/ext/swfmill/src/codegen/basic.xsl +45 -0
- data/ext/swfmill/src/codegen/basics.xsl +235 -0
- data/ext/swfmill/src/codegen/dumper.xsl +109 -0
- data/ext/swfmill/src/codegen/header.xsl +131 -0
- data/ext/swfmill/src/codegen/mk.xsl +26 -0
- data/ext/swfmill/src/codegen/parser.xsl +196 -0
- data/ext/swfmill/src/codegen/parsexml.xsl +312 -0
- data/ext/swfmill/src/codegen/size.xsl +189 -0
- data/ext/swfmill/src/codegen/source.xml +2197 -0
- data/ext/swfmill/src/codegen/writer.xsl +190 -0
- data/ext/swfmill/src/codegen/writexml.xsl +138 -0
- data/ext/swfmill/src/swfmill.cpp +482 -0
- data/ext/swfmill/src/swft/Makefile.am +55 -0
- data/ext/swfmill/src/swft/Makefile.in +717 -0
- data/ext/swfmill/src/swft/Parser.cpp +76 -0
- data/ext/swfmill/src/swft/Parser.h +37 -0
- data/ext/swfmill/src/swft/SVGAttributeParser.cpp +78 -0
- data/ext/swfmill/src/swft/SVGAttributeParser.h +35 -0
- data/ext/swfmill/src/swft/SVGColor.cpp +116 -0
- data/ext/swfmill/src/swft/SVGColor.h +37 -0
- data/ext/swfmill/src/swft/SVGColors.h +167 -0
- data/ext/swfmill/src/swft/SVGGradient.cpp +258 -0
- data/ext/swfmill/src/swft/SVGGradient.h +81 -0
- data/ext/swfmill/src/swft/SVGPathParser.cpp +155 -0
- data/ext/swfmill/src/swft/SVGPathParser.h +126 -0
- data/ext/swfmill/src/swft/SVGPointsParser.cpp +51 -0
- data/ext/swfmill/src/swft/SVGPointsParser.h +25 -0
- data/ext/swfmill/src/swft/SVGStyle.cpp +181 -0
- data/ext/swfmill/src/swft/SVGStyle.h +80 -0
- data/ext/swfmill/src/swft/SVGTransformParser.cpp +72 -0
- data/ext/swfmill/src/swft/SVGTransformParser.h +32 -0
- data/ext/swfmill/src/swft/readpng.c +305 -0
- data/ext/swfmill/src/swft/readpng.h +92 -0
- data/ext/swfmill/src/swft/swft.cpp +251 -0
- data/ext/swfmill/src/swft/swft.h +64 -0
- data/ext/swfmill/src/swft/swft_document.cpp +57 -0
- data/ext/swfmill/src/swft/swft_import.cpp +38 -0
- data/ext/swfmill/src/swft/swft_import_binary.cpp +82 -0
- data/ext/swfmill/src/swft/swft_import_jpeg.cpp +255 -0
- data/ext/swfmill/src/swft/swft_import_mp3.cpp +268 -0
- data/ext/swfmill/src/swft/swft_import_png.cpp +231 -0
- data/ext/swfmill/src/swft/swft_import_ttf.cpp +519 -0
- data/ext/swfmill/src/swft/swft_import_wav.cpp +255 -0
- data/ext/swfmill/src/swft/swft_path.cpp +178 -0
- data/ext/swfmill/src/xslt/Makefile.am +51 -0
- data/ext/swfmill/src/xslt/Makefile.in +536 -0
- data/ext/swfmill/src/xslt/README +19 -0
- data/ext/swfmill/src/xslt/assemble.xsl +38 -0
- data/ext/swfmill/src/xslt/simple-deprecated.xslt +62 -0
- data/ext/swfmill/src/xslt/simple-elements.xslt +627 -0
- data/ext/swfmill/src/xslt/simple-import.xslt +565 -0
- data/ext/swfmill/src/xslt/simple-svg.xslt +383 -0
- data/ext/swfmill/src/xslt/simple-tools.xslt +255 -0
- data/ext/swfmill/src/xslt/simple.cpp +1686 -0
- data/ext/swfmill/src/xslt/simple.xml +7 -0
- data/ext/swfmill/src/xslt/xslt.h +7 -0
- data/ext/swfmill/test/Makefile.am +1 -0
- data/ext/swfmill/test/Makefile.in +490 -0
- data/ext/swfmill/test/xml/Makefile.am +20 -0
- data/ext/swfmill/test/xml/Makefile.in +353 -0
- data/ext/swfmill/test/xml/test-xml +21 -0
- data/ext/swfmill_ext.cc +375 -0
- data/lib/swfmill.rb +30 -0
- data/spec/data/swfmill-banner1.swf +0 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +14 -0
- data/spec/swfmill_spec.rb +125 -0
- metadata +206 -0
@@ -0,0 +1,16 @@
|
|
1
|
+
#ifndef SWF_IDITEMS_H
|
2
|
+
#define SWF_IDITEMS_H
|
3
|
+
|
4
|
+
#include <SWFIdItem.h>
|
5
|
+
|
6
|
+
namespace SWF {
|
7
|
+
|
8
|
+
class StackItem : public IdItem<StackItem> {};
|
9
|
+
class Style : public IdItem<Style> {};
|
10
|
+
class NamespaceConstant : public IdItem<NamespaceConstant> {};
|
11
|
+
class MultinameConstant : public IdItem<MultinameConstant> {};
|
12
|
+
class OpCode : public IdItem<OpCode> {};
|
13
|
+
|
14
|
+
}
|
15
|
+
#endif
|
16
|
+
|
@@ -0,0 +1,235 @@
|
|
1
|
+
#include "SWFItem.h"
|
2
|
+
#include <cstring>
|
3
|
+
#include <cctype>
|
4
|
+
#include "base64.h"
|
5
|
+
#include <sys/types.h>
|
6
|
+
|
7
|
+
namespace SWF {
|
8
|
+
|
9
|
+
// ------------ utility functions
|
10
|
+
|
11
|
+
int swf_get_bits_needed_for_uint( uint64_t value ) {
|
12
|
+
int i=0;
|
13
|
+
while( value > 0 ) {
|
14
|
+
value >>= 1;
|
15
|
+
i++;
|
16
|
+
}
|
17
|
+
return i;
|
18
|
+
}
|
19
|
+
|
20
|
+
int swf_get_bits_needed_for_int( int64_t value ) {
|
21
|
+
if( value < 0 )
|
22
|
+
/* XXX one more than necessary if num = -2^n */
|
23
|
+
return swf_get_bits_needed_for_uint( -value ) + 1;
|
24
|
+
else if ( value > 0 )
|
25
|
+
return swf_get_bits_needed_for_uint( value ) + 1;
|
26
|
+
else
|
27
|
+
return 0;
|
28
|
+
}
|
29
|
+
|
30
|
+
int swf_get_bits_needed_for_fp( double value ) {
|
31
|
+
return swf_get_bits_needed_for_int( (int64_t)(value * 65536.0) );
|
32
|
+
}
|
33
|
+
|
34
|
+
int SWFBitsNeeded( int32_t value, bool is_signed ) {
|
35
|
+
if( is_signed )
|
36
|
+
return swf_get_bits_needed_for_int( value );
|
37
|
+
else
|
38
|
+
return swf_get_bits_needed_for_uint( value );
|
39
|
+
/*
|
40
|
+
long cnt;
|
41
|
+
if( is_signed ) {
|
42
|
+
if(value < 0) {
|
43
|
+
// a special case
|
44
|
+
if(value == -1) {
|
45
|
+
return 1;
|
46
|
+
}
|
47
|
+
cnt = 33;
|
48
|
+
do {
|
49
|
+
cnt--;
|
50
|
+
value *= 2;
|
51
|
+
} while(value < 0);
|
52
|
+
if( value == 0 ) return cnt+1;
|
53
|
+
}
|
54
|
+
else {
|
55
|
+
// a special case
|
56
|
+
if(value == 0) {
|
57
|
+
return 1;
|
58
|
+
}
|
59
|
+
cnt = 33;
|
60
|
+
do {
|
61
|
+
cnt--;
|
62
|
+
value *= 2;
|
63
|
+
} while(value > 0);
|
64
|
+
if( value == 0 ) return cnt+1;
|
65
|
+
}
|
66
|
+
} else {
|
67
|
+
if( value < 0 ) {
|
68
|
+
printf("ERROR: unsigned, but <0? %s:%i\n", __FILE__, __LINE__);
|
69
|
+
abort();
|
70
|
+
}
|
71
|
+
// a special case
|
72
|
+
if(value == 0) {
|
73
|
+
return 1;
|
74
|
+
}
|
75
|
+
cnt = 32;
|
76
|
+
while((long) value > 0) {
|
77
|
+
cnt--;
|
78
|
+
value *= 2;
|
79
|
+
}
|
80
|
+
if( value == 0 ) return cnt+1;
|
81
|
+
}
|
82
|
+
return cnt;
|
83
|
+
*/
|
84
|
+
}
|
85
|
+
|
86
|
+
long SWFMaxBitsNeeded( bool is_signed, int how_many, ... ) {
|
87
|
+
long bits = 0;
|
88
|
+
va_list ap;
|
89
|
+
int n;
|
90
|
+
va_start( ap, how_many );
|
91
|
+
|
92
|
+
for( int i=0; i<how_many; i++ ) {
|
93
|
+
int b = SWFBitsNeeded( va_arg( ap, int ), is_signed );
|
94
|
+
if( b > bits ) bits = b;
|
95
|
+
}
|
96
|
+
|
97
|
+
va_end( ap );
|
98
|
+
return bits;
|
99
|
+
}
|
100
|
+
|
101
|
+
Item::Item() {
|
102
|
+
file_offset = -1;
|
103
|
+
cached_size = -1;
|
104
|
+
}
|
105
|
+
|
106
|
+
size_t Item::getSize( Context *ctx, int start_at ) {
|
107
|
+
if( cached_size == -1 ) {
|
108
|
+
cached_size = calcSize( ctx, start_at );
|
109
|
+
}
|
110
|
+
return cached_size;
|
111
|
+
}
|
112
|
+
|
113
|
+
int Item::getHeaderSize( int size ) {
|
114
|
+
return 0;
|
115
|
+
}
|
116
|
+
|
117
|
+
void Item::writeHeader( Writer *w, Context *ctx, size_t len ) {
|
118
|
+
}
|
119
|
+
|
120
|
+
|
121
|
+
|
122
|
+
Rest::Rest() {
|
123
|
+
size = 0;
|
124
|
+
data = NULL;
|
125
|
+
}
|
126
|
+
|
127
|
+
Rest::~Rest() {
|
128
|
+
delete[] data;
|
129
|
+
}
|
130
|
+
|
131
|
+
bool Rest::parse( Reader *r, int end, Context *ctx ) {
|
132
|
+
file_offset = r->getPosition();
|
133
|
+
|
134
|
+
size = end - r->getPosition();
|
135
|
+
if( size > 0 ) {
|
136
|
+
data = new unsigned char[size];
|
137
|
+
r->getData( data, size );
|
138
|
+
}
|
139
|
+
|
140
|
+
return r->getError() == SWFR_OK;
|
141
|
+
}
|
142
|
+
|
143
|
+
void Rest::dump( int indent, Context *ctx ) {
|
144
|
+
for( int i=0; i<indent; i++ ) printf(" ");
|
145
|
+
printf("Rest (length %i)\n", size);
|
146
|
+
if( size && data != NULL ) {
|
147
|
+
int i=0;
|
148
|
+
while( i<size ) {
|
149
|
+
for( int in=0; in<indent+1; in++ ) printf(" ");
|
150
|
+
for( int n=0; n<8 && i<size; n++ ) {
|
151
|
+
printf(" %02X", data[i] );
|
152
|
+
i++;
|
153
|
+
}
|
154
|
+
printf("\n");
|
155
|
+
}
|
156
|
+
}
|
157
|
+
}
|
158
|
+
|
159
|
+
size_t Rest::calcSize( Context *ctx, int start_at ) {
|
160
|
+
int r = start_at;
|
161
|
+
r += size * 8;
|
162
|
+
r += Item::getHeaderSize(r-start_at);
|
163
|
+
return r-start_at;
|
164
|
+
}
|
165
|
+
|
166
|
+
void Rest::write( Writer *w, Context *ctx ) {
|
167
|
+
Item::writeHeader( w, ctx, 0 );
|
168
|
+
|
169
|
+
if( size && data ) {
|
170
|
+
w->putData( data, size );
|
171
|
+
}
|
172
|
+
}
|
173
|
+
|
174
|
+
#define TMP_STRLEN 0xFF
|
175
|
+
void Rest::writeXML( xmlNodePtr xml, Context *ctx ) {
|
176
|
+
char tmp[TMP_STRLEN];
|
177
|
+
xmlNodePtr node = xml;
|
178
|
+
|
179
|
+
// node = xmlNewChild( node, NULL, (const xmlChar *)"Rest", NULL );
|
180
|
+
{
|
181
|
+
if( size && data ) {
|
182
|
+
char *tmp_data = (char *)data;
|
183
|
+
int sz = size;
|
184
|
+
char *tmpstr = new char[ (sz * 3) ];
|
185
|
+
|
186
|
+
int l = base64_encode( tmpstr, tmp_data, sz );
|
187
|
+
if( l > 0 ) {
|
188
|
+
tmpstr[l] = 0;
|
189
|
+
xmlNewTextChild( node, NULL, (const xmlChar *)"data", (const xmlChar *)tmpstr );
|
190
|
+
}
|
191
|
+
delete[] tmpstr;
|
192
|
+
}
|
193
|
+
}
|
194
|
+
}
|
195
|
+
|
196
|
+
void Rest::parseXML( xmlNodePtr node, Context *ctx ) {
|
197
|
+
data = NULL;
|
198
|
+
size = 0;
|
199
|
+
|
200
|
+
xmlChar *xmld = xmlNodeGetContent( node );
|
201
|
+
char *d = (char *)xmld;
|
202
|
+
if( d ) {
|
203
|
+
// unsure if this is neccessary
|
204
|
+
for( int i=strlen(d)-1; i>0 && isspace(d[i]); i-- ) d[i]=0;
|
205
|
+
while( isspace(d[0]) ) d++;
|
206
|
+
int l = strlen(d);
|
207
|
+
char *dst = new char[ l ];
|
208
|
+
int lout = base64_decode( dst, (char*)d, l );
|
209
|
+
if( lout > 0 ) {
|
210
|
+
size = lout;
|
211
|
+
data = new unsigned char[ lout ];
|
212
|
+
memcpy( data, dst, lout );
|
213
|
+
}
|
214
|
+
delete[] dst;
|
215
|
+
xmlFree( xmld );
|
216
|
+
}
|
217
|
+
}
|
218
|
+
|
219
|
+
void Rest::getdata( unsigned char **d, int *s ) {
|
220
|
+
*d = data;
|
221
|
+
*s = size;
|
222
|
+
}
|
223
|
+
|
224
|
+
void Rest::setdata( unsigned char *d, int s ) {
|
225
|
+
delete[] data;
|
226
|
+
data = NULL;
|
227
|
+
size = s;
|
228
|
+
|
229
|
+
if( size ) {
|
230
|
+
data = new unsigned char[ size ];
|
231
|
+
memcpy( data, d, size );
|
232
|
+
}
|
233
|
+
}
|
234
|
+
|
235
|
+
}
|
@@ -0,0 +1,60 @@
|
|
1
|
+
#ifndef SWF_ITEM_H
|
2
|
+
#define SWF_ITEM_H
|
3
|
+
|
4
|
+
#include <SWFReader.h>
|
5
|
+
#include <SWFWriter.h>
|
6
|
+
#include <libxml/tree.h>
|
7
|
+
|
8
|
+
namespace SWF {
|
9
|
+
|
10
|
+
class Context;
|
11
|
+
|
12
|
+
int SWFBitsNeeded( int32_t value, bool is_signed = false );
|
13
|
+
long SWFMaxBitsNeeded( bool is_signed, int how_many, ... );
|
14
|
+
|
15
|
+
class Item {
|
16
|
+
public:
|
17
|
+
Item();
|
18
|
+
virtual ~Item() {}
|
19
|
+
|
20
|
+
virtual bool parse( Reader *r, int end, Context *ctx ) = 0;
|
21
|
+
virtual void dump( int indent, Context *ctx ) = 0;
|
22
|
+
virtual size_t calcSize( Context *ctx, int start_at ) = 0;
|
23
|
+
virtual void write( Writer *r, Context *ctx ) = 0;
|
24
|
+
|
25
|
+
virtual void writeXML( xmlNodePtr xml, Context *ctx ) = 0;
|
26
|
+
virtual void parseXML( xmlNodePtr xml, Context *ctx ) = 0;
|
27
|
+
|
28
|
+
// wont touch the context if size is cached.
|
29
|
+
size_t getSize( Context *ctx, int start_at );
|
30
|
+
|
31
|
+
protected:
|
32
|
+
int getHeaderSize( int size );
|
33
|
+
void writeHeader( Writer *w, Context *ctx, size_t len );
|
34
|
+
|
35
|
+
int file_offset; // bytes after header for SWF, line for XML (NYI)
|
36
|
+
int cached_size; // cached size
|
37
|
+
};
|
38
|
+
|
39
|
+
// to save the rest of a tag as binary data...
|
40
|
+
class Rest : public Item {
|
41
|
+
public:
|
42
|
+
Rest();
|
43
|
+
virtual ~Rest();
|
44
|
+
virtual bool parse( Reader *r, int end, Context *ctx );
|
45
|
+
virtual void dump( int indent, Context *ctx );
|
46
|
+
virtual size_t calcSize( Context *ctx, int start_at );
|
47
|
+
virtual void write( Writer *w, Context *ctx );
|
48
|
+
virtual void writeXML( xmlNodePtr node, Context *ctx );
|
49
|
+
virtual void parseXML( xmlNodePtr node, Context *ctx );
|
50
|
+
|
51
|
+
void getdata( unsigned char **data, int *size );
|
52
|
+
void setdata( unsigned char *data, int size );
|
53
|
+
|
54
|
+
protected:
|
55
|
+
int size;
|
56
|
+
unsigned char *data;
|
57
|
+
};
|
58
|
+
|
59
|
+
}
|
60
|
+
#endif
|
@@ -0,0 +1,179 @@
|
|
1
|
+
#ifndef F_List_H
|
2
|
+
#define F_List_H
|
3
|
+
|
4
|
+
#include <cstdio>
|
5
|
+
#define WARNING printf
|
6
|
+
|
7
|
+
namespace SWF {
|
8
|
+
|
9
|
+
template <class T> class ListItem;
|
10
|
+
|
11
|
+
/*
|
12
|
+
a simple (likely non-threadsafe) LinkedList
|
13
|
+
*/
|
14
|
+
|
15
|
+
template <class T>
|
16
|
+
class List {
|
17
|
+
public:
|
18
|
+
List( bool ownership = true )
|
19
|
+
: mOwnership( ownership ) {
|
20
|
+
mFirst = mLast = NULL;
|
21
|
+
}
|
22
|
+
~List() {
|
23
|
+
ListItem<T> *item = mFirst, *next;
|
24
|
+
if( mOwnership ) {
|
25
|
+
while( item ) {
|
26
|
+
if( item->data() ) delete item->data();
|
27
|
+
next = item->next();
|
28
|
+
delete item;
|
29
|
+
item = next;
|
30
|
+
}
|
31
|
+
} else {
|
32
|
+
while( item ) {
|
33
|
+
next = item->next();
|
34
|
+
delete item;
|
35
|
+
item = next;
|
36
|
+
}
|
37
|
+
}
|
38
|
+
}
|
39
|
+
|
40
|
+
ListItem<T> *append( T *data, void *user_data = NULL ) {
|
41
|
+
if( !mLast ) {
|
42
|
+
if( !mFirst ) {
|
43
|
+
return mFirst = mLast = new ListItem<T>( data, NULL, user_data );
|
44
|
+
} else {
|
45
|
+
WARNING("Linked List has First but no Last item\n");
|
46
|
+
return NULL;
|
47
|
+
}
|
48
|
+
} else {
|
49
|
+
return mLast = new ListItem<T>( data, mLast, user_data );
|
50
|
+
}
|
51
|
+
}
|
52
|
+
|
53
|
+
ListItem<T> *prepend( T *data, void *user_data = NULL ) {
|
54
|
+
if( !mFirst ) {
|
55
|
+
return mFirst = mLast = new ListItem<T>( data, NULL, user_data );
|
56
|
+
} else {
|
57
|
+
ListItem<T> *item = new ListItem<T>( data, NULL, user_data );
|
58
|
+
item->mNext = mFirst;
|
59
|
+
mFirst->mPrevious = item;
|
60
|
+
return mFirst = item;
|
61
|
+
}
|
62
|
+
}
|
63
|
+
|
64
|
+
ListItem<T> *prepend2( T *data, void *user_data = NULL ) {
|
65
|
+
if( !mFirst ) {
|
66
|
+
return mFirst = mLast = new ListItem<T>( data, NULL, user_data );
|
67
|
+
} else {
|
68
|
+
return new ListItem<T>( data, mFirst, user_data );
|
69
|
+
}
|
70
|
+
}
|
71
|
+
|
72
|
+
T* remove( ListItem<T> *item ) {
|
73
|
+
item->remove( this );
|
74
|
+
T *ret = item->data();
|
75
|
+
if( mOwnership && item->data() ) {
|
76
|
+
delete item->data();
|
77
|
+
ret = NULL;
|
78
|
+
}
|
79
|
+
delete item;
|
80
|
+
return ret;
|
81
|
+
}
|
82
|
+
|
83
|
+
void moveToLast( ListItem<T> *item ) {
|
84
|
+
if( item == mLast ) return;
|
85
|
+
item->remove( this );
|
86
|
+
item->mPrevious = mLast;
|
87
|
+
if( mLast ) {
|
88
|
+
mLast->mNext = item;
|
89
|
+
}
|
90
|
+
mLast = item;
|
91
|
+
if( !mFirst ) mFirst = item;
|
92
|
+
}
|
93
|
+
|
94
|
+
ListItem<T> *first() { return mFirst; };
|
95
|
+
ListItem<T> *last() { return mLast; };
|
96
|
+
|
97
|
+
friend class ListItem<T>;
|
98
|
+
|
99
|
+
int size() {
|
100
|
+
if (mFirst == NULL) return 0;
|
101
|
+
if (mFirst == mLast) return 1;
|
102
|
+
|
103
|
+
int count = 1;
|
104
|
+
ListItem<T> *item = mFirst;
|
105
|
+
while(item != mLast) {
|
106
|
+
count++;
|
107
|
+
item = item->next();
|
108
|
+
}
|
109
|
+
|
110
|
+
return count;
|
111
|
+
}
|
112
|
+
|
113
|
+
protected:
|
114
|
+
ListItem<T> *mFirst;
|
115
|
+
ListItem<T> *mLast;
|
116
|
+
bool mOwnership;
|
117
|
+
};
|
118
|
+
|
119
|
+
template <class T>
|
120
|
+
class ListItem {
|
121
|
+
public:
|
122
|
+
ListItem( T *data, ListItem* insertAfter = NULL, void *user_data = NULL ) {
|
123
|
+
mData = data;
|
124
|
+
mPrevious = insertAfter;
|
125
|
+
mNext = insertAfter ? insertAfter->replaceNext( this ) : NULL;
|
126
|
+
if( mNext ) mNext->mPrevious = this;
|
127
|
+
mUserData = user_data;
|
128
|
+
}
|
129
|
+
|
130
|
+
ListItem *replaceNext( ListItem *next ) {
|
131
|
+
ListItem *ret = mNext;
|
132
|
+
mNext = next;
|
133
|
+
return ret;
|
134
|
+
}
|
135
|
+
|
136
|
+
void remove( List<T> *list ) {
|
137
|
+
if( !mPrevious ) list->mFirst = mNext;
|
138
|
+
else mPrevious->mNext = mNext;
|
139
|
+
if( !mNext ) list->mLast = mPrevious;
|
140
|
+
else mNext->mPrevious = mPrevious;
|
141
|
+
mPrevious = mNext = NULL;
|
142
|
+
}
|
143
|
+
|
144
|
+
ListItem *next() {
|
145
|
+
return( mNext );
|
146
|
+
}
|
147
|
+
|
148
|
+
ListItem *previous() {
|
149
|
+
return( mPrevious );
|
150
|
+
}
|
151
|
+
|
152
|
+
T* data() {
|
153
|
+
return( mData );
|
154
|
+
}
|
155
|
+
|
156
|
+
void* UserData() {
|
157
|
+
return( mUserData );
|
158
|
+
}
|
159
|
+
|
160
|
+
bool isLast() {
|
161
|
+
return( mNext == 0 );
|
162
|
+
}
|
163
|
+
bool isFirst() {
|
164
|
+
return( mPrevious == 0 );
|
165
|
+
}
|
166
|
+
|
167
|
+
friend class List<T>;
|
168
|
+
|
169
|
+
protected:
|
170
|
+
ListItem *mPrevious;
|
171
|
+
ListItem *mNext;
|
172
|
+
T *mData;
|
173
|
+
void *mUserData;
|
174
|
+
};
|
175
|
+
|
176
|
+
|
177
|
+
}
|
178
|
+
|
179
|
+
#endif
|