swfmill 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|