Panda3D

dcSwitch.h

00001 // Filename: dcSwitch.h
00002 // Created by:  drose (23Jun04)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #ifndef DCSWITCH_H
00016 #define DCSWITCH_H
00017 
00018 #include "dcbase.h"
00019 #include "dcDeclaration.h"
00020 #include "dcPackerInterface.h"
00021 
00022 class DCParameter;
00023 class HashGenerator;
00024 class DCField;
00025 
00026 ////////////////////////////////////////////////////////////////////
00027 //       Class : DCSwitch
00028 // Description : This represents a switch statement, which can appear
00029 //               inside a class body and represents two or more
00030 //               alternative unpacking schemes based on the first
00031 //               field read.
00032 ////////////////////////////////////////////////////////////////////
00033 class EXPCL_DIRECT DCSwitch : public DCDeclaration {
00034 public:
00035   DCSwitch(const string &name, DCField *key_parameter);
00036   virtual ~DCSwitch();
00037 
00038 PUBLISHED:
00039   virtual DCSwitch *as_switch();
00040   virtual const DCSwitch *as_switch() const;
00041 
00042   const string &get_name() const;
00043   DCField *get_key_parameter() const;
00044 
00045   int get_num_cases() const;
00046   int get_case_by_value(const string &case_value) const;
00047   DCPackerInterface *get_case(int n) const;
00048   DCPackerInterface *get_default_case() const;
00049 
00050   string get_value(int case_index) const;
00051   int get_num_fields(int case_index) const;
00052   DCField *get_field(int case_index, int n) const;
00053   DCField *get_field_by_name(int case_index, const string &name) const;
00054 
00055 public:
00056   bool is_field_valid() const;
00057   int add_case(const string &value);
00058   void add_invalid_case();
00059   bool add_default();
00060   bool add_field(DCField *field);
00061   void add_break();
00062 
00063   const DCPackerInterface *apply_switch(const char *value_data, size_t length) const;
00064 
00065   virtual void output(ostream &out, bool brief) const;
00066   virtual void write(ostream &out, bool brief, int indent_level) const;
00067   void output_instance(ostream &out, bool brief, const string &prename, 
00068                        const string &name, const string &postname) const;
00069   void write_instance(ostream &out, bool brief, int indent_level,
00070                       const string &prename, const string &name,
00071                       const string &postname) const;
00072   virtual void generate_hash(HashGenerator &hashgen) const;
00073   virtual bool pack_default_value(DCPackData &pack_data, bool &pack_error) const;
00074 
00075   bool do_check_match_switch(const DCSwitch *other) const;
00076 
00077 public:
00078   typedef pvector<DCField *> Fields;
00079   typedef pmap<string, DCField *> FieldsByName;
00080 
00081   class SwitchFields : public DCPackerInterface {
00082   public:
00083     SwitchFields(const string &name);
00084     ~SwitchFields();
00085     virtual DCPackerInterface *get_nested_field(int n) const;
00086 
00087     bool add_field(DCField *field);
00088     bool do_check_match_switch_case(const SwitchFields *other) const;
00089 
00090     void output(ostream &out, bool brief) const;
00091     void write(ostream &out, bool brief, int indent_level) const;
00092 
00093   protected:
00094     virtual bool do_check_match(const DCPackerInterface *other) const;
00095 
00096   public:
00097     Fields _fields;
00098     FieldsByName _fields_by_name;
00099     bool _has_default_value;
00100   };
00101 
00102   class SwitchCase {
00103   public:
00104     SwitchCase(const string &value, SwitchFields *fields);
00105     ~SwitchCase();
00106 
00107     bool do_check_match_switch_case(const SwitchCase *other) const;
00108 
00109   public:
00110     string _value;
00111     SwitchFields *_fields;
00112   };
00113 
00114 private:
00115   SwitchFields *start_new_case();
00116 
00117 private:
00118   string _name;
00119   DCField *_key_parameter;
00120 
00121   typedef pvector<SwitchCase *> Cases;
00122   Cases _cases;
00123   SwitchFields *_default_case;
00124 
00125   // All SwitchFields created and used by the DCSwitch object are also
00126   // stored here; this is the vector that "owns" the pointers.
00127   typedef pvector<SwitchFields *> CaseFields;
00128   CaseFields _case_fields;
00129 
00130   // All nested DCField objects that have been added to one or more of
00131   // the above SwitchFields are also recorded here; this is the vector
00132   // that "owns" these pointers.
00133   Fields _nested_fields;
00134 
00135   // These are the SwitchFields that are currently being filled up
00136   // during this stage of the parser.  There might be more than one at
00137   // a time, if we have multiple cases being introduced in the middle
00138   // of a series of fields (without a break statement intervening).
00139   CaseFields _current_fields;
00140   bool _fields_added;
00141 
00142   // This map indexes into the _cases vector, above.
00143   typedef pmap<string, int> CasesByValue;
00144   CasesByValue _cases_by_value;
00145 };
00146 
00147 #endif
 All Classes Functions Variables Enumerations