root/OpenSceneGraph/trunk/src/osgPlugins/txp/trpage_parse.cpp @ 13041

Revision 13041, 7.6 kB (checked in by robert, 3 years ago)

Ran script to remove trailing spaces and tabs

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* ************************
2   Copyright Terrain Experts Inc.
3   Terrain Experts Inc (TERREX) reserves all rights to this source code
4   unless otherwise specified in writing by the President of TERREX.
5   This copyright may be updated in the future, in which case that version
6   supercedes this one.
7   -------------------
8   Terrex Experts Inc.
9   4400 East Broadway #314
10   Tucson, AZ  85711
11   info@terrex.com
12   Tel: (520) 323-7990
13   ************************
14   */
15
16#include <stdlib.h>
17#include <stdio.h>
18
19/* trpage_parse.cpp
20   This source file contains methods for the trpgr_Parser and trpgr_Token classes.
21   trpgr_Parser is the main class.  It parses the basic structure of paging archive
22   data out of Read Buffers.  You should not need to change this.
23   If you want to parse data out of a different structure instead, look at
24   subclassing trpgReadBuffer and replacing its virtual methods.  That's what
25   trpgMemReadBuffer is doing.
26
27   This file also contains the implementation of trpgSceneParser().
28   That class implements a set of callbacks for handling the Pushes and Pops
29   in an archive.  You fill in the Start/EndChildren callbacks and register
30   for the rest of the tokens that you want.
31*/
32
33#include <trpage_read.h>
34
35/* ***************************
36    Paging token callback structure
37   ***************************
38   */
39trpgr_Token::trpgr_Token()
40{
41    cb = NULL;
42    destroy = true;
43}
44trpgr_Token::~trpgr_Token()
45{
46}
47trpgr_Token::trpgr_Token(int in_tok,trpgr_Callback *in_cb,bool in_dest)
48{
49    init(in_tok,in_cb,in_dest);
50}
51void trpgr_Token::init(int in_tok,trpgr_Callback *in_cb,bool in_dest)
52{
53    Token = in_tok;
54    cb = in_cb;
55    destroy = in_dest;
56}
57// Destruct
58// Destroy our callback if appropriate
59void trpgr_Token::Destruct()
60{
61    if (cb && destroy)
62        delete cb;
63    cb = NULL;
64    destroy = true;
65}
66
67/* ***************************
68   Paging parser implementation.
69   ***************************
70   */
71
72// Constructor
73trpgr_Parser::trpgr_Parser()
74{
75    lastObject = NULL;
76}
77trpgr_Parser::~trpgr_Parser()
78{
79}
80
81// Validity check
82bool trpgr_Parser::isValid() const
83{
84    return true;
85}
86
87// Add Callback
88// Make the given callback object current for the given token.
89void trpgr_Parser::AddCallback(trpgToken tok,trpgr_Callback *cb,bool in_dest)
90{
91    RemoveCallback(tok);
92
93    tokenMap[tok] = trpgr_Token(tok,cb,in_dest);
94}
95
96// Callback used as writeable wrapper
97class WriteWrapper : public trpgr_Callback {
98public:
99    WriteWrapper(trpgReadWriteable *in_wr)  { wr = in_wr; };
100    void *Parse(trpgToken,trpgReadBuffer &buf) {
101        if (wr->Read(buf))
102            return wr;
103        else
104            return NULL;
105    }
106protected:
107    trpgReadWriteable *wr;
108};
109
110// Add Callback (writeable)
111// Build a wrapper around a trpgWriteable so it can read itself
112void trpgr_Parser::AddCallback(trpgToken tok,trpgReadWriteable *wr)
113{
114    AddCallback(tok,new WriteWrapper(wr),true);
115}
116
117// Get the claaback associated with a token, will return 0 if none
118const trpgr_Callback *trpgr_Parser::GetCallback(trpgToken tok) const
119{
120    tok_map::const_iterator iter = tokenMap.find(tok);
121    if(iter != tokenMap.end())
122        return iter->second.cb;
123    else
124        return 0;
125}
126trpgr_Callback *trpgr_Parser::GetCallback(trpgToken tok)
127{
128    tok_map::iterator iter = tokenMap.find(tok);
129    if(iter != tokenMap.end())
130        return iter->second.cb;
131    else
132        return 0;
133}
134
135
136// Remove Callback
137void trpgr_Parser::RemoveCallback(trpgToken tok)
138{
139    tokenMap.erase(tok);
140}
141
142// Set Default Callback
143// This gets called for all tokens we don't understand
144void trpgr_Parser::SetDefaultCallback(trpgr_Callback *cb,bool in_dest)
145{
146    defCb.Destruct();
147    defCb.init(-1,cb,in_dest);
148}
149
150/* Token Is Valid
151   Checks if something *could be* a token.
152   Doesn't necessarily mean that it is.
153*/
154bool trpgr_Parser::TokenIsValid(trpgToken tok)
155{
156    if (tok < 0)
157        return false;
158
159    return true;
160}
161
162/* Parse Buffer
163   This runs through the given buffer parsing token sets until
164   it (1) runs out of buffer or (2) fails.
165   Note: Good place to return an exception, but keep it simple for now.
166*/
167bool trpgr_Parser::Parse(trpgReadBuffer &buf)
168{
169    bool ret = true;
170
171    try
172    {
173        while (!buf.isEmpty())
174        {
175            /* We're expecting the following
176            Token    (int32)
177            Length  (int32)
178            Data    (variable)
179            */
180            trpgToken tok;
181            int32 len;
182            if (!buf.Get(tok))  throw 1;
183            // Push and Pop are special - no data
184            if (tok != TRPG_PUSH && tok != TRPG_POP)
185            {
186                if (!buf.Get(len)) throw 1;
187                if (!TokenIsValid(tok))  throw 1;
188                if (len < 0)  throw 1;
189                // Limit what we're reading to the length of this
190                buf.PushLimit(len);
191            }
192
193            // Call our token handler for this one
194            try
195            {
196                const trpgr_Token *tcb = NULL;
197                tok_map::const_iterator p = tokenMap.find(tok);
198                if (p != tokenMap.end())
199                    tcb = &(*p).second;
200                if (!tcb)
201                    // No such token, call the default
202                    tcb = &defCb;
203
204                // Run the callback
205                if (tcb->cb)
206                {
207                    void *ret = tcb->cb->Parse(tok,buf);
208                    // Note: Do something with the return value
209                    lastObject = ret;
210                }
211            }
212            catch (...)
213            {
214                // Don't want to screw up the limit stack
215            }
216            // No limit to worry about with push and pop
217            if (tok != TRPG_PUSH && tok != TRPG_POP)
218            {
219                buf.SkipToLimit();
220                buf.PopLimit();
221            }
222        }
223    }
224    catch (...)
225    {
226        // Failed to parse.
227        ret = false;
228    }
229
230    return ret;
231}
232
233/*    ****************
234  Scene Parser
235  ****************
236  */
237// Helper - callback for Push
238class trpgSceneHelperPush : public trpgr_Callback
239{
240public:
241    trpgSceneHelperPush(trpgSceneParser *in_parse)
242    { parse = in_parse; };
243
244    void *Parse(trpgToken /*tok*/,trpgReadBuffer& /*buf*/)
245    {
246        // Call the start children callback
247        parse->StartChildren(parse->lastObject);
248        parse->parents.push_back(parse->lastObject);
249        return (void *)1;
250    }
251protected:
252    trpgSceneParser *parse;
253};
254
255// Helper - callback for Pop
256class trpgSceneHelperPop : public trpgr_Callback
257{
258public:
259    trpgSceneHelperPop(trpgSceneParser *in_parse)
260    { parse = in_parse; };
261    void *Parse(trpgToken /*tok*/,trpgReadBuffer& /*buf*/)
262    {
263        // Make sure we don't have an extra pop
264        if (parse->parents.size() == 0)
265            // Note: let someone know about the extra pop
266            return NULL;
267        // Call the end children callback
268        int len = parse->parents.size();
269        parse->EndChildren(parse->parents[len-1]);
270        parse->parents.resize(len-1);
271        return (void *)1;
272    }
273protected:
274    trpgSceneParser *parse;
275};
276
277// Helper - default callback
278// Puts a 1 on the parent stack
279// Note: Need to use this fact above
280class trpgSceneHelperDefault : public trpgr_Callback
281{
282public:
283    trpgSceneHelperDefault(trpgSceneParser *in_parse) { parse = in_parse; }
284    void *Parse(trpgToken /*tok*/,trpgReadBuffer& /*buf*/)
285    {
286        // Absorb it quietly
287        return (void *)1;
288    }
289protected:
290    trpgSceneParser *parse;
291};
292
293trpgSceneParser::trpgSceneParser()
294{
295    // Register for Push and Pop
296    AddCallback(TRPG_PUSH,new trpgSceneHelperPush(this));
297    AddCallback(TRPG_POP,new trpgSceneHelperPop(this));
298
299    // Register for default
300    SetDefaultCallback(new trpgSceneHelperDefault(this));
301}
302trpgSceneParser::~trpgSceneParser()
303{
304}
Note: See TracBrowser for help on using the browser.