$search
00001 #include "exporter.hh" 00002 #include "registry.hh" 00003 #include "registryiterator.hh" 00004 #include <utilmm/configfile/configset.hh> 00005 #include <utilmm/stringtools.hh> 00006 #include <typelib/typevisitor.hh> 00007 #include <set> 00008 #include <fstream> 00009 00010 using namespace Typelib; 00011 using namespace std; 00012 using utilmm::join; 00013 00014 void Exporter::save(std::string const& file_name, utilmm::config_set const& config, Registry const& registry) 00015 { 00016 std::ofstream file(file_name.c_str(), std::ofstream::trunc); 00017 save(file, config, registry); 00018 } 00019 00020 void Exporter::save(std::ostream& stream, utilmm::config_set const& config, Registry const& registry) 00021 { 00022 begin(stream, registry); 00023 00024 std::set<Type const*> saved_types; 00025 00026 typedef std::map 00027 < const std::string 00028 , RegistryIterator 00029 , bool (*) (const std::string&, const std::string&) 00030 > TypeMap; 00031 TypeMap types(nameSort); 00032 00033 RegistryIterator const it_end(registry.end()); 00034 for (RegistryIterator it = registry.begin(); it != it_end; ++it) 00035 types.insert(make_pair(it.getName(), it)); 00036 00037 // Some exporters need to limit how many times a namespace appears. So, the 00038 // main algorithm (here) is meant to limit switching between namespaces. 00039 TypeMap free_types(nameSort); 00040 std::string last_namespace; 00041 while (!types.empty()) 00042 { 00043 TypeMap::iterator it = types.begin(); 00044 TypeMap::iterator const end = types.end(); 00045 00046 while (it != end) 00047 { 00048 bool done_dependencies = false; 00049 if (it->second.isAlias()) 00050 done_dependencies = (saved_types.find(&(*it->second)) != saved_types.end()); 00051 else 00052 { 00053 std::set<Type const*> dependencies = it->second->dependsOn(); 00054 done_dependencies = includes(saved_types.begin(), saved_types.end(), 00055 dependencies.begin(), dependencies.end()); 00056 } 00057 00058 if (done_dependencies) 00059 { 00060 free_types.insert(*it); 00061 types.erase(it++); 00062 } 00063 else ++it; 00064 } 00065 00066 if (free_types.empty()) 00067 { 00068 list<string> remaining; 00069 for (TypeMap::iterator it = types.begin(); it != types.end(); ++it) 00070 remaining.push_back(it->first); 00071 throw ExportError(join(remaining) + " seem to be recursive type(s). Exporting them is not supported yet"); 00072 } 00073 00074 // Remove all non-persistent types from the free_type set. If we found 00075 // any, just go loop. Otherwise, do dump some other types. 00076 bool got_some = false; 00077 TypeMap::iterator free_it = free_types.begin(); 00078 TypeMap::iterator save_it = free_types.end(); 00079 while (free_it != free_types.end()) 00080 { 00081 if (!free_it->second.isPersistent()) 00082 { 00083 got_some = true; 00084 saved_types.insert(&(*free_it->second)); 00085 free_types.erase(free_it++); 00086 } 00087 else 00088 { 00089 if (save_it == free_types.end() && free_it->second.getNamespace() == last_namespace) 00090 save_it = free_it; 00091 ++free_it; 00092 } 00093 } 00094 if (got_some) 00095 continue; 00096 00097 if (save_it == free_types.end()) 00098 save_it = free_types.begin(); 00099 00100 std::string ns = save_it->second.getNamespace(); 00101 while (save_it != free_types.end() && save_it->second.getNamespace() == ns) 00102 { 00103 saved_types.insert(&(*save_it->second)); 00104 if (save(stream, save_it->second)) 00105 last_namespace = ns; 00106 00107 free_types.erase(save_it++); 00108 } 00109 } 00110 00111 // Now save the remaining types in free_types 00112 for (TypeMap::iterator it = free_types.begin(); it != free_types.end(); ++it) 00113 { 00114 if (it->second.isPersistent()) 00115 save(stream, it->second); 00116 } 00117 00118 end(stream, registry); 00119 } 00120 00121 bool Exporter::save( std::ostream& stream, Registry const& registry ) 00122 { 00123 utilmm::config_set config; 00124 try { save(stream, config, registry); } 00125 catch(UnsupportedType) { return false; } 00126 catch(ExportError) { return false; } 00127 return true; 00128 } 00129 00130 void Exporter::begin(std::ostream& stream, Registry const& registry) {} 00131 void Exporter::end (std::ostream& stream, Registry const& registry) {} 00132