1 // Filename: File.cpp 2 #include "util/HashGenerator.h" 3 #include "dc/DistributedType.h" 4 #include "dc/Class.h" 5 #include "dc/Field.h" 6 7 #include "File.h" 8 namespace dclass // open namespace 9 { 10 11 12 typedef std::unordered_map<std::string, DistributedType*>::value_type TypeName; 13 14 // constructor File()15File::File() 16 { 17 } 18 19 //destructor ~File()20File::~File() 21 { 22 for(auto it = m_classes.begin(); it != m_classes.end(); ++it) { 23 delete(*it); 24 } 25 for(auto it = m_structs.begin(); it != m_structs.end(); ++it) { 26 delete(*it); 27 } 28 for(auto it = m_imports.begin(); it != m_imports.end(); ++it) { 29 delete(*it); 30 } 31 32 m_classes.clear(); 33 m_structs.clear(); 34 m_imports.clear(); 35 m_types_by_id.clear(); 36 m_types_by_name.clear(); 37 m_fields_by_id.clear(); 38 m_keywords.clear(); 39 } 40 41 // get_class_by_id returns the requested class or nullptr if there is no such class. get_class_by_id(unsigned int id)42Class* File::get_class_by_id(unsigned int id) 43 { 44 DistributedType* dt = get_type_by_id(id); 45 if(dt == nullptr) { 46 return nullptr; 47 } 48 if(dt->as_struct() == nullptr) { 49 return nullptr; 50 } 51 return dt->as_struct()->as_class(); 52 } get_class_by_id(unsigned int id) const53const Class* File::get_class_by_id(unsigned int id) const 54 { 55 const DistributedType* dt = get_type_by_id(id); 56 if(dt == nullptr) { 57 return nullptr; 58 } 59 if(dt->as_struct() == nullptr) { 60 return nullptr; 61 } 62 return dt->as_struct()->as_class(); 63 } 64 // get_class_by_name returns the requested class or nullptr if there is no such class. get_class_by_name(const std::string & name)65Class* File::get_class_by_name(const std::string &name) 66 { 67 DistributedType* dt = get_type_by_name(name); 68 if(dt == nullptr) { 69 return nullptr; 70 } 71 if(dt->as_struct() == nullptr) { 72 return nullptr; 73 } 74 return dt->as_struct()->as_class(); 75 } get_class_by_name(const std::string & name) const76const Class* File::get_class_by_name(const std::string &name) const 77 { 78 const DistributedType* dt = get_type_by_name(name); 79 if(dt == nullptr) { 80 return nullptr; 81 } 82 if(dt->as_struct() == nullptr) { 83 return nullptr; 84 } 85 return dt->as_struct()->as_class(); 86 } 87 88 // add_class adds the newly-allocated class to the file. 89 // Returns false if there is a name conflict. 90 // The File becomes the owner of the pointer and will delete it when it destructs. add_class(Class * cls)91bool File::add_class(Class *cls) 92 { 93 // Classes have to have a name 94 if(cls->get_name().empty()) { 95 return false; 96 } 97 98 // A Class can't share a name with any other type. 99 bool inserted = m_types_by_name.insert(TypeName(cls->get_name(), cls)).second; 100 if(!inserted) { 101 return false; 102 } 103 104 cls->set_id(m_types_by_id.size()); 105 m_types_by_id.push_back(cls); 106 m_classes.push_back(cls); 107 return true; 108 } 109 110 // add_struct adds the newly-allocated struct to the file. 111 // Returns false if there is a name conflict. 112 // The File becomes the owner of the pointer and will delete it when it destructs. add_struct(Struct * strct)113bool File::add_struct(Struct *strct) 114 { 115 // Structs have to have a name 116 if(strct->get_name().empty()) { 117 return false; 118 } 119 120 // A Struct can't share a name with any other type. 121 bool inserted = m_types_by_name.insert(TypeName(strct->get_name(), strct)).second; 122 if(!inserted) { 123 return false; 124 } 125 126 strct->set_id(m_types_by_id.size()); 127 m_types_by_id.push_back(strct); 128 m_structs.push_back(strct); 129 return true; 130 } 131 132 // add_typedef adds the alias <name> to the file for the type <type>. 133 // Returns false if there is a name conflict. add_typedef(const std::string & name,DistributedType * type)134bool File::add_typedef(const std::string& name, DistributedType* type) 135 { 136 // Typedefs can't use the empty string as a name 137 if(name.empty()) { 138 return false; 139 } 140 141 // A type alias can't share a name with any other type. 142 return m_types_by_name.insert(TypeName(name, type)).second; 143 } 144 145 // add_import adds a newly-allocated import to the file. 146 // Imports with duplicate modules are combined. add_import(Import * import)147void File::add_import(Import* import) 148 { 149 // TODO: Combine duplicates 150 m_imports.push_back(import); 151 } 152 153 // add_keyword adds a keyword with the name <keyword> to the list of declared keywords. add_keyword(const std::string & keyword)154void File::add_keyword(const std::string &keyword) 155 { 156 if(!has_keyword(keyword)) { 157 m_keywords.push_back(keyword); 158 } 159 } 160 161 // add_field gives the field a unique id within the file. add_field(Field * field)162void File::add_field(Field *field) 163 { 164 field->set_id((unsigned int)m_fields_by_id.size()); 165 m_fields_by_id.push_back(field); 166 } 167 get_hash() const168uint32_t File::get_hash() const 169 { 170 HashGenerator hashgen; 171 generate_hash(hashgen); 172 return hashgen.get_hash(); 173 } 174 175 // generate_hash accumulates the properties of this file into the hash. generate_hash(HashGenerator & hashgen) const176void File::generate_hash(HashGenerator& hashgen) const 177 { 178 hashgen.add_int(m_classes.size()); 179 for(auto it = m_classes.begin(); it != m_classes.end(); ++it) { 180 (*it)->generate_hash(hashgen); 181 } 182 183 hashgen.add_int(m_structs.size()); 184 for(auto it = m_structs.begin(); it != m_structs.end(); ++it) { 185 (*it)->generate_hash(hashgen); 186 } 187 188 hashgen.add_int(m_keywords.size()); 189 for(auto it = m_keywords.begin(); it != m_keywords.end(); ++it) { 190 hashgen.add_string(*it); 191 } 192 } 193 194 195 } // close namespace dclass 196