aboutsummaryrefslogtreecommitdiff
path: root/bdep/utility.txx
blob: 38f0e35ca2ca69af2b2bdd4e9de8a64507bcd6c5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
// file      : bdep/utility.txx -*- C++ -*-
// copyright : Copyright (c) 2014-2017 Code Synthesis Ltd
// license   : MIT; see accompanying LICENSE file

#include <iostream> // cin

#include <libbutl/fdstream.mxx>

#include <libbutl/manifest-parser.mxx>
#include <libbutl/manifest-serializer.mxx>

#include <bdep/diagnostics.hxx>

namespace bdep
{
  // *_manifest()
  //
  template <typename T>
  T
  parse_manifest (const path& f, const char* what, bool iu)
  {
    using namespace butl;

    try
    {
      if (f.string () == "-")
        return parse_manifest<T> (std::cin, "stdin", what, iu);

      if (!file_exists (f))
        fail << what << " manifest file " << f << " does not exist";

      ifdstream ifs (f);
      return parse_manifest<T> (ifs, f.string (), what, iu);
    }
    catch (const system_error& e) // EACCES, etc.
    {
      fail << "unable to access " << what << " manifest " << f << ": " << e
           << endf;
    }
  }

  template <typename T>
  T
  parse_manifest (istream& is, const string& name, const char* what, bool iu)
  {
    using namespace butl;

    try
    {
      manifest_parser p (is, name);
      return T (p, iu);
    }
    catch (const manifest_parsing& e)
    {
      fail << "invalid " << what << " manifest: " << name << ':'
           << e.line << ':' << e.column << ": " << e.description << endf;
    }
    catch (const io_error& e)
    {
      fail << "unable to read " << what << " manifest " << name << ": " << e
           << endf;
    }
  }

  template <typename T>
  void
  serialize_manifest (const T& m, const path& f, const char* what)
  {
    using namespace std;
    using namespace butl;

    try
    {
      ofdstream ofs (f, ios::binary);
      auto_rmfile arm (f); // Try to remove on failure ignoring errors.

      serialize_manifest (m, ofs, f.string (), what);

      ofs.close ();
      arm.cancel ();
    }
    catch (const system_error& e) // EACCES, etc.
    {
      fail << "unable to access " << what << " manifest " << f << ": " << e;
    }
  }

  template <typename T>
  void
  serialize_manifest (const T& m,
                      ostream& os,
                      const string& name,
                      const char* what)
  {
    using namespace butl;

    try
    {
      manifest_serializer s (os, name);
      m.serialize (s);
      return;
    }
    catch (const manifest_serialization& e)
    {
      fail << "invalid " << what << " manifest: " << e.description;
    }
    catch (const io_error& e)
    {
      fail << "unable to write " << what << " manifest " << name << ": " << e;
    }
  }
}