aboutsummaryrefslogtreecommitdiff
path: root/libbutl/manifest-rewriter.mxx
blob: 6cba68227a41f057a00769cc0d329a1f337bf237 (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
// file      : libbutl/manifest-rewriter.mxx -*- C++ -*-
// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd
// license   : MIT; see accompanying LICENSE file

#ifndef __cpp_modules
#pragma once
#endif

// C includes.

#ifndef __cpp_lib_modules
#endif

// Other includes.

#ifdef __cpp_modules
export module butl.manifest_rewriter;
#ifdef __cpp_lib_modules
#endif
import butl.path;
import butl.fdstream;
import butl.manifest_types;
#else
#include <libbutl/path.mxx>
#include <libbutl/fdstream.mxx>
#include <libbutl/manifest-types.mxx>
#endif

#include <libbutl/export.hxx>

LIBBUTL_MODEXPORT namespace butl
{
  // Rewrite a hand-written manifest file preserving formatting, comments,
  // etc., of the unaffected parts. The general workflow is as follows:
  //
  // 1. Parse the manifest file using manifest_parser into a sequence of
  //    name/value pairs and their positions.
  //
  // 2. Create an instance of manifest_rewriter for the manifest file. This
  //    opens the file in read/write mode with exclusive access.
  //
  // 3. Iterate over this sequence in reverse and apply changes to the desired
  //    name/value pairs using the below API. Doing this in reverse makes sure
  //    the positions obtained on step 1 remain valid.
  //
  // Note that if an exception is thrown by replace() or insert(), then the
  // writer is no longer usable and there is no guarantees that the file is
  // left in a consistent state.
  //
  class LIBBUTL_SYMEXPORT manifest_rewriter
  {
  public:
    manifest_rewriter (path);

    // Replace the existing value at the specified position (specifically,
    // between colon_pos and end_pos) with the specified new value. The new
    // value is serialized as if by manifest_serializer.
    //
    void
    replace (const manifest_name_value&);

    // Insert a new name/value after the specified position (specifically,
    // after end_pos). To insert before the first value, use the special
    // start-of-manifest value as position. The new name/value is serialized
    // as if by manifest_serializer. Throw manifest_serialization exception
    // on error.
    //
    void
    insert (const manifest_name_value& pos, const manifest_name_value&);

  private:
    path path_;
    auto_fd fd_;
  };
}