File: utils.cc

package info (click to toggle)
glom 1.30.4-7
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 41,260 kB
  • sloc: ansic: 160,257; cpp: 72,338; javascript: 9,331; sh: 4,971; xml: 476; makefile: 315; perl: 236
file content (153 lines) | stat: -rw-r--r-- 4,844 bytes parent folder | download | duplicates (3)
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#include <tests/import/utils.h>
#include <libglom/utils.h>
#include <glibmm/convert.h>
#include <glibmm/fileutils.h>
#include <glibmm/main.h>

namespace ImportTests
{

//The result just shows whether it finished before the timeout.
static bool finished_parsing = true;

bool check(const std::string& name, bool test, std::stringstream& report)
{
  if(!test)
    report << name << ": FAILED" << std::endl;

  return test;
}

// Returns the file URI of the temporary created file, which will contain the buffer's contents.
static Glib::ustring create_file_from_buffer(const char* input, guint input_size)
{
  const auto file_uri = Glom::Utils::get_temp_file_uri("glom_import_testdata");
  if(file_uri.empty())
  {
    std::cerr << G_STRFUNC << ": file_uri was empty." << std::endl;
    return std::string();
  }

  Glib::RefPtr<Gio::File> file = Gio::File::create_for_uri(file_uri);

  gssize result = 0;
 
  try
  {
    result = file->append_to()->write(input, input_size);
    g_return_val_if_fail(-1 < result, "");
  }
  catch(const Gio::Error& ex)
  {
    std::cerr << G_STRFUNC << ": Gio::File::write() failed: " << ex.what() << std::endl;
    return std::string();
  }

  return file_uri;
}

static void on_mainloop_killed_by_watchdog(const Glib::RefPtr<Glib::MainLoop>& mainloop)
{
  finished_parsing = false;
  //Quit the mainloop that we ran because the parser uses an idle handler.
  mainloop->quit();
}

static void on_parser_encoding_error(const Glib::RefPtr<Glib::MainLoop>& mainloop)
{
  finished_parsing = true;
  //Quit the mainloop that we ran because the parser uses an idle handler.
  mainloop->quit();
}

static void on_parser_finished(const Glib::RefPtr<Glib::MainLoop>& mainloop)
{
  finished_parsing = true;
  //Quit the mainloop that we ran because the parser uses an idle handler.
  mainloop->quit();
}

static void on_file_read_error(const std::string& /*unused*/, const Glib::RefPtr<Glib::MainLoop>& mainloop)
{
  finished_parsing = true;
  //Quit the mainloop that we ran because the parser uses an idle handler.
  mainloop->quit();
}

bool run_parser_from_buffer(const FuncConnectParserSignals& connect_parser_signals, const std::string& input)
{
  return run_parser_from_buffer(connect_parser_signals, input.data(), input.size());
}

bool run_parser_from_buffer(const FuncConnectParserSignals& connect_parser_signals, const char* input, guint input_size)
{
  finished_parsing = true;

  //Start a mainloop because the parser uses an idle handler.
  //TODO: Stop the parser from doing that.
  Glib::RefPtr<Glib::MainLoop> mainloop = Glib::MainLoop::create();
  Glom::CsvParser parser("UTF-8");

  parser.signal_encoding_error().connect(sigc::bind(&on_parser_encoding_error, mainloop));
  parser.signal_finished_parsing().connect(sigc::bind(&on_parser_finished, mainloop));

  // Install a watchdog for the mainloop. No test should need longer than 300
  // seconds. Also, we need to avoid being stuck in the mainloop.
  // Infinitely running tests are useless.
  mainloop->get_context()->signal_timeout().connect_seconds_once(sigc::bind(&on_mainloop_killed_by_watchdog, mainloop), 300);

  connect_parser_signals(parser);

  const auto file_uri = create_file_from_buffer(input, input_size);
  parser.set_file_and_start_parsing(file_uri);
  if(Glom::CsvParser::State::PARSING != parser.get_state())
    return false;

  mainloop->run();

  Glib::RefPtr<Gio::File> file = Gio::File::create_for_uri(file_uri);

  try
  {
    const auto removed = file->remove();
    g_assert(removed);
  }
  catch(const Gio::Error& ex)
  {
    std::cerr << G_STRFUNC << ": Gio::File::remove() failed: " << ex.what() << std::endl;
    return false;
  }

  return finished_parsing;
}

bool run_parser_on_file(const FuncConnectParserSignals& connect_parser_signals, const std::string &uri)
{
  finished_parsing = true;

  //Start a mainloop because the parser uses an idle handler.
  //TODO: Stop the parser from doing that.
  Glib::RefPtr<Glib::MainLoop> mainloop = Glib::MainLoop::create();
  Glom::CsvParser parser("UTF-8");

  parser.signal_encoding_error().connect(sigc::bind(&on_parser_encoding_error, mainloop));
  parser.signal_finished_parsing().connect(sigc::bind(&on_parser_finished, mainloop));
  parser.signal_file_read_error().connect(sigc::bind(&on_file_read_error, mainloop));

  // Install a watchdog for the mainloop. No test should need longer than 300
  // seconds. Also, we need to avoid being stuck in the mainloop.
  // Infinitely running tests are useless.
  mainloop->get_context()->signal_timeout().connect_seconds_once(sigc::bind(&on_mainloop_killed_by_watchdog, mainloop), 300);

  connect_parser_signals(parser);

  parser.set_file_and_start_parsing(uri);
  if(Glom::CsvParser::State::PARSING != parser.get_state())
    return false;

  mainloop->run();

  return finished_parsing;
}

} //namespace ImportTests