HAL
project_manager.cpp
Go to the documentation of this file.
2 
10 
11 #include <filesystem>
12 #include <fstream>
13 #include <iostream>
14 #include <rapidjson/filereadstream.h>
15 #include <rapidjson/stringbuffer.h>
16 
17 #define PRETTY_JSON_OUTPUT 0
18 #if PRETTY_JSON_OUTPUT == 1
19 #include "rapidjson/prettywriter.h"
20 #else
21 #include "rapidjson/writer.h"
22 #endif
23 
25 
26 namespace hal
27 {
28  ProjectManager* ProjectManager::inst = nullptr;
29 
30  const std::string ProjectManager::s_project_file = ".project.json";
31 
32  ProjectManager::ProjectManager() : m_project_status(ProjectStatus::NONE)
33  {
34  ;
35  }
36 
38  {
39  if (!inst)
40  inst = new ProjectManager;
41  return inst;
42  }
43 
44  void ProjectManager::register_serializer(const std::string& tagname, ProjectSerializer* serializer)
45  {
46  if (m_serializer.find(tagname) == m_serializer.end())
47  m_serializer[tagname] = serializer;
48  else
49  {
50  log_warning("project_manager", "serializer '{}' already registered.", tagname);
51  }
52  }
53 
54  void ProjectManager::unregister_serializer(const std::string& tagname)
55  {
56  auto it = m_serializer.find(tagname);
57  if (it != m_serializer.end())
58  m_serializer.erase(it);
59  }
60 
61  std::string ProjectManager::get_filename(const std::string& tagname)
62  {
63  auto it = m_filename.find(tagname);
64  if (it == m_filename.end())
65  return std::string();
66  return it->second;
67  }
68 
69  bool ProjectManager::open_project(const std::string& path)
70  {
71  if (!path.empty())
72  m_proj_dir = ProjectDirectory(path);
73  if (!std::filesystem::exists(m_proj_dir))
74  {
75  log_warning("project_manager", "cannot open project '{}', path doesn't exist.", path);
76  return false;
77  }
78  if (deserialize())
79  {
80  m_project_status = ProjectStatus::OPENED;
81  return true;
82  }
83  return false;
84  }
85 
86  void ProjectManager::set_project_directory(const std::string& path)
87  {
88  m_proj_dir = ProjectDirectory(path);
89  }
90 
92  {
93  return m_proj_dir;
94  }
95 
96  bool ProjectManager::create_project_directory(const std::string& path)
97  {
98  std::error_code errCode;
99  m_proj_dir = ProjectDirectory(path);
100  if (std::filesystem::exists(m_proj_dir))
101  return false;
102  bool success = std::filesystem::create_directory(m_proj_dir, errCode);
103  if (errCode)
104  {
105  log_warning("project_manager", "cannot create directory '{}': '{}'", m_proj_dir.string(), errCode.message());
106  return false;
107  }
108  if (!success)
109  return false;
110  m_netlist_file = m_proj_dir.get_default_filename(".hal");
111 
112  std::filesystem::create_directory(m_proj_dir.get_filename("py"));
113  std::filesystem::create_directory(m_proj_dir.get_filename(ProjectDirectory::s_shadow_dir));
114  return serialize_to_projectfile(false);
115  }
116 
118  {
119  if (m_proj_dir.empty())
120  return false;
121  return std::filesystem::remove_all(m_proj_dir);
122  }
123 
125  {
126  m_project_status = stat;
127  }
128 
130  {
131  return m_project_status;
132  }
133 
134  void ProjectManager::set_gate_library_path(const std::string& glpath)
135  {
136  m_gatelib_path = glpath;
137  }
138 
140  {
141  if (!netlist)
142  return false;
143 
144  m_netlist_save = netlist;
145  const GateLibrary* gl = m_netlist_save->get_gate_library();
146  if (gl)
147  m_gatelib_path = gl->get_path().string();
148  if (shadow)
149  m_netlist_file = m_proj_dir.get_shadow_filename(".hal");
150  else
151  m_netlist_file = m_proj_dir.get_default_filename(".hal");
152 
153  if (!netlist_serializer::serialize_to_file(m_netlist_save, m_netlist_file))
154  return false;
155 
156  if (!serialize_external(shadow))
157  return false;
158 
159  return serialize_to_projectfile(shadow);
160  }
161 
163  {
164  std::filesystem::path filename(m_proj_dir);
165  filename.append(m_netlist_file);
166  return filename.string();
167  }
168 
169  std::unique_ptr<Netlist>& ProjectManager::get_netlist()
170  {
171  return m_netlist_load;
172  }
173 
175  {
176  std::filesystem::path projFilePath(m_proj_dir);
177  projFilePath.append(s_project_file);
178 
179  FILE* fp = fopen(projFilePath.string().c_str(), "r");
180  if (fp == NULL)
181  return;
182 
183  char buffer[65536];
184  rapidjson::FileReadStream frs(fp, buffer, sizeof(buffer));
185  rapidjson::Document doc;
186  doc.ParseStream<0, rapidjson::UTF8<>, rapidjson::FileReadStream>(frs);
187  fclose(fp);
188 
189  if (doc.HasMember("netlist"))
190  {
191  rapidjson::Value::MemberIterator netlistMember = doc.FindMember("netlist");
192  std::string netlistFilename = netlistMember->value.GetString();
193  int n = ProjectDirectory::s_shadow_dir.size() + 1;
194  if (netlistFilename.substr(0, n) == ProjectDirectory::s_shadow_dir + '/')
195  {
196  netlistFilename.erase(0, n);
197  netlistMember->value.SetString(netlistFilename.c_str(), doc.GetAllocator());
198 
199  std::ofstream of(projFilePath);
200  if (!of.good())
201  return;
202 
203  rapidjson::StringBuffer strbuf;
204 #if PRETTY_JSON_OUTPUT == 1
205  rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(strbuf);
206 #else
207  rapidjson::Writer<rapidjson::StringBuffer> writer(strbuf);
208 #endif
209  doc.Accept(writer);
210  of << strbuf.GetString();
211  of.close();
212  }
213  }
214  }
215 
216  bool ProjectManager::deserialize()
217  {
218  std::filesystem::path projFilePath(m_proj_dir);
219  projFilePath.append(s_project_file);
220 
221  FILE* fp = fopen(projFilePath.string().c_str(), "r");
222  if (fp == NULL)
223  {
224  log_error("project_manager", "cannot open project file '{}'.", projFilePath.string());
225  return false;
226  }
227 
228  char buffer[65536];
229  rapidjson::FileReadStream frs(fp, buffer, sizeof(buffer));
230  rapidjson::Document doc;
231  doc.ParseStream<0, rapidjson::UTF8<>, rapidjson::FileReadStream>(frs);
232  fclose(fp);
233 
234  if (doc.HasMember("gate_library"))
235  {
236  m_gatelib_path = doc["gate_library"].GetString();
237  std::filesystem::path gatelibPath(m_gatelib_path);
238  if (gatelibPath.is_relative())
239  gatelibPath = m_proj_dir / gatelibPath;
240 
241  if (doc.HasMember("netlist"))
242  {
243  m_netlist_file = doc["netlist"].GetString();
244  std::filesystem::path netlistPath(m_proj_dir);
245  netlistPath.append(m_netlist_file);
246  m_netlist_load = netlist_factory::load_netlist(netlistPath,gatelibPath);
247  if (!m_netlist_load)
248  {
249  log_error("project_manager", "cannot load netlist {}.", netlistPath.string());
250  return false;
251  }
252  }
253  else
254  {
255  log_error("project_manager", "no 'netlist' token found in project file {}.", projFilePath.string());
256  return false;
257  }
258  }
259  else
260  {
261  log_error("netlist", "'gate_library' token not found in project file '{}'.", projFilePath.string());
262  return false;
263  }
264 
265 
266  if (doc.HasMember("serializer"))
267  {
268  for (auto it = doc["serializer"].MemberBegin(); it != doc["serializer"].MemberEnd(); ++it)
269  {
270  m_filename[it->name.GetString()] = it->value.GetString();
271  }
272  }
273 
274  for (auto it = m_serializer.begin(); it != m_serializer.end(); ++it)
275  {
276  it->second->deserialize(m_netlist_load.get(), m_proj_dir);
277  }
278  return true;
279  }
280 
281  bool ProjectManager::serialize_external(bool shadow)
282  {
283  if (!m_netlist_save)
284  return false;
285 
286  m_filename.clear();
287 
288  for (auto it = m_serializer.begin(); it != m_serializer.end(); ++it)
289  {
290  std::string relfile = it->second->serialize(m_netlist_save, shadow ? m_proj_dir.get_filename(ProjectDirectory::s_shadow_dir) : m_proj_dir, shadow);
291  if (relfile.empty())
292  continue;
293  m_filename[it->first] = relfile;
294  }
295  return true;
296  }
297 
298  bool ProjectManager::serialize_to_projectfile(bool shadow) const
299  {
300  std::filesystem::path projFilePath = m_proj_dir.get_filename(s_project_file);
301  if (shadow)
302  {
303  std::filesystem::path shadowPath = m_proj_dir.get_filename(ProjectDirectory::s_shadow_dir);
304  std::filesystem::create_directory(shadowPath);
305  projFilePath = shadowPath;
306  projFilePath.append(s_project_file);
307  }
308 
309  JsonWriteDocument doc;
310  doc["serialization_format_version"] = SERIALIZATION_FORMAT_VERSION;
311  doc["netlist"] = m_proj_dir.get_relative_file_path(m_netlist_file).string();
312  doc["gate_library"] = m_proj_dir.get_relative_file_path(m_gatelib_path).string();
313 
314  if (!m_filename.empty())
315  {
316  JsonWriteObject& serial = doc.add_object("serializer");
317  for (auto it = m_filename.begin(); it != m_filename.end(); ++it)
318  {
319  if (it->second.empty())
320  continue;
321  serial[it->first] = it->second;
322  }
323  serial.close();
324  }
325  return doc.serialize(projFilePath.string());
326  }
327 
328  void ProjectManager::dump() const
329  {
330  for (auto it = m_filename.begin(); it != m_filename.end(); ++it)
331  {
332  std::cout << "serializer: <" << it->first << "> <" << it->second << ">" << std::endl;
333  }
334  }
335 } // namespace hal
Apache License January AND DISTRIBUTION Definitions License shall mean the terms and conditions for and distribution as defined by Sections through of this document Licensor shall mean the copyright owner or entity authorized by the copyright owner that is granting the License Legal Entity shall mean the union of the acting entity and all other entities that control are controlled by or are under common control with that entity For the purposes of this definition control direct or to cause the direction or management of such whether by contract or including but not limited to software source documentation and configuration files Object form shall mean any form resulting from mechanical transformation or translation of a Source including but not limited to compiled object generated and conversions to other media types Work shall mean the work of whether in Source or Object made available under the as indicated by a copyright notice that is included in or attached to the whether in Source or Object that is based or other modifications as a an original work of authorship For the purposes of this Derivative Works shall not include works that remain separable or merely the Work and Derivative Works thereof Contribution shall mean any work of including the original version of the Work and any modifications or additions to that Work or Derivative Works that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner For the purposes of this submitted means any form of or written communication sent to the Licensor or its including but not limited to communication on electronic mailing source code control and issue tracking systems that are managed or on behalf of
std::filesystem::path get_path() const
const GateLibrary * get_gate_library() const
Definition: netlist.cpp:132
std::filesystem::path get_filename(const std::string &relative_filename) const
std::filesystem::path get_relative_file_path(const std::string &filename) const
static const std::string s_shadow_dir
std::filesystem::path get_shadow_filename(const std::string &extension=std::string()) const
std::filesystem::path get_default_filename(const std::string &extension=std::string()) const
static ProjectManager * instance()
void set_project_status(ProjectStatus status)
bool create_project_directory(const std::string &path)
void unregister_serializer(const std::string &tagname)
bool serialize_project(Netlist *netlist, bool shadow=false)
std::unique_ptr< Netlist > & get_netlist()
void register_serializer(const std::string &tagname, ProjectSerializer *serializer)
void set_gate_library_path(const std::string &gl_path)
std::string get_filename(const std::string &serializer_name)
ProjectStatus get_project_status() const
void restore_project_file_from_autosave()
static const std::string s_project_file
std::string get_netlist_filename() const
bool open_project(const std::string &path="")
const ProjectDirectory & get_project_directory() const
void set_project_directory(const std::string &path)
#define log_error(channel,...)
Definition: log.h:78
#define log_warning(channel,...)
Definition: log.h:76
std::unique_ptr< Netlist > load_netlist(const std::filesystem::path &netlist_file, const std::filesystem::path &gate_library_file)
Create a netlist from the given file.
bool serialize_to_file(const Netlist *nl, const std::filesystem::path &hal_file)
std::error_code error_code
Definition: defines.h:46
n
Definition: test.py:6
const int SERIALIZATION_FORMAT_VERSION
This file contains various functions to create and load netlists.