Xmipp  v3.23.11-Nereus
utilities.cpp
Go to the documentation of this file.
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2020 NKI/AVL, Netherlands Cancer Institute
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright notice, this
10  * list of conditions and the following disclaimer
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation
13  * and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
19  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26 
27 #include "cif++/utilities.hpp"
28 
29 #include "revision.hpp"
30 
31 #include <atomic>
32 #include <cassert>
33 #include <cmath>
34 #include <cstring>
35 #include <deque>
36 #include <fstream>
37 #include <functional>
38 #include <iomanip>
39 #include <iostream>
40 #include <map>
41 #include <mutex>
42 #include <regex>
43 #include <sstream>
44 #include <thread>
45 
46 #if not defined(_MSC_VER)
47 #include <sys/ioctl.h>
48 #include <termios.h>
49 #endif
50 
51 namespace fs = std::filesystem;
52 
53 // --------------------------------------------------------------------
54 
55 namespace cif
56 {
57 
58 int VERBOSE = 0;
59 
60 // --------------------------------------------------------------------
61 
62 std::string get_version_nr()
63 {
64  std::ostringstream s;
65  write_version_string(s, false);
66  return s.str();
67 }
68 
69 // --------------------------------------------------------------------
70 
71 #ifdef _MSC_VER
72 }
73 #include <Windows.h>
74 #include <libloaderapi.h>
75 #include <wincon.h>
76 
77 #include <codecvt>
78 
79 namespace cif
80 {
81 
82 uint32_t get_terminal_width()
83 {
84  CONSOLE_SCREEN_BUFFER_INFO csbi;
85  ::GetConsoleScreenBufferInfo(::GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
86  return csbi.srWindow.Right - csbi.srWindow.Left + 1;
87 }
88 
89 std::string GetExecutablePath()
90 {
91  WCHAR buffer[4096];
92 
93  DWORD n = ::GetModuleFileNameW(nullptr, buffer, sizeof(buffer) / sizeof(WCHAR));
94  if (n == 0)
95  throw std::runtime_error("could not get exe path");
96 
97  std::wstring ws(buffer);
98 
99  // convert from utf16 to utf8
100  std::wstring_convert<std::codecvt_utf8<wchar_t>> conv1;
101  std::string u8str = conv1.to_bytes(ws);
102 
103  return u8str;
104 }
105 
106 #else
107 
108 #include <limits.h>
109 
111 {
112  uint32_t result = 80;
113 
114  if (isatty(STDOUT_FILENO))
115  {
116  struct winsize w;
117  ioctl(0, TIOCGWINSZ, &w);
118  result = w.ws_col;
119  }
120  return result;
121 }
122 
123 std::string get_executable_path()
124 {
125  using namespace std::literals;
126 
127  // This used to be PATH_MAX, but lets simply assume 1024 is enough...
128  char path[1024] = "";
129  if (readlink("/proc/self/exe", path, sizeof(path)) == -1)
130  throw std::runtime_error("could not get exe path "s + strerror(errno));
131  return {path};
132 }
133 
134 #endif
135 
136 // --------------------------------------------------------------------
137 
139 {
140  ProgressImpl(int64_t inMax, const std::string &inAction)
141  : mMax(inMax)
142  , mConsumed(0)
143  , mAction(inAction)
144  , mMessage(inAction)
145  , mThread(std::bind(&ProgressImpl::Run, this))
146  {
147  }
148 
149  void Run();
150  void Stop()
151  {
152  mStop = true;
153  if (mThread.joinable())
154  mThread.join();
155  }
156 
157  void PrintProgress();
158  void PrintDone();
159 
160  int64_t mMax;
161  std::atomic<int64_t> mConsumed;
162  int64_t mLastConsumed = 0;
163  int mSpinnerIndex = 0;
164  std::string mAction, mMessage;
166  std::thread mThread;
167  std::chrono::time_point<std::chrono::system_clock>
168  mStart = std::chrono::system_clock::now();
169  bool mStop = false;
170 };
171 
173 {
174  using namespace std::literals;
175 
176  bool printedAny = false;
177 
178  try
179  {
180  for (;;)
181  {
182  std::this_thread::sleep_for(2s);
183 
184  std::unique_lock lock(mMutex);
185 
186  if (mStop or mConsumed == mMax)
187  break;
188 
189  auto elapsed = std::chrono::system_clock::now() - mStart;
190 
191  if (elapsed < std::chrono::seconds(5))
192  continue;
193 
194  PrintProgress();
195  printedAny = true;
196  }
197  }
198  catch (...)
199  {
200  }
201 
202  if (printedAny)
203  PrintDone();
204 }
205 
207 {
208  // const char* kBlocks[] = {
209  // " ", // 0
210  // u8"\u258F", // 1
211  // u8"\u258E", // 2
212  // u8"\u258D", // 3
213  // u8"\u258C", // 4
214  // u8"\u258B", // 5
215  // u8"\u258A", // 6
216  // u8"\u2589", // 7
217  // u8"\u2588", // 8
218  // };
219 
220  const char *kBlocks[] = {
221  " ", // 0
222  " ", // 1
223  " ", // 2
224  "-", // 3
225  "-", // 4
226  "-", // 5
227  "=", // 6
228  "=", // 7
229  "=", // 8
230  };
231 
232  uint32_t width = get_terminal_width();
233 
234  std::string msg;
235  msg.reserve(width + 1);
236  if (mMessage.length() <= 20)
237  {
238  msg = mMessage;
239  if (msg.length() < 20)
240  msg.append(20 - msg.length(), ' ');
241  }
242  else
243  msg = mMessage.substr(0, 17) + "...";
244 
245  msg += " |";
246 
247  int64_t consumed = mConsumed;
248  float progress = static_cast<float>(consumed) / mMax;
249  int pi = static_cast<int>(std::ceil(progress * 33 * 8));
250  // int tw = width - 28;
251  // int twd = static_cast<int>(tw * progress + 0.5f);
252  // msg.append(twd, '=');
253  // msg.append(tw - twd, ' ');
254 
255  for (int i = 0; i < 33; ++i)
256  {
257  if (pi <= 0)
258  msg += kBlocks[0];
259  else if (pi >= 8)
260  msg += kBlocks[8];
261  else
262  msg += kBlocks[pi];
263  pi -= 8;
264  }
265 
266  msg.append("| ");
267 
268  const char kSpinner[] = {' ', '.', 'o', 'O', '0', 'O', 'o', '.'};
269  const size_t kSpinnerCount = sizeof(kSpinner);
270 
271  if (mLastConsumed < consumed)
272  {
273  mLastConsumed = consumed;
274  mSpinnerIndex = (mSpinnerIndex + 1) % kSpinnerCount;
275  }
276 
277  const char spinner[2] = {kSpinner[mSpinnerIndex], 0};
278  msg.append(spinner);
279 
280  // int perc = static_cast<int>(100 * progress);
281  // if (perc < 100)
282  // msg += ' ';
283  // if (perc < 10)
284  // msg += ' ';
285  // msg += to_string(perc);
286  // msg += '%';
287 
288  std::cout << '\r' << msg;
289  std::cout.flush();
290 }
291 
292 namespace
293 {
294 
295  std::ostream &operator<<(std::ostream &os, const std::chrono::duration<double> &t)
296  {
297  uint64_t s = static_cast<uint64_t>(std::trunc(t.count()));
298  if (s > 24 * 60 * 60)
299  {
300  auto days = s / (24 * 60 * 60);
301  os << days << "d ";
302  s %= 24 * 60 * 60;
303  }
304 
305  if (s > 60 * 60)
306  {
307  auto hours = s / (60 * 60);
308  os << hours << "h ";
309  s %= 60 * 60;
310  }
311 
312  if (s > 60)
313  {
314  auto minutes = s / 60;
315  os << minutes << "m ";
316  s %= 60;
317  }
318 
319  double ss = s + 1e-6 * (t.count() - s);
320 
321  os << std::fixed << std::setprecision(1) << ss << 's';
322 
323  return os;
324  }
325 
326 } // namespace
327 
329 {
330  std::chrono::duration<double> elapsed = std::chrono::system_clock::now() - mStart;
331 
332  std::ostringstream msgstr;
333  msgstr << mAction << " done in " << elapsed << " seconds";
334  auto msg = msgstr.str();
335 
336  uint32_t width = get_terminal_width();
337 
338  if (msg.length() < width)
339  msg += std::string(width - msg.length(), ' ');
340 
341  std::cout << '\r' << msg << std::endl;
342 }
343 
344 Progress::Progress(int64_t inMax, const std::string &inAction)
345  : m_impl(nullptr)
346 {
347  if (isatty(STDOUT_FILENO) and VERBOSE >= 0)
348  m_impl = new ProgressImpl(inMax, inAction);
349 }
350 
351 Progress::~Progress()
352 {
353  if (m_impl != nullptr)
354  m_impl->Stop();
355 
356  delete m_impl;
357 }
358 
359 void Progress::consumed(int64_t inConsumed)
360 {
361  if (m_impl != nullptr and
362  (m_impl->mConsumed += inConsumed) >= m_impl->mMax)
363  {
364  m_impl->Stop();
365  }
366 }
367 
368 void Progress::progress(int64_t inProgress)
369 {
370  if (m_impl != nullptr and
371  (m_impl->mConsumed = inProgress) >= m_impl->mMax)
372  {
373  m_impl->Stop();
374  }
375 }
376 
377 void Progress::message(const std::string &inMessage)
378 {
379  if (m_impl != nullptr)
380  {
381  std::unique_lock lock(m_impl->mMutex);
382  m_impl->mMessage = inMessage;
383  }
384 }
385 
386 } // namespace cif
387 
388 // --------------------------------------------------------------------
389 //
390 // Try to find a named resource. Can be either a local file with this name,
391 // a file located in our cache directory or a resource linked in with mrc.
392 //
393 // We have a special, private version of mrsrc here. To be able to create
394 // shared libraries and still be able to link when there's no mrc used.
395 
396 namespace mrsrc
397 {
399 struct rsrc_imp
400 {
401  unsigned int m_next;
402  unsigned int m_child;
403  unsigned int m_name;
404  unsigned int m_size;
405  unsigned int m_data;
406 };
407 } // namespace mrsrc
408 
409 #if _MSC_VER
410 
411 extern "C" CIFPP_EXPORT const mrsrc::rsrc_imp *gResourceIndexDefault[1] = {};
412 extern "C" CIFPP_EXPORT const char *gResourceDataDefault[1] = {};
413 extern "C" CIFPP_EXPORT const char *gResourceNameDefault[1] = {};
414 
415 extern "C" const mrsrc::rsrc_imp gResourceIndex[];
416 extern "C" const char gResourceData[];
417 extern "C" const char gResourceName[];
418 
419 #pragma comment(linker, "/alternatename:gResourceIndex=gResourceIndexDefault")
420 #pragma comment(linker, "/alternatename:gResourceData=gResourceDataDefault")
421 #pragma comment(linker, "/alternatename:gResourceName=gResourceNameDefault")
422 
423 #else
424 extern const __attribute__((weak)) mrsrc::rsrc_imp gResourceIndex[];
425 extern const __attribute__((weak)) char gResourceData[];
426 extern const __attribute__((weak)) char gResourceName[];
427 
428 const mrsrc::rsrc_imp gResourceIndex[1] = {};
429 const char gResourceData[1] = {};
430 const char gResourceName[1] = {};
431 
432 #endif
433 
434 namespace mrsrc
435 {
437 {
438  public:
439  static rsrc_data &instance()
440  {
441  static rsrc_data s_instance;
442  return s_instance;
443  }
444 
445  const rsrc_imp *index() const { return m_index; }
446 
447  const char *data(unsigned int offset) const
448  {
449  return m_data + offset;
450  }
451 
452  const char *name(unsigned int offset) const
453  {
454  return m_name + offset;
455  }
456 
457  private:
458  rsrc_data()
459  {
460  // if (gResourceIndex and (gResourceIndex[0].m_child > 0 or gResourceIndex[0].m_size > 0) and gResourceIndex and gResourceName)
461  if (gResourceIndex[0].m_child > 0 or gResourceIndex[0].m_size > 0)
462  {
463  m_index = gResourceIndex;
464  m_data = gResourceData;
465  m_name = gResourceName;
466  }
467  }
468 
469  rsrc_imp m_dummy = {};
470  const rsrc_imp *m_index = &m_dummy;
471  const char *m_data = "";
472  const char *m_name = "";
473 };
474 
478 
479 class rsrc
480 {
481  public:
483  : m_impl(rsrc_data::instance().index())
484  {
485  }
486 
487  rsrc(const rsrc &other)
488  : m_impl(other.m_impl)
489  {
490  }
491 
492  rsrc &operator=(const rsrc &other)
493  {
494  m_impl = other.m_impl;
495  return *this;
496  }
497 
498  rsrc(std::filesystem::path path);
499 
500  std::string name() const { return rsrc_data::instance().name(m_impl->m_name); }
501 
502  const char *data() const { return rsrc_data::instance().data(m_impl->m_data); }
503 
504  unsigned long size() const { return m_impl->m_size; }
505 
506  explicit operator bool() const { return m_impl != NULL and m_impl->m_size > 0; }
507 
508  template <typename RSRC>
510  {
511  public:
512  using iterator_category = std::input_iterator_tag;
513  using value_type = RSRC;
514  using difference_type = std::ptrdiff_t;
515  using pointer = value_type *;
517 
518  iterator_t(const rsrc_imp *cur)
519  : m_cur(cur)
520  {
521  }
522 
524  : m_cur(i.m_cur)
525  {
526  }
527 
529  {
530  m_cur = i.m_cur;
531  return *this;
532  }
533 
534  reference operator*() { return m_cur; }
535  pointer operator->() { return &m_cur; }
536 
538  {
539  if (m_cur.m_impl->m_next)
540  m_cur.m_impl = rsrc_data::instance().index() + m_cur.m_impl->m_next;
541  else
542  m_cur.m_impl = nullptr;
543  return *this;
544  }
545 
547  {
548  auto tmp(*this);
549  this->operator++();
550  return tmp;
551  }
552 
553  bool operator==(const iterator_t &rhs) const { return m_cur.m_impl == rhs.m_cur.m_impl; }
554  bool operator!=(const iterator_t &rhs) const { return m_cur.m_impl != rhs.m_cur.m_impl; }
555 
556  private:
557  value_type m_cur;
558  };
559 
561 
562  iterator begin() const
563  {
564  const rsrc_imp *impl = nullptr;
565  if (m_impl and m_impl->m_child)
566  impl = rsrc_data::instance().index() + m_impl->m_child;
567  return iterator(impl);
568  }
569 
570  iterator end() const
571  {
572  return iterator(nullptr);
573  }
574 
575  private:
576  rsrc(const rsrc_imp *imp)
577  : m_impl(imp)
578  {
579  }
580 
581  const rsrc_imp *m_impl;
582 };
583 
584 inline rsrc::rsrc(std::filesystem::path p)
585 {
586  m_impl = rsrc_data::instance().index();
587 
588  // using std::filesytem::path would have been natural here of course...
589 
590  auto pb = p.begin();
591  auto pe = p.end();
592 
593  while (m_impl != nullptr and pb != pe)
594  {
595  auto name = *pb++;
596 
597  const rsrc_imp *impl = nullptr;
598  for (rsrc child : *this)
599  {
600  if (child.name() == name)
601  {
602  impl = child.m_impl;
603  break;
604  }
605  }
606 
607  m_impl = impl;
608  }
609 
610  if (pb != pe) // not found
611  m_impl = nullptr;
612 }
613 
614 // --------------------------------------------------------------------
615 
616 template <typename CharT, typename Traits>
617 class basic_streambuf : public std::basic_streambuf<CharT, Traits>
618 {
619  public:
620  typedef CharT char_type;
621  typedef Traits traits_type;
622  typedef typename traits_type::int_type int_type;
623  typedef typename traits_type::pos_type pos_type;
624  typedef typename traits_type::off_type off_type;
625 
627  basic_streambuf(const std::string &path)
628  : m_rsrc(path)
629  {
630  init();
631  }
632 
635  : m_rsrc(rsrc)
636  {
637  init();
638  }
639 
640  basic_streambuf(const basic_streambuf &) = delete;
641 
643  : basic_streambuf(rhs.m_rsrc)
644  {
645  }
646 
647  basic_streambuf &operator=(const basic_streambuf &) = delete;
648 
650  {
651  swap(rhs);
652  return *this;
653  }
654 
656  {
657  std::swap(m_begin, rhs.m_begin);
658  std::swap(m_end, rhs.m_end);
659  std::swap(m_current, rhs.m_current);
660  }
661 
662  private:
663  void init()
664  {
665  m_begin = reinterpret_cast<const char_type *>(m_rsrc.data());
666  m_end = reinterpret_cast<const char_type *>(m_rsrc.data() + m_rsrc.size());
667  m_current = m_begin;
668  }
669 
670  int_type underflow()
671  {
672  if (m_current == m_end)
673  return traits_type::eof();
674 
675  return traits_type::to_int_type(*m_current);
676  }
677 
678  int_type uflow()
679  {
680  if (m_current == m_end)
681  return traits_type::eof();
682 
683  return traits_type::to_int_type(*m_current++);
684  }
685 
686  int_type pbackfail(int_type ch)
687  {
688  if (m_current == m_begin or (ch != traits_type::eof() and ch != m_current[-1]))
689  return traits_type::eof();
690 
691  return traits_type::to_int_type(*--m_current);
692  }
693 
694  std::streamsize showmanyc()
695  {
696  assert(std::less_equal<const char *>()(m_current, m_end));
697  return m_end - m_current;
698  }
699 
700  pos_type seekoff(off_type off, std::ios_base::seekdir dir, std::ios_base::openmode which)
701  {
702  switch (dir)
703  {
704  case std::ios_base::beg:
705  m_current = m_begin + off;
706  break;
707 
708  case std::ios_base::end:
709  m_current = m_end + off;
710  break;
711 
712  case std::ios_base::cur:
713  m_current += off;
714  break;
715 
716  default:
717  break;
718  }
719 
720  if (m_current < m_begin)
721  m_current = m_begin;
722 
723  if (m_current > m_end)
724  m_current = m_end;
725 
726  return m_current - m_begin;
727  }
728 
729  pos_type seekpos(pos_type pos, std::ios_base::openmode which)
730  {
731  m_current = m_begin + pos;
732 
733  if (m_current < m_begin)
734  m_current = m_begin;
735 
736  if (m_current > m_end)
737  m_current = m_end;
738 
739  return m_current - m_begin;
740  }
741 
742  private:
743  rsrc m_rsrc;
744  const char_type *m_begin;
745  const char_type *m_end;
746  const char_type *m_current;
747 };
748 
750 
751 // --------------------------------------------------------------------
752 // class mrsrc::istream
753 
754 template <typename CharT, typename Traits>
755 class basic_istream : public std::basic_istream<CharT, Traits>
756 {
757  public:
758  typedef CharT char_type;
759  typedef Traits traits_type;
760  typedef typename traits_type::int_type int_type;
761  typedef typename traits_type::pos_type pos_type;
762  typedef typename traits_type::off_type off_type;
763 
764  private:
766  using __istream_type = std::basic_istream<CharT, Traits>;
767 
768  __streambuf_type m_buffer;
769 
770  public:
771  basic_istream(const std::string &path)
772  : __istream_type(&m_buffer)
773  , m_buffer(path)
774  {
775  this->init(&m_buffer);
776  }
777 
778  basic_istream(rsrc &resource)
779  : __istream_type(&m_buffer)
780  , m_buffer(resource)
781  {
782  this->init(&m_buffer);
783  }
784 
785  basic_istream(const basic_istream &) = delete;
786 
788  : __istream_type(std::move(rhs))
789  , m_buffer(std::move(rhs.m_buffer))
790  {
791  __istream_type::set_rdbuf(&m_buffer);
792  }
793 
794  basic_istream &operator=(const basic_istream &) = delete;
795 
797  {
798  __istream_type::operator=(std::move(rhs));
799  m_buffer = std::move(rhs.m_buffer);
800  return *this;
801  }
802 
803  void swap(basic_istream &rhs)
804  {
805  __istream_type::swap(rhs);
806  m_buffer.swap(rhs.m_buffer);
807  }
808 
810  {
811  return const_cast<__streambuf_type *>(&m_buffer);
812  }
813 };
814 
816 } // namespace mrsrc
817 
818 // --------------------------------------------------------------------
819 
820 namespace cif
821 {
822 
823 // --------------------------------------------------------------------
824 
826 {
827  public:
829  {
830  static std::unique_ptr<ResourcePool> s_instance(new ResourcePool);
831  return *s_instance;
832  }
833 
834  void pushDir(fs::path dir)
835  {
836  std::error_code ec;
837 
838  if (fs::exists(dir, ec) and not ec)
839  mDirs.push_front(dir);
840  }
841 
842  void pushDir(const char *path)
843  {
844  if (path != nullptr)
845  pushDir(fs::path(path));
846  }
847 
848  void pushAlias(const std::string &name, std::filesystem::path dataFile)
849  {
850  std::error_code ec;
851  if (not fs::exists(dataFile, ec) or ec)
852  throw std::runtime_error("Attempt to add a file resource for " + name + " that cannot be used (" + dataFile.string() + ") :" + ec.message());
853 
854  mLocalResources[name] = dataFile;
855  }
856 
857  std::unique_ptr<std::istream> load(fs::path name);
858 
859  private:
860  ResourcePool();
861 
862  std::unique_ptr<std::ifstream> open(fs::path &p)
863  {
864  std::unique_ptr<std::ifstream> result;
865 
866  try
867  {
868  if (fs::exists(p))
869  {
870  std::unique_ptr<std::ifstream> file(new std::ifstream(p, std::ios::binary));
871  if (file->is_open())
872  result.reset(file.release());
873  }
874  }
875  catch (...)
876  {
877  }
878 
879  return result;
880  }
881 
882  std::map<std::string, std::filesystem::path> mLocalResources;
883  std::deque<fs::path> mDirs;
884 };
885 
886 ResourcePool::ResourcePool()
887 {
888 #if defined(DATA_DIR)
889  pushDir(DATA_DIR);
890 #endif
891 
892  pushDir(getenv("LIBCIFPP_DATA_DIR"));
893 
894  auto ccp4 = getenv("CCP4");
895  if (ccp4 != nullptr)
896  pushDir(fs::path(ccp4) / "share" / "libcifpp");
897 
898 #if defined(CACHE_DIR)
899  pushDir(CACHE_DIR);
900 #endif
901 }
902 
903 std::unique_ptr<std::istream> ResourcePool::load(fs::path name)
904 {
905  std::unique_ptr<std::istream> result;
906  std::error_code ec;
907 
908  fs::path p = name;
909 
910  if (mLocalResources.count(name.string()))
911  result = open(mLocalResources[name.string()]);
912 
913  for (auto di = mDirs.begin(); not result and di != mDirs.end(); ++di)
914  {
915  auto p2 = *di / p;
916  if (fs::exists(p2, ec) and not ec)
917  result = open(p2);
918  }
919 
920  // if (not result and gResourceData)
921  if (not result and (gResourceIndex[0].m_child > 0 or gResourceIndex[0].m_size > 0))
922  {
923  mrsrc::rsrc rsrc(name);
924  if (rsrc)
925  result.reset(new mrsrc::istream(rsrc));
926  }
927 
928  return result;
929 }
930 
931 // --------------------------------------------------------------------
932 
933 void add_data_directory(std::filesystem::path dataDir)
934 {
935  ResourcePool::instance().pushDir(dataDir);
936 }
937 
938 void add_file_resource(const std::string &name, std::filesystem::path dataFile)
939 {
940  ResourcePool::instance().pushAlias(name, dataFile);
941 }
942 
943 std::unique_ptr<std::istream> load_resource(std::filesystem::path name)
944 {
945  return ResourcePool::instance().load(name);
946 }
947 
948 } // namespace cif
uint32_t get_terminal_width()
Definition: utilities.cpp:110
Mutex mutex
basic_streambuf(basic_streambuf &&rhs)
Definition: utilities.cpp:642
std::ptrdiff_t difference_type
Definition: utilities.cpp:514
basic_istream(basic_istream &&rhs)
Definition: utilities.cpp:787
std::thread mThread
Definition: utilities.cpp:166
std::atomic< int64_t > mConsumed
Definition: utilities.cpp:161
traits_type::int_type int_type
Definition: utilities.cpp:622
bool operator==(const iterator_t &rhs) const
Definition: utilities.cpp:553
const char gResourceData[1]
Definition: utilities.cpp:429
std::mutex mMutex
Definition: utilities.cpp:165
unsigned int m_child
Definition: utilities.cpp:402
iterator_t operator++(int)
Definition: utilities.cpp:546
const char * data(unsigned int offset) const
Definition: utilities.cpp:447
HBITMAP buffer
Definition: svm-toy.cpp:37
unsigned int m_next
Definition: utilities.cpp:401
static rsrc_data & instance()
Definition: utilities.cpp:439
iterator_t & operator++()
Definition: utilities.cpp:537
basic_streambuf(const rsrc &rsrc)
constructor taking a rsrc
Definition: utilities.cpp:634
unsigned int m_size
Definition: utilities.cpp:404
std::input_iterator_tag iterator_category
Definition: utilities.cpp:512
basic_istream & operator=(basic_istream &&rhs)
Definition: utilities.cpp:796
const mrsrc::rsrc_imp gResourceIndex[1]
Definition: utilities.cpp:428
iterator_t & operator=(const iterator_t &i)
Definition: utilities.cpp:528
const __attribute__((weak)) mrsrc const __attribute__((weak)) char gResourceData[]
std::unique_ptr< std::istream > load_resource(std::filesystem::path name)
Definition: utilities.cpp:943
void add_file_resource(const std::string &name, std::filesystem::path dataFile)
Definition: utilities.cpp:938
traits_type::pos_type pos_type
Definition: utilities.cpp:761
void swap(basic_istream &rhs)
Definition: utilities.cpp:803
static ResourcePool & instance()
Definition: utilities.cpp:828
double * di
iterator begin() const
Definition: utilities.cpp:562
#define i
const char * name(unsigned int offset) const
Definition: utilities.cpp:452
unsigned int m_data
Definition: utilities.cpp:405
Class mrsrc::rsrc contains a pointer to the data in the resource, as well as offering an iterator int...
Definition: utilities.cpp:479
rsrc(const rsrc &other)
Definition: utilities.cpp:487
viol index
rsrc & operator=(const rsrc &other)
Definition: utilities.cpp:492
traits_type::int_type int_type
Definition: utilities.cpp:760
traits_type::off_type off_type
Definition: utilities.cpp:624
unsigned long size() const
Definition: utilities.cpp:504
const char gResourceName[1]
Definition: utilities.cpp:430
bool operator!=(const iterator_t &rhs) const
Definition: utilities.cpp:554
basic_streambuf(const std::string &path)
constructor taking a path to the resource in memory
Definition: utilities.cpp:627
std::string name() const
Definition: utilities.cpp:500
basic_istream(const std::string &path)
Definition: utilities.cpp:771
basic_istream(rsrc &resource)
Definition: utilities.cpp:778
int VERBOSE
Definition: utilities.cpp:58
__streambuf_type * rdbuf() const
Definition: utilities.cpp:809
void add_data_directory(std::filesystem::path dataDir)
Definition: utilities.cpp:933
traits_type::off_type off_type
Definition: utilities.cpp:762
std::string get_version_nr()
Definition: utilities.cpp:62
int trunc(double x)
Definition: ap.cpp:7248
void pushAlias(const std::string &name, std::filesystem::path dataFile)
Definition: utilities.cpp:848
iterator_t(const iterator_t &i)
Definition: utilities.cpp:523
iterator_t(const rsrc_imp *cur)
Definition: utilities.cpp:518
std::string mMessage
Definition: utilities.cpp:164
Internal data structure as generated by mrc.
Definition: utilities.cpp:399
const char * data() const
Definition: utilities.cpp:502
unsigned int m_name
Definition: utilities.cpp:403
value_type & reference
Definition: utilities.cpp:516
traits_type::pos_type pos_type
Definition: utilities.cpp:623
void pushDir(const char *path)
Definition: utilities.cpp:842
ProgressImpl(int64_t inMax, const std::string &inAction)
Definition: utilities.cpp:140
iterator end() const
Definition: utilities.cpp:570
#define pi
void pushDir(fs::path dir)
Definition: utilities.cpp:834
basic_streambuf & operator=(basic_streambuf &&rhs)
Definition: utilities.cpp:649
const rsrc_imp * index() const
Definition: utilities.cpp:445
std::unique_ptr< std::istream > load(fs::path name)
Definition: utilities.cpp:903
int * n
std::string get_executable_path()
Definition: utilities.cpp:123
void swap(basic_streambuf &rhs)
Definition: utilities.cpp:655