<commit_before>#include <taichi/common/util.h>

#if defined(TC_PLATFORM_WINDOWS)
#include <windowsx.h>
#include <taichi/common/task.h>
#include <taichi/visual/gui.h>
#include <map>

// Note: some code is copied from MSDN:
// https://docs.microsoft.com/en-us/windows/desktop/learnwin32/introduction-to-windows-programming-in-c--

std::map<HWND, taichi::GUI *> gui_from_hwnd;

LRESULT CALLBACK WindowProc(HWND hwnd,
                            UINT uMsg,
                            WPARAM wParam,
                            LPARAM lParam) {
  auto dc = GetDC(hwnd);
  auto gui = gui_from_hwnd[hwnd];
  using namespace taichi;
  int x, y;
  switch (uMsg) {
    case WM_DESTROY:
      PostQuitMessage(0);
      exit(0);
      return 0;
    case WM_LBUTTONDOWN:
      gui->mouse_event(
          GUI::MouseEvent{GUI::MouseEvent::Type::press, gui->cursor_pos});
      break;
    case WM_LBUTTONUP:
      gui->mouse_event(
          GUI::MouseEvent{GUI::MouseEvent::Type::release, gui->cursor_pos});
      break;
    case WM_MOUSEMOVE:
      x = GET_X_LPARAM(lParam);
      y = GET_Y_LPARAM(lParam);
      gui->set_mouse_pos(x, gui->height - 1 - y);
      gui->mouse_event(
          GUI::MouseEvent{GUI::MouseEvent::Type::move, gui->cursor_pos});
      break;
    case WM_PAINT:
      break;
  }
  return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

TC_NAMESPACE_BEGIN

void GUI::process_event() {
  MSG msg;
  if (PeekMessage(&msg, hwnd, 0, 0, PM_REMOVE)) {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
  }
}

void GUI::create_window() {
  const char CLASS_NAME[] = "Taichi Win32 Window";

  WNDCLASS wc = {};

  wc.lpfnWndProc = WindowProc;
  wc.hInstance = GetModuleHandle(0);
  wc.lpszClassName = CLASS_NAME;

  RegisterClass(&wc);

  hwnd = CreateWindowEx(0,                    // Optional window styles.
                        CLASS_NAME,           // Window class
                        window_name.c_str(),  // Window text
                        WS_OVERLAPPEDWINDOW,  // Window style
                        // Size and position
                        CW_USEDEFAULT, CW_USEDEFAULT, width + 16, height + 32,
                        NULL,                // Parent window
                        NULL,                // Menu
                        GetModuleHandle(0),  // Instance handle
                        NULL                 // Additional application data
  );

  gui_from_hwnd[hwnd] = this;

  if (hwnd == NULL) {
    TC_ERROR("Window creation failed");
  }

  ShowWindow(hwnd, SW_SHOWDEFAULT);
  hdc = GetDC(hwnd);
  data = (COLORREF *)calloc(width * height, sizeof(COLORREF));
  src = CreateCompatibleDC(hdc);
}

void GUI::redraw() {
  UpdateWindow(hwnd);
  // http:// www.cplusplus.com/reference/cstdlib/calloc/
  for (int i = 0; i < width; i++) {
    for (int j = 0; j < height; j++) {
      auto c = reinterpret_cast<unsigned char *>(data + (j * width) + i);
      c[0] = (unsigned char)(canvas->img[i][height - j - 1][2] * 255.0_f);
      c[1] = (unsigned char)(canvas->img[i][height - j - 1][1] * 255.0_f);
      c[2] = (unsigned char)(canvas->img[i][height - j - 1][0] * 255.0_f);
      c[3] = 0;
    }
  }
  bitmap = CreateBitmap(width, height, 1, 32, (void *)data);
  SelectObject(src, bitmap);
  BitBlt(hdc, 0, 0, width, height, src, 0, 0, SRCCOPY);
  DeleteObject(bitmap);
}

void GUI::set_title(std::string title) {
  SetWindowText(hwnd, title.c_str());
}

GUI::~GUI() {
  std::free(data);
  DeleteDC(src);
  gui_from_hwnd.erase(hwnd);
}

TC_NAMESPACE_END

#endif<commit_msg>WM_CLOSE message handler<commit_after>#include <taichi/common/util.h>

#if defined(TC_PLATFORM_WINDOWS)
#include <windowsx.h>
#include <taichi/common/task.h>
#include <taichi/visual/gui.h>
#include <map>

// Note: some code is copied from MSDN:
// https://docs.microsoft.com/en-us/windows/desktop/learnwin32/introduction-to-windows-programming-in-c--

std::map<HWND, taichi::GUI *> gui_from_hwnd;

LRESULT CALLBACK WindowProc(HWND hwnd,
                            UINT uMsg,
                            WPARAM wParam,
                            LPARAM lParam) {
  auto dc = GetDC(hwnd);
  auto gui = gui_from_hwnd[hwnd];
  using namespace taichi;
  int x, y;
  switch (uMsg) {
    case WM_DESTROY:
      PostQuitMessage(0);
      exit(0);
      return 0;
    case WM_LBUTTONDOWN:
      gui->mouse_event(
          GUI::MouseEvent{GUI::MouseEvent::Type::press, gui->cursor_pos});
      break;
    case WM_LBUTTONUP:
      gui->mouse_event(
          GUI::MouseEvent{GUI::MouseEvent::Type::release, gui->cursor_pos});
      break;
    case WM_MOUSEMOVE:
      x = GET_X_LPARAM(lParam);
      y = GET_Y_LPARAM(lParam);
      gui->set_mouse_pos(x, gui->height - 1 - y);
      gui->mouse_event(
          GUI::MouseEvent{GUI::MouseEvent::Type::move, gui->cursor_pos});
      break;
    case WM_PAINT:
      break;
    case WM_CLOSE:
      exit(0);
      break;
  }
  return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

TC_NAMESPACE_BEGIN

void GUI::process_event() {
  MSG msg;
  if (PeekMessage(&msg, hwnd, 0, 0, PM_REMOVE)) {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
  }
}

void GUI::create_window() {
  const char CLASS_NAME[] = "Taichi Win32 Window";

  WNDCLASS wc = {};

  wc.lpfnWndProc = WindowProc;
  wc.hInstance = GetModuleHandle(0);
  wc.lpszClassName = CLASS_NAME;

  RegisterClass(&wc);

  hwnd = CreateWindowEx(0,                    // Optional window styles.
                        CLASS_NAME,           // Window class
                        window_name.c_str(),  // Window text
                        WS_OVERLAPPEDWINDOW,  // Window style
                        // Size and position
                        CW_USEDEFAULT, CW_USEDEFAULT, width + 16, height + 32,
                        NULL,                // Parent window
                        NULL,                // Menu
                        GetModuleHandle(0),  // Instance handle
                        NULL                 // Additional application data
  );

  gui_from_hwnd[hwnd] = this;

  if (hwnd == NULL) {
    TC_ERROR("Window creation failed");
  }

  ShowWindow(hwnd, SW_SHOWDEFAULT);
  hdc = GetDC(hwnd);
  data = (COLORREF *)calloc(width * height, sizeof(COLORREF));
  src = CreateCompatibleDC(hdc);
}

void GUI::redraw() {
  UpdateWindow(hwnd);
  // http:// www.cplusplus.com/reference/cstdlib/calloc/
  for (int i = 0; i < width; i++) {
    for (int j = 0; j < height; j++) {
      auto c = reinterpret_cast<unsigned char *>(data + (j * width) + i);
      c[0] = (unsigned char)(canvas->img[i][height - j - 1][2] * 255.0_f);
      c[1] = (unsigned char)(canvas->img[i][height - j - 1][1] * 255.0_f);
      c[2] = (unsigned char)(canvas->img[i][height - j - 1][0] * 255.0_f);
      c[3] = 0;
    }
  }
  bitmap = CreateBitmap(width, height, 1, 32, (void *)data);
  SelectObject(src, bitmap);
  BitBlt(hdc, 0, 0, width, height, src, 0, 0, SRCCOPY);
  DeleteObject(bitmap);
}

void GUI::set_title(std::string title) {
  SetWindowText(hwnd, title.c_str());
}

GUI::~GUI() {
  std::free(data);
  DeleteDC(src);
  gui_from_hwnd.erase(hwnd);
}

TC_NAMESPACE_END

#endif<|endoftext|>


<commit_before>#include <sys/types.h>
#include <sys/errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#include <unistd.h>

#include <map>
#include <vector>

#include <common/buffer.h>
#include <common/endian.h>
#include <common/limits.h>
#include <common/timer/timer.h>

#include <xcodec/xcodec.h>
#include <xcodec/xcodec_cache.h>
#include <xcodec/xcodec_decoder.h>
#include <xcodec/xcodec_encoder.h>

enum FileAction {
	None, Compress, Decompress
};

static void compress(const std::string&, int, int, XCodec *, bool, Timer *, bool);
static void decompress(const std::string&, int, int, XCodec *, bool, Timer *, bool);
static bool fill(int, Buffer *);
static void flush(int, Buffer *);
static void print_ratio(const std::string&, uint64_t, uint64_t);
static void process_file(const std::string&, int, int, FileAction, XCodec *, bool, Timer *, bool);
static void process_files(int, char *[], FileAction, XCodec *, bool, bool, Timer *, bool);
static void time_samples(Timer *);
static void time_stats(Timer *);
static void usage(void);

int
main(int argc, char *argv[])
{
	UUID uuid;
	uuid.generate();

	XCodecCache *cache = XCodecCache::lookup(uuid);
	XCodec codec(cache);

	bool codec_timing, quiet_output, samples, stats, verbose;
	FileAction action;
	int ch;

	action = None;
	codec_timing = false;
	quiet_output = false;
	samples = false;
	stats = false;
	verbose = false;

	while ((ch = getopt(argc, argv, "?cdsvQST")) != -1) {
		switch (ch) {
		case 'c':
			action = Compress;
			break;
		case 'd':
			action = Decompress;
			break;
		case 's':
			stats = true;
			break;
		case 'v':
			verbose = true;
			break;
		case 'Q':
			quiet_output = true;
			break;
		case 'S':
			samples = true;
			break;
		case 'T':
			codec_timing = true;
			break;
		case '?':
		default:
			usage();
		}
	}
	argc -= optind;
	argv += optind;

	if (verbose) {
		Log::mask(".?", Log::Debug);
	} else {
		Log::mask(".?", Log::Info);
	}

	Timer codec_timer;

	switch (action) {
	case None:
		usage();
	case Compress:
	case Decompress:
		process_files(argc, argv, action, &codec, quiet_output, codec_timing, &codec_timer, stats);
		if (samples)
			time_samples(&codec_timer);
		if (codec_timing)
			time_stats(&codec_timer);
		break;
	default:
		NOTREACHED();
	}

	return (0);
}

static void
compress(const std::string& name, int ifd, int ofd, XCodec *codec, bool timing, Timer *timer, bool stats)
{
	XCodecEncoder encoder(codec->cache());
	Buffer input, output;
	uint64_t inbytes, outbytes;

	if (stats)
		inbytes = outbytes = 0;

	while (fill(ifd, &input)) {
		if (stats)
			inbytes += input.length();
		if (timing)
			timer->start();
		encoder.encode(&output, &input);
		if (timing)
			timer->stop();
		if (stats) {
			inbytes -= input.length();
			outbytes += output.length();
		}
		flush(ofd, &output);
	}
	ASSERT(input.empty());
	ASSERT(output.empty());

	if (stats)
		print_ratio(name, inbytes, outbytes);
}

static void
decompress(const std::string& name, int ifd, int ofd, XCodec *codec, bool timing, Timer *timer, bool stats)
{
	std::set<uint64_t> unknown_hashes;
	XCodecDecoder decoder(codec->cache());
	Buffer input, output;
	uint64_t inbytes, outbytes;

	(void)codec;

	if (stats)
		inbytes = outbytes = 0;

	while (fill(ifd, &input)) {
		if (stats)
			inbytes += input.length();
		if (timing)
			timer->start();
		if (!decoder.decode(&output, &input, unknown_hashes)) {
			ERROR("/decompress") << "Decode failed.";
			return;
		}
		if (timing)
			timer->stop();
		if (!unknown_hashes.empty()) {
			ERROR("/decompress") << "Cannot decode stream with unknown hashes.";
			return;
		}
		if (stats) {
			inbytes -= input.length();
			outbytes += output.length();
		}
		flush(ofd, &output);
	}
	ASSERT(input.empty());
	ASSERT(output.empty());

	if (stats)
		print_ratio(name, inbytes, outbytes);
}

static bool
fill(int fd, Buffer *input)
{
	uint8_t data[65536];
	ssize_t len;

	len = read(fd, data, sizeof data);
	if (len == -1)
		HALT("/fill") << "read failed.";
	if (len == 0)
		return (false);
	input->append(data, len);
	return (true);
}

static void
flush(int fd, Buffer *output)
{
	ssize_t len;

	if (fd == -1) {
		output->clear();
		return;
	}

	for (;;) {
		Buffer::SegmentIterator iter = output->segments();
		if (iter.end())
			break;

		const BufferSegment *seg = *iter;

		len = write(fd, seg->data(), seg->length());
		if (len != (ssize_t)seg->length())
			HALT("/output") << "write failed.";
		output->skip((size_t)len);
	}
	ASSERT(output->empty());
}

static void
print_ratio(const std::string& name, uint64_t inbytes, uint64_t outbytes)
{
	INFO("/codec_stats") << name << ": " << inbytes << " bytes in, " << outbytes << " bytes out.";
}

static void
process_file(const std::string& name, int ifd, int ofd, FileAction action, XCodec *codec, bool timing, Timer *timer, bool stats)
{
	switch (action) {
	case Compress:
		compress(name, ifd, ofd, codec, timing, timer, stats);
		break;
	case Decompress:
		decompress(name, ifd, ofd, codec, timing, timer, stats);
		break;
	default:
		NOTREACHED();
	}
}

static void
process_files(int argc, char *argv[], FileAction action, XCodec *codec, bool quiet, bool timing, Timer *timer, bool stats)
{
	int ifd, ofd;

	if (argc == 0) {
		ifd = STDIN_FILENO;
		if (quiet)
			ofd = -1;
		else
			ofd = STDOUT_FILENO;
		process_file("<stdin>", ifd, ofd, action, codec, timing, timer, stats);
	} else {
		while (argc--) {
			const char *file = *argv++;

			ifd = open(file, O_RDONLY);
			ASSERT(ifd != -1);
			if (quiet)
				ofd = -1;
			else
				ofd = STDOUT_FILENO;

			process_file(file, ifd, ofd, action, codec, timing, timer, stats);

			close(ifd);
		}
	}
}

static void
time_samples(Timer *timer)
{
	std::vector<uintmax_t> samples = timer->samples();
	std::vector<uintmax_t>::iterator it;

	for (it = samples.begin(); it != samples.end(); ++it)
		fprintf(stderr, "%ju\n", *it);
}

static void
time_stats(Timer *timer)
{
	std::vector<uintmax_t> samples = timer->samples();
	std::vector<uintmax_t>::iterator it;
	LogHandle log("/codec_timer");
	uintmax_t microseconds;

	INFO(log) << samples.size() << " timer samples.";
	microseconds = 0;
	for (it = samples.begin(); it != samples.end(); ++it)
		microseconds += *it;
	INFO(log) << microseconds << " total runtime.";
	INFO(log) << (microseconds / samples.size()) << " mean microseconds/call.";
}

static void
usage(void)
{
	fprintf(stderr,
"usage: tack [-svQST] -c [file ...]\n"
"       tack [-svQST] -d [file ...]\n");
	exit(1);
}
<commit_msg>Spew ratios.<commit_after>#include <sys/types.h>
#include <sys/errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#include <unistd.h>

#include <map>
#include <vector>

#include <common/buffer.h>
#include <common/endian.h>
#include <common/limits.h>
#include <common/timer/timer.h>

#include <xcodec/xcodec.h>
#include <xcodec/xcodec_cache.h>
#include <xcodec/xcodec_decoder.h>
#include <xcodec/xcodec_encoder.h>

enum FileAction {
	None, Compress, Decompress
};

static void compress(const std::string&, int, int, XCodec *, bool, Timer *, bool);
static void decompress(const std::string&, int, int, XCodec *, bool, Timer *, bool);
static bool fill(int, Buffer *);
static void flush(int, Buffer *);
static void print_ratio(const std::string&, uint64_t, uint64_t);
static void process_file(const std::string&, int, int, FileAction, XCodec *, bool, Timer *, bool);
static void process_files(int, char *[], FileAction, XCodec *, bool, bool, Timer *, bool);
static void time_samples(Timer *);
static void time_stats(Timer *);
static void usage(void);

int
main(int argc, char *argv[])
{
	UUID uuid;
	uuid.generate();

	XCodecCache *cache = XCodecCache::lookup(uuid);
	XCodec codec(cache);

	bool codec_timing, quiet_output, samples, stats, verbose;
	FileAction action;
	int ch;

	action = None;
	codec_timing = false;
	quiet_output = false;
	samples = false;
	stats = false;
	verbose = false;

	while ((ch = getopt(argc, argv, "?cdsvQST")) != -1) {
		switch (ch) {
		case 'c':
			action = Compress;
			break;
		case 'd':
			action = Decompress;
			break;
		case 's':
			stats = true;
			break;
		case 'v':
			verbose = true;
			break;
		case 'Q':
			quiet_output = true;
			break;
		case 'S':
			samples = true;
			break;
		case 'T':
			codec_timing = true;
			break;
		case '?':
		default:
			usage();
		}
	}
	argc -= optind;
	argv += optind;

	if (verbose) {
		Log::mask(".?", Log::Debug);
	} else {
		Log::mask(".?", Log::Info);
	}

	Timer codec_timer;

	switch (action) {
	case None:
		usage();
	case Compress:
	case Decompress:
		process_files(argc, argv, action, &codec, quiet_output, codec_timing, &codec_timer, stats);
		if (samples)
			time_samples(&codec_timer);
		if (codec_timing)
			time_stats(&codec_timer);
		break;
	default:
		NOTREACHED();
	}

	return (0);
}

static void
compress(const std::string& name, int ifd, int ofd, XCodec *codec, bool timing, Timer *timer, bool stats)
{
	XCodecEncoder encoder(codec->cache());
	Buffer input, output;
	uint64_t inbytes, outbytes;

	if (stats)
		inbytes = outbytes = 0;

	while (fill(ifd, &input)) {
		if (stats)
			inbytes += input.length();
		if (timing)
			timer->start();
		encoder.encode(&output, &input);
		if (timing)
			timer->stop();
		if (stats) {
			inbytes -= input.length();
			outbytes += output.length();
		}
		flush(ofd, &output);
	}
	ASSERT(input.empty());
	ASSERT(output.empty());

	if (stats)
		print_ratio(name, inbytes, outbytes);
}

static void
decompress(const std::string& name, int ifd, int ofd, XCodec *codec, bool timing, Timer *timer, bool stats)
{
	std::set<uint64_t> unknown_hashes;
	XCodecDecoder decoder(codec->cache());
	Buffer input, output;
	uint64_t inbytes, outbytes;

	(void)codec;

	if (stats)
		inbytes = outbytes = 0;

	while (fill(ifd, &input)) {
		if (stats)
			inbytes += input.length();
		if (timing)
			timer->start();
		if (!decoder.decode(&output, &input, unknown_hashes)) {
			ERROR("/decompress") << "Decode failed.";
			return;
		}
		if (timing)
			timer->stop();
		if (!unknown_hashes.empty()) {
			ERROR("/decompress") << "Cannot decode stream with unknown hashes.";
			return;
		}
		if (stats) {
			inbytes -= input.length();
			outbytes += output.length();
		}
		flush(ofd, &output);
	}
	ASSERT(input.empty());
	ASSERT(output.empty());

	if (stats)
		print_ratio(name, inbytes, outbytes);
}

static bool
fill(int fd, Buffer *input)
{
	uint8_t data[65536];
	ssize_t len;

	len = read(fd, data, sizeof data);
	if (len == -1)
		HALT("/fill") << "read failed.";
	if (len == 0)
		return (false);
	input->append(data, len);
	return (true);
}

static void
flush(int fd, Buffer *output)
{
	ssize_t len;

	if (fd == -1) {
		output->clear();
		return;
	}

	for (;;) {
		Buffer::SegmentIterator iter = output->segments();
		if (iter.end())
			break;

		const BufferSegment *seg = *iter;

		len = write(fd, seg->data(), seg->length());
		if (len != (ssize_t)seg->length())
			HALT("/output") << "write failed.";
		output->skip((size_t)len);
	}
	ASSERT(output->empty());
}

static void
print_ratio(const std::string& name, uint64_t inbytes, uint64_t outbytes)
{
	INFO("/codec_stats") << name << ": " << inbytes << " bytes in, " << outbytes << " bytes out.";
	if (inbytes <= outbytes) {
		INFO("/codec_stats") << name << ": bloat ratio 1:" << ((float)outbytes / inbytes) << " (" << ((float)inbytes / outbytes) << ":1)";
	} else {
		INFO("/codec_stats") << name << ": compression ratio 1:" << ((float)outbytes / inbytes) << " (" << ((float)inbytes / outbytes) << ":1)";
	}
}

static void
process_file(const std::string& name, int ifd, int ofd, FileAction action, XCodec *codec, bool timing, Timer *timer, bool stats)
{
	switch (action) {
	case Compress:
		compress(name, ifd, ofd, codec, timing, timer, stats);
		break;
	case Decompress:
		decompress(name, ifd, ofd, codec, timing, timer, stats);
		break;
	default:
		NOTREACHED();
	}
}

static void
process_files(int argc, char *argv[], FileAction action, XCodec *codec, bool quiet, bool timing, Timer *timer, bool stats)
{
	int ifd, ofd;

	if (argc == 0) {
		ifd = STDIN_FILENO;
		if (quiet)
			ofd = -1;
		else
			ofd = STDOUT_FILENO;
		process_file("<stdin>", ifd, ofd, action, codec, timing, timer, stats);
	} else {
		while (argc--) {
			const char *file = *argv++;

			ifd = open(file, O_RDONLY);
			ASSERT(ifd != -1);
			if (quiet)
				ofd = -1;
			else
				ofd = STDOUT_FILENO;

			process_file(file, ifd, ofd, action, codec, timing, timer, stats);

			close(ifd);
		}
	}
}

static void
time_samples(Timer *timer)
{
	std::vector<uintmax_t> samples = timer->samples();
	std::vector<uintmax_t>::iterator it;

	for (it = samples.begin(); it != samples.end(); ++it)
		fprintf(stderr, "%ju\n", *it);
}

static void
time_stats(Timer *timer)
{
	std::vector<uintmax_t> samples = timer->samples();
	std::vector<uintmax_t>::iterator it;
	LogHandle log("/codec_timer");
	uintmax_t microseconds;

	INFO(log) << samples.size() << " timer samples.";
	microseconds = 0;
	for (it = samples.begin(); it != samples.end(); ++it)
		microseconds += *it;
	INFO(log) << microseconds << " total runtime.";
	INFO(log) << (microseconds / samples.size()) << " mean microseconds/call.";
}

static void
usage(void)
{
	fprintf(stderr,
"usage: tack [-svQST] -c [file ...]\n"
"       tack [-svQST] -d [file ...]\n");
	exit(1);
}
<|endoftext|>


<commit_before>/*! \file */ //Copyright 2011-2018 Tyler Gilbert; All Rights Reserved

#include "inet/Http.hpp"
#include "var.hpp"
#include "sys.hpp"
#include "inet/Url.hpp"

using namespace inet;

Http::Http(Socket & socket) : m_socket(socket){

}

HttpClient::HttpClient(Socket & socket) : Http(socket){
	m_transfer_size = 1024;
	m_is_chunked_transfer_encoding = false;
}

int HttpClient::get(const var::ConstString & url, const sys::File & response, const sys::ProgressCallback * progress_callback){
	return query("GET", url, 0, &response, progress_callback);
}

int HttpClient::post(const var::ConstString & url, const var::ConstString & request, const sys::File & response, const sys::ProgressCallback * progress_callback){
	DataFile request_file;
	request_file.data().copy_cstring(request.cstring());
	return post(url, request_file, response, progress_callback);
}

int HttpClient::post(const var::ConstString & url, const sys::File & request, const sys::File & response, const sys::ProgressCallback * progress_callback){
	return query("POST", url, &request, &response, progress_callback);
}

int HttpClient::put(const var::ConstString & url, const var::ConstString & request, const sys::File & response, const sys::ProgressCallback * progress_callback){
	DataFile request_file;
	request_file.data().copy_cstring(request.cstring());
	return put(url, request_file, response, progress_callback);
}

int HttpClient::put(const var::ConstString & url, const sys::File & data, const sys::File & response, const sys::ProgressCallback * progress_callback){
	return query("PUT", url, &data, &response, progress_callback);
}

int HttpClient::patch(const var::ConstString & url, const var::ConstString & request, const sys::File & response, const sys::ProgressCallback * progress_callback){
	DataFile request_file;
	request_file.data().copy_cstring(request.cstring());
	return patch(url, request_file, response, progress_callback);
}

int HttpClient::patch(const var::ConstString & url, const sys::File & data, const sys::File & response, const sys::ProgressCallback * progress_callback){
	return query("PATCH", url, &data, &response, progress_callback);
}

int HttpClient::head(const var::ConstString & url){

	return 0;
}

int HttpClient::remove(const var::ConstString & request, const var::String & data){

	return 0;
}

int HttpClient::query(const var::ConstString & command,
							 const var::ConstString & url,
							 const sys::File * send_file,
							 const sys::File * get_file,
							 const sys::ProgressCallback * progress_callback){
	int result;
	Url u(url);
	result = connect_to_server(u.domain_name(), u.port());
	if( result < 0 ){
		return result;
	}

	result = send_header(command, u.domain_name(), u.path(), send_file, progress_callback);
	if( result < 0 ){
		return result;
	}

	if( send_file ){
		//send the file on the socket
		socket().write(*send_file, m_transfer_size);
	}

	listen_for_header();
	if( get_file ){
		listen_for_data(*get_file, progress_callback);
	}

	if( is_keep_alive() == false ){
		close_connection();
	}

	return 0;

}

int HttpClient::send_string(const var::ConstString & str){
	if( !str.is_empty() ){
		return socket().write(str.str(), str.length());
	}
	return 0;
}

int HttpClient::close_connection(){
	return socket().close();
}

int HttpClient::connect_to_server(const var::ConstString & domain_name, u16 port){
	SocketAddressInfo address_info;

	if( (socket().fileno() >= 0) && is_keep_alive() ){
		//already connected
		return 0;
	}

	var::Vector<SocketAddressInfo> address_list = address_info.fetch_node(domain_name);
	if( address_list.count() > 0 ){
		m_address = address_list.at(0);
		m_address.set_port(port);
		if( socket().create(m_address)  < 0 ){
			return -1;
		}

		if( socket().connect(m_address) < 0 ){
			return -1;
		}

		return 0;
	}

	return -1;
}

int HttpClient::build_header(const var::ConstString & method, const var::ConstString & host, const var::ConstString & path, u32 length){
	bool is_user_agent_present = false;
	bool is_accept_present = false;
	bool is_keep_alive_present = false;
	m_header.clear();
	m_header << method << " " << path << " HTTP/1.1\r\n";
	m_header << "Host: " << host << "\r\n";

	for(u32 i = 0; i < header_request_fields().count(); i++){
		if( header_request_fields().at(i).is_empty() == false ){
			m_header << header_request_fields().at(i) << "\r\n";
			if( header_request_fields().at(i).find("User-Agent:") == 0 ){ is_user_agent_present = true; }
			if( header_request_fields().at(i).find("Accept:") == 0 ){ is_accept_present = true; }
			if( header_request_fields().at(i).find("Connection:") == 0 ){ is_keep_alive_present = true; }
		}
	}

	if( !is_keep_alive_present ){
		if( is_keep_alive() ){
			m_header << "Connection: keep-alive\r\n";
		}
	}
	if( !is_user_agent_present ){ m_header << "User-Agent: StratifyOS\r\n"; }
	if( !is_accept_present ){ m_header << "Accept: */*\r\n"; }

	if( length > 0 ){
		m_header << "Content-Length: " << String().format(F32U, length) << "\r\n";
	}
	m_header << "\r\n";

	return 0;
}

int HttpClient::send_header(const var::ConstString & method,
									 const var::ConstString & host,
									 const var::ConstString & path,
									 const sys::File * file,
									 const sys::ProgressCallback * progress_callback){

	u32 data_length = file != 0 ? file->size() : 0;

	build_header(method, host, path, data_length);

	//printf(">> %s", m_header.str());

	if( socket().write(m_header) != (int)m_header.length() ){
		return -1;
	}

	if( file ){
		if( socket().write(*file, m_transfer_size, file->size(), progress_callback) < 0 ){
			return -1;
		}
	}

	return 0;
}

int HttpClient::listen_for_header(){

	var::String line;
	do {
		line = socket().gets('\n');
		if( line.length() > 2 ){

			m_header << line;

			//printf("> %s", line.str());

			var::Token line_tokens(line, ": \t\r\n");
			var::String title = line_tokens.at(0);
			var::String value;
			if( line_tokens.count() > 1 ){
				value = line_tokens.at(1);
			}

			var::String rebuild_line;
			rebuild_line << title << ": " << value;
			m_header_response_fields.push_back(rebuild_line);

			title.to_upper();
			value.to_upper();

			if( title == "HTTP/1.1" ){ m_status_code = value.atoi(); }
			if( title == "CONTENT-LENGTH" ){ m_content_length = value.atoi(); }
			if( title == "TRANSFER-ENCODING" ){ m_transfer_encoding = value; }
		}

	} while( line.length() > 2 ); //while reading the header

	return -1;
}

int HttpClient::listen_for_data(const sys::File & file, const sys::ProgressCallback * progress_callback){
	if( m_transfer_encoding == "CHUNKED" ){
		u32 bytes_incoming = 0;
		do {
			String line = socket().gets();
			//convert line from hex
			bytes_incoming = line.to_unsigned_long(16);

			//read bytes_incoming from the socket and write it to the output file
			if( file.write(socket(), bytes_incoming, bytes_incoming) != (int)bytes_incoming ){
				return -1;
			}

			//need to call the progress callback -- what is the total?

		} while( bytes_incoming > 0 );

	} else {
		//read the response from the socket
		file.write(socket(), m_transfer_size, m_content_length, progress_callback);
	}
	return 0;
}

<commit_msg>set default status code to -1<commit_after>/*! \file */ //Copyright 2011-2018 Tyler Gilbert; All Rights Reserved

#include "inet/Http.hpp"
#include "var.hpp"
#include "sys.hpp"
#include "inet/Url.hpp"

using namespace inet;

Http::Http(Socket & socket) : m_socket(socket){

}

HttpClient::HttpClient(Socket & socket) : Http(socket){
	m_transfer_size = 1024;
	m_is_chunked_transfer_encoding = false;
}

int HttpClient::get(const var::ConstString & url, const sys::File & response, const sys::ProgressCallback * progress_callback){
	return query("GET", url, 0, &response, progress_callback);
}

int HttpClient::post(const var::ConstString & url, const var::ConstString & request, const sys::File & response, const sys::ProgressCallback * progress_callback){
	DataFile request_file;
	request_file.data().copy_cstring(request.cstring());
	return post(url, request_file, response, progress_callback);
}

int HttpClient::post(const var::ConstString & url, const sys::File & request, const sys::File & response, const sys::ProgressCallback * progress_callback){
	return query("POST", url, &request, &response, progress_callback);
}

int HttpClient::put(const var::ConstString & url, const var::ConstString & request, const sys::File & response, const sys::ProgressCallback * progress_callback){
	DataFile request_file;
	request_file.data().copy_cstring(request.cstring());
	return put(url, request_file, response, progress_callback);
}

int HttpClient::put(const var::ConstString & url, const sys::File & data, const sys::File & response, const sys::ProgressCallback * progress_callback){
	return query("PUT", url, &data, &response, progress_callback);
}

int HttpClient::patch(const var::ConstString & url, const var::ConstString & request, const sys::File & response, const sys::ProgressCallback * progress_callback){
	DataFile request_file;
	request_file.data().copy_cstring(request.cstring());
	return patch(url, request_file, response, progress_callback);
}

int HttpClient::patch(const var::ConstString & url, const sys::File & data, const sys::File & response, const sys::ProgressCallback * progress_callback){
	return query("PATCH", url, &data, &response, progress_callback);
}

int HttpClient::head(const var::ConstString & url){

	return 0;
}

int HttpClient::remove(const var::ConstString & request, const var::String & data){

	return 0;
}

int HttpClient::query(const var::ConstString & command,
							 const var::ConstString & url,
							 const sys::File * send_file,
							 const sys::File * get_file,
							 const sys::ProgressCallback * progress_callback){
	m_status_code = -1;
	int result;
	Url u(url);
	result = connect_to_server(u.domain_name(), u.port());
	if( result < 0 ){
		return result;
	}

	result = send_header(command, u.domain_name(), u.path(), send_file, progress_callback);
	if( result < 0 ){
		return result;
	}

	if( send_file ){
		//send the file on the socket
		socket().write(*send_file, m_transfer_size);
	}

	listen_for_header();
	if( get_file ){
		listen_for_data(*get_file, progress_callback);
	}

	if( is_keep_alive() == false ){
		close_connection();
	}

	return 0;

}

int HttpClient::send_string(const var::ConstString & str){
	if( !str.is_empty() ){
		return socket().write(str.str(), str.length());
	}
	return 0;
}

int HttpClient::close_connection(){
	return socket().close();
}

int HttpClient::connect_to_server(const var::ConstString & domain_name, u16 port){
	SocketAddressInfo address_info;

	if( (socket().fileno() >= 0) && is_keep_alive() ){
		//already connected
		return 0;
	}

	var::Vector<SocketAddressInfo> address_list = address_info.fetch_node(domain_name);
	if( address_list.count() > 0 ){
		m_address = address_list.at(0);
		m_address.set_port(port);
		if( socket().create(m_address)  < 0 ){
			return -1;
		}

		if( socket().connect(m_address) < 0 ){
			return -1;
		}

		return 0;
	}

	return -1;
}

int HttpClient::build_header(const var::ConstString & method, const var::ConstString & host, const var::ConstString & path, u32 length){
	bool is_user_agent_present = false;
	bool is_accept_present = false;
	bool is_keep_alive_present = false;
	m_header.clear();
	m_header << method << " " << path << " HTTP/1.1\r\n";
	m_header << "Host: " << host << "\r\n";

	for(u32 i = 0; i < header_request_fields().count(); i++){
		if( header_request_fields().at(i).is_empty() == false ){
			m_header << header_request_fields().at(i) << "\r\n";
			if( header_request_fields().at(i).find("User-Agent:") == 0 ){ is_user_agent_present = true; }
			if( header_request_fields().at(i).find("Accept:") == 0 ){ is_accept_present = true; }
			if( header_request_fields().at(i).find("Connection:") == 0 ){ is_keep_alive_present = true; }
		}
	}

	if( !is_keep_alive_present ){
		if( is_keep_alive() ){
			m_header << "Connection: keep-alive\r\n";
		}
	}
	if( !is_user_agent_present ){ m_header << "User-Agent: StratifyOS\r\n"; }
	if( !is_accept_present ){ m_header << "Accept: */*\r\n"; }

	if( length > 0 ){
		m_header << "Content-Length: " << String().format(F32U, length) << "\r\n";
	}
	m_header << "\r\n";

	return 0;
}

int HttpClient::send_header(const var::ConstString & method,
									 const var::ConstString & host,
									 const var::ConstString & path,
									 const sys::File * file,
									 const sys::ProgressCallback * progress_callback){

	u32 data_length = file != 0 ? file->size() : 0;

	build_header(method, host, path, data_length);

	//printf(">> %s", m_header.str());

	if( socket().write(m_header) != (int)m_header.length() ){
		return -1;
	}

	if( file ){
		if( socket().write(*file, m_transfer_size, file->size(), progress_callback) < 0 ){
			return -1;
		}
	}

	return 0;
}

int HttpClient::listen_for_header(){

	var::String line;
	do {
		line = socket().gets('\n');
		if( line.length() > 2 ){

			m_header << line;

			//printf("> %s", line.str());

			var::Token line_tokens(line, ": \t\r\n");
			var::String title = line_tokens.at(0);
			var::String value;
			if( line_tokens.count() > 1 ){
				value = line_tokens.at(1);
			}

			var::String rebuild_line;
			rebuild_line << title << ": " << value;
			m_header_response_fields.push_back(rebuild_line);

			title.to_upper();
			value.to_upper();

			if( title == "HTTP/1.1" ){ m_status_code = value.atoi(); }
			if( title == "CONTENT-LENGTH" ){ m_content_length = value.atoi(); }
			if( title == "TRANSFER-ENCODING" ){ m_transfer_encoding = value; }
		}

	} while( line.length() > 2 ); //while reading the header

	return -1;
}

int HttpClient::listen_for_data(const sys::File & file, const sys::ProgressCallback * progress_callback){
	if( m_transfer_encoding == "CHUNKED" ){
		u32 bytes_incoming = 0;
		do {
			String line = socket().gets();
			//convert line from hex
			bytes_incoming = line.to_unsigned_long(16);

			//read bytes_incoming from the socket and write it to the output file
			if( file.write(socket(), bytes_incoming, bytes_incoming) != (int)bytes_incoming ){
				return -1;
			}

			//need to call the progress callback -- what is the total?

		} while( bytes_incoming > 0 );

	} else {
		//read the response from the socket
		file.write(socket(), m_transfer_size, m_content_length, progress_callback);
	}
	return 0;
}

<|endoftext|>


<commit_before>/*******************************************************************************
 Infomap software package for multi-level network clustering
 Copyright (c) 2013, 2014 Daniel Edler, Anton Eriksson, Martin Rosvall

 This file is part of the Infomap software package.
 See file LICENSE_AGPLv3.txt for full license details.
 For more information, see <http://www.mapequation.org>
 ******************************************************************************/

#include "Config.h"
#include "ProgramInterface.h"
#include "SafeFile.h"
#include "../utils/FileURI.h"
#include "../utils/Log.h"
#include <vector>
#include <stdexcept>

namespace infomap {

constexpr int FlowModel::undirected;
constexpr int FlowModel::directed;
constexpr int FlowModel::undirdir;
constexpr int FlowModel::outdirdir;
constexpr int FlowModel::rawdir;

Config::Config(const std::string& flags, bool isCLI) : isCLI(isCLI)
{
  ProgramInterface api("Infomap",
                       "Implementation of the Infomap clustering algorithm based on the Map Equation (see www.mapequation.org)",
                       INFOMAP_VERSION);

  api.setGroups({ "Input", "Algorithm", "Accuracy", "Output" });

  bool deprecated_includeSelfLinks = false;
  std::vector<std::string> optionalOutputDir; // Used if !isCLI
  // --------------------- Input options ---------------------
  if (isCLI) {
    api.addNonOptionArgument(networkFile, "network_file", "File containing the network data. Assumes a link list format if no Pajek formatted heading.", "Input");
  } else {
    api.addOptionArgument(networkFile, "input", "File containing the network data. Assumes a link list format if no Pajek formatted heading.", ArgType::path, "Input");
  }

  api.addOptionArgument(skipAdjustBipartiteFlow, "skip-adjust-bipartite-flow", "Skip distributing all flow from the bipartite nodes to the primary nodes.", "Input", true);

  api.addOptionArgument(bipartiteTeleportation, "bipartite-teleportation", "Teleport like the bipartite flow instead of two-step (unipartite) teleportation.", "Input", true);

  api.addOptionArgument(weightThreshold, "weight-threshold", "Limit the number of links to read from the network. Ignore links with less weight than the threshold.", ArgType::number, "Input", true);

  api.addOptionArgument(deprecated_includeSelfLinks, 'k', "include-self-links", "DEPRECATED. Include self links by default now, exclude with --no-self-links.", "Input", true);

  api.addOptionArgument(noSelfLinks, "no-self-links", "Exclude self links in the input network.", "Input", true);

  api.addOptionArgument(nodeLimit, "node-limit", "Limit the number of nodes to read from the network. Ignore links connected to ignored nodes.", ArgType::integer, "Input", true);

  api.addOptionArgument(matchableMultilayerIds, "matchable-multilayer-ids", "Construct state ids from node and layer ids that are consistent across networks for the same max number of layers. Set to at least the largest layer id among networks to match.", ArgType::integer, "Input", true);

  api.addOptionArgument(clusterDataFile, 'c', "cluster-data", "Provide an initial two-level (clu format) or multi-layer (tree format) solution.", ArgType::path, "Input");

  api.addOptionArgument(assignToNeighbouringModule, "assign-to-neighbouring-module", "Assign nodes without module assignments (from --cluster-data) to the module assignment of a neighbouring node if possible.", "Input", true);

  api.addOptionArgument(metaDataFile, "meta-data", "Provide meta data (clu format) that should be encoded.", ArgType::path, "Input", true);

  api.addOptionArgument(metaDataRate, "meta-data-rate", "Metadata encoding rate. Default is to encode each step.", ArgType::number, "Input", true);

  api.addOptionArgument(unweightedMetaData, "meta-data-unweighted", "Don't weight meta data by node flow.", "Input", true);

  api.addOptionArgument(noInfomap, "no-infomap", "Don't run the optimizer. Useful to calculate codelength of provided cluster data or to print non-modular statistics.", "Input");

  // --------------------- Output options ---------------------

  api.addOptionArgument(outName, "out-name", "Name for the output files, e.g. [output_directory]/[out-name].tree", ArgType::string, "Output", true);

  api.addOptionArgument(noFileOutput, '0', "no-file-output", "Don't write output to file.", "Output", true);

  api.addOptionArgument(printTree, "tree", "Write a tree file with the modular hierarchy. Automatically enabled if no other output is specified.", "Output");

  api.addOptionArgument(printFlowTree, "ftree", "Write a ftree file with the modular hierarchy including aggregated links between (nested) modules. (Used by Network Navigator)", "Output");

  api.addOptionArgument(printClu, "clu", "Write a clu file with the top cluster ids for each node.", "Output");

  api.addOptionArgument(cluLevel, "clu-level", "For clu output, print modules at specified depth from root. Use -1 for bottom level modules.", ArgType::integer, "Output", true);

  api.addOptionArgument(outputFormats, 'o', "output", "Comma-separated output formats without spaces, e.g. -o clu,tree,ftree. Options: clu, tree, ftree, newick, json, csv, network, states, flow.", ArgType::list, "Output", true);

  api.addOptionArgument(hideBipartiteNodes, "hide-bipartite-nodes", "Project bipartite solution to unipartite.", "Output", true);

  api.addOptionArgument(printAllTrials, "print-all-trials", "Print all trials to separate files.", "Output", true);

  // --------------------- Core algorithm options ---------------------
  api.addOptionArgument(twoLevel, '2', "two-level", "Optimize a two-level partition of the network. Default is multi-level.", "Algorithm");

  std::string flowModelArg;

  api.addOptionArgument(flowModelArg, 'f', "flow-model", "Specify flow model. Options: undirected, directed, undirdir, outdirdir, rawdir.", ArgType::option, "Algorithm");

  api.addOptionArgument(directed, 'd', "directed", "Assume directed links. Shorthand for '--flow-model directed'.", "Algorithm");

  api.addOptionArgument(recordedTeleportation, 'e', "recorded-teleportation", "If teleportation is used to calculate the flow, also record it when minimizing codelength.", "Algorithm", true);

  api.addOptionArgument(useNodeWeightsAsFlow, "use-node-weights-as-flow", "Use node weights (from api or after names in Pajek format) as flow, normalized to sum to 1", "Algorithm", true);

  api.addOptionArgument(teleportToNodes, "to-nodes", "Teleport to nodes instead of to links, assuming uniform node weights if no such input data.", "Algorithm", true);

  api.addOptionArgument(teleportationProbability, 'p', "teleportation-probability", "Probability of teleporting to a random node or link.", ArgType::probability, "Algorithm", true);

  api.addOptionArgument(regularized, "regularized", "Effectively add a fully connected Bayesian prior network to not overfit due to missing links. Implies recorded teleportation", "Algorithm", true);

  api.addOptionArgument(regularizationStrength, "regularization-strength", "Adjust relative strength of Bayesian prior network with this multiplier.", ArgType::number, "Algorithm", true);

  api.addOptionArgument(entropyBiasCorrection, "entropy-corrected", "Correct for negative entropy bias in small samples (many modules).", "Algorithm", true);

  api.addOptionArgument(entropyBiasCorrectionMultiplier, "entropy-correction-strength", "Increase or decrease the default entropy correction with this factor.", ArgType::number, "Algorithm", true);

  api.addOptionArgument(markovTime, "markov-time", "Scales link flow to change the cost of moving between modules. Higher values results in fewer modules.", ArgType::number, "Algorithm", true);

  api.addOptionArgument(preferredNumberOfModules, "preferred-number-of-modules", "Penalize solutions the more they differ from this number.", ArgType::integer, "Algorithm", true);

  api.addOptionArgument(multilayerRelaxRate, "multilayer-relax-rate", "Probability to relax the constraint to move only in the current layer.", ArgType::probability, "Algorithm", true);

  api.addOptionArgument(multilayerRelaxLimit, "multilayer-relax-limit", "Number of neighboring layers in each direction to relax to. If negative, relax to any layer.", ArgType::integer, "Algorithm", true);

  api.addOptionArgument(multilayerRelaxLimitUp, "multilayer-relax-limit-up", "Number of neighboring layers with higher id to relax to. If negative, relax to any layer.", ArgType::integer, "Algorithm", true);

  api.addOptionArgument(multilayerRelaxLimitDown, "multilayer-relax-limit-down", "Number of neighboring layers with lower id to relax to. If negative, relax to any layer.", ArgType::integer, "Algorithm", true);

  api.addOptionArgument(multilayerRelaxByJensenShannonDivergence, "multilayer-relax-by-jsd", "Relax proportional to the out-link similarity measured by the Jensen-Shannon divergence.", "Algorithm", true);

  // --------------------- Performance and accuracy options ---------------------
  api.addOptionArgument(seedToRandomNumberGenerator, 's', "seed", "A seed (integer) to the random number generator for reproducible results.", ArgType::integer, "Accuracy");

  api.addOptionArgument(numTrials, 'N', "num-trials", "Number of outer-most loops to run before picking the best solution.", ArgType::integer, "Accuracy");

  api.addOptionArgument(coreLoopLimit, 'M', "core-loop-limit", "Limit the number of loops that tries to move each node into the best possible module.", ArgType::integer, "Accuracy", true);

  api.addOptionArgument(levelAggregationLimit, 'L', "core-level-limit", "Limit the number of times the core loops are reapplied on existing modular network to search bigger structures.", ArgType::integer, "Accuracy", true);

  api.addOptionArgument(tuneIterationLimit, 'T', "tune-iteration-limit", "Limit the number of main iterations in the two-level partition algorithm. 0 means no limit.", ArgType::integer, "Accuracy", true);

  api.addOptionArgument(minimumCodelengthImprovement, "core-loop-codelength-threshold", "Minimum codelength threshold for accepting a new solution in core loop.", ArgType::number, "Accuracy", true);

  api.addOptionArgument(minimumRelativeTuneIterationImprovement, "tune-iteration-relative-threshold", "Set codelength improvement threshold of each new tune iteration to 'f' times the initial two-level codelength.", ArgType::number, "Accuracy", true);

  api.addIncrementalOptionArgument(fastHierarchicalSolution, 'F', "fast-hierarchical-solution", "Find top modules fast. Use -FF to keep all fast levels. Use -FFF to skip recursive part.", "Accuracy", true);

  api.addOptionArgument(preferModularSolution, "prefer-modular-solution", "Prefer modular solutions even if they are worse than putting all nodes in one module.", "Accuracy", true);

  api.addOptionArgument(innerParallelization, "inner-parallelization", "Parallelize the inner-most loop for greater speed. This may give some accuracy tradeoff.", "Accuracy", true);

  api.addOptionalNonOptionArguments(optionalOutputDir, "out_directory", "Directory to write the results to.", "Output");

  api.addIncrementalOptionArgument(verbosity, 'v', "verbose", "Verbose output on the console. Add additional 'v' flags to increase verbosity up to -vvv.", "Output");

  api.addOptionArgument(silent, "silent", "No output on the console.", "Output");

  api.parseArgs(flags);

  if (deprecated_includeSelfLinks) {
    throw std::runtime_error("The --include-self-links flag is deprecated to include self links by default. Use --no-self-links to exclude.");
  }

  if (!optionalOutputDir.empty())
    outDirectory = optionalOutputDir[0];

  if (!isCLI && outDirectory.empty())
    noFileOutput = true;

  if (!noFileOutput && outDirectory.empty() && isCLI) {
    throw std::runtime_error("Missing out_directory");
  }

  if (flowModelArg == "directed" || directed) {
    setFlowModel(FlowModel::directed);
  } else if (flowModelArg == "undirected") {
    setFlowModel(FlowModel::undirected);
  } else if (flowModelArg == "undirdir") {
    setFlowModel(FlowModel::undirdir);
  } else if (flowModelArg == "outdirdir") {
    setFlowModel(FlowModel::outdirdir);
  } else if (flowModelArg == "rawdir") {
    setFlowModel(FlowModel::rawdir);
  } else if (!flowModelArg.empty()) {
    throw std::runtime_error("Unrecognized flow model");
  }

  if (regularized) {
    recordedTeleportation = true;
  }

  if (*--outDirectory.end() != '/')
    outDirectory.append("/");

  if (haveOutput() && !isDirectoryWritable(outDirectory))
    throw std::runtime_error(io::Str() << "Can't write to directory '" << outDirectory << "'. Check that the directory exists and that you have write permissions.");

  if (outName.empty()) {
    outName = !networkFile.empty() ? FileURI(networkFile).getName() : "no-name";
  }

  parsedString = flags;
  parsedOptions = api.getUsedOptionArguments();

  adaptDefaults();

  Log::init(verbosity, silent, verboseNumberPrecision);
}

void Config::adaptDefaults()
{
  auto outputs = io::split(outputFormats, ',');
  for (std::string& o : outputs) {
    if (o == "clu") {
      printClu = true;
    } else if (o == "tree") {
      printTree = true;
    } else if (o == "ftree") {
      printFlowTree = true;
    } else if (o == "newick") {
      printNewick = true;
    } else if (o == "json") {
      printJson = true;
    } else if (o == "csv") {
      printCsv = true;
    } else if (o == "network") {
      printPajekNetwork = true;
    } else if (o == "flow") {
      printFlowNetwork = true;
    } else if (o == "states") {
      printStateNetwork = true;
    } else {
      throw std::runtime_error(io::Str() << "Unrecognized output format: '" << o << "'.");
    }
  }

  // Of no output format specified, use tree as default (if not used as a library).
  if (isCLI && !haveModularResultOutput()) {
    printTree = true;
  }
}

std::ostream& operator<<(std::ostream& out, FlowModel f)
{
  return out << flowModelToString(f);
}

} // namespace infomap
<commit_msg>fix: Don't allow less than 1 trial<commit_after>/*******************************************************************************
 Infomap software package for multi-level network clustering
 Copyright (c) 2013, 2014 Daniel Edler, Anton Eriksson, Martin Rosvall

 This file is part of the Infomap software package.
 See file LICENSE_AGPLv3.txt for full license details.
 For more information, see <http://www.mapequation.org>
 ******************************************************************************/

#include "Config.h"
#include "ProgramInterface.h"
#include "SafeFile.h"
#include "../utils/FileURI.h"
#include "../utils/Log.h"
#include <vector>
#include <stdexcept>

namespace infomap {

constexpr int FlowModel::undirected;
constexpr int FlowModel::directed;
constexpr int FlowModel::undirdir;
constexpr int FlowModel::outdirdir;
constexpr int FlowModel::rawdir;

Config::Config(const std::string& flags, bool isCLI) : isCLI(isCLI)
{
  ProgramInterface api("Infomap",
                       "Implementation of the Infomap clustering algorithm based on the Map Equation (see www.mapequation.org)",
                       INFOMAP_VERSION);

  api.setGroups({ "Input", "Algorithm", "Accuracy", "Output" });

  bool deprecated_includeSelfLinks = false;
  std::vector<std::string> optionalOutputDir; // Used if !isCLI
  // --------------------- Input options ---------------------
  if (isCLI) {
    api.addNonOptionArgument(networkFile, "network_file", "File containing the network data. Assumes a link list format if no Pajek formatted heading.", "Input");
  } else {
    api.addOptionArgument(networkFile, "input", "File containing the network data. Assumes a link list format if no Pajek formatted heading.", ArgType::path, "Input");
  }

  api.addOptionArgument(skipAdjustBipartiteFlow, "skip-adjust-bipartite-flow", "Skip distributing all flow from the bipartite nodes to the primary nodes.", "Input", true);

  api.addOptionArgument(bipartiteTeleportation, "bipartite-teleportation", "Teleport like the bipartite flow instead of two-step (unipartite) teleportation.", "Input", true);

  api.addOptionArgument(weightThreshold, "weight-threshold", "Limit the number of links to read from the network. Ignore links with less weight than the threshold.", ArgType::number, "Input", true);

  api.addOptionArgument(deprecated_includeSelfLinks, 'k', "include-self-links", "DEPRECATED. Include self links by default now, exclude with --no-self-links.", "Input", true);

  api.addOptionArgument(noSelfLinks, "no-self-links", "Exclude self links in the input network.", "Input", true);

  api.addOptionArgument(nodeLimit, "node-limit", "Limit the number of nodes to read from the network. Ignore links connected to ignored nodes.", ArgType::integer, "Input", true);

  api.addOptionArgument(matchableMultilayerIds, "matchable-multilayer-ids", "Construct state ids from node and layer ids that are consistent across networks for the same max number of layers. Set to at least the largest layer id among networks to match.", ArgType::integer, "Input", true);

  api.addOptionArgument(clusterDataFile, 'c', "cluster-data", "Provide an initial two-level (clu format) or multi-layer (tree format) solution.", ArgType::path, "Input");

  api.addOptionArgument(assignToNeighbouringModule, "assign-to-neighbouring-module", "Assign nodes without module assignments (from --cluster-data) to the module assignment of a neighbouring node if possible.", "Input", true);

  api.addOptionArgument(metaDataFile, "meta-data", "Provide meta data (clu format) that should be encoded.", ArgType::path, "Input", true);

  api.addOptionArgument(metaDataRate, "meta-data-rate", "Metadata encoding rate. Default is to encode each step.", ArgType::number, "Input", true);

  api.addOptionArgument(unweightedMetaData, "meta-data-unweighted", "Don't weight meta data by node flow.", "Input", true);

  api.addOptionArgument(noInfomap, "no-infomap", "Don't run the optimizer. Useful to calculate codelength of provided cluster data or to print non-modular statistics.", "Input");

  // --------------------- Output options ---------------------

  api.addOptionArgument(outName, "out-name", "Name for the output files, e.g. [output_directory]/[out-name].tree", ArgType::string, "Output", true);

  api.addOptionArgument(noFileOutput, '0', "no-file-output", "Don't write output to file.", "Output", true);

  api.addOptionArgument(printTree, "tree", "Write a tree file with the modular hierarchy. Automatically enabled if no other output is specified.", "Output");

  api.addOptionArgument(printFlowTree, "ftree", "Write a ftree file with the modular hierarchy including aggregated links between (nested) modules. (Used by Network Navigator)", "Output");

  api.addOptionArgument(printClu, "clu", "Write a clu file with the top cluster ids for each node.", "Output");

  api.addOptionArgument(cluLevel, "clu-level", "For clu output, print modules at specified depth from root. Use -1 for bottom level modules.", ArgType::integer, "Output", true);

  api.addOptionArgument(outputFormats, 'o', "output", "Comma-separated output formats without spaces, e.g. -o clu,tree,ftree. Options: clu, tree, ftree, newick, json, csv, network, states, flow.", ArgType::list, "Output", true);

  api.addOptionArgument(hideBipartiteNodes, "hide-bipartite-nodes", "Project bipartite solution to unipartite.", "Output", true);

  api.addOptionArgument(printAllTrials, "print-all-trials", "Print all trials to separate files.", "Output", true);

  // --------------------- Core algorithm options ---------------------
  api.addOptionArgument(twoLevel, '2', "two-level", "Optimize a two-level partition of the network. Default is multi-level.", "Algorithm");

  std::string flowModelArg;

  api.addOptionArgument(flowModelArg, 'f', "flow-model", "Specify flow model. Options: undirected, directed, undirdir, outdirdir, rawdir.", ArgType::option, "Algorithm");

  api.addOptionArgument(directed, 'd', "directed", "Assume directed links. Shorthand for '--flow-model directed'.", "Algorithm");

  api.addOptionArgument(recordedTeleportation, 'e', "recorded-teleportation", "If teleportation is used to calculate the flow, also record it when minimizing codelength.", "Algorithm", true);

  api.addOptionArgument(useNodeWeightsAsFlow, "use-node-weights-as-flow", "Use node weights (from api or after names in Pajek format) as flow, normalized to sum to 1", "Algorithm", true);

  api.addOptionArgument(teleportToNodes, "to-nodes", "Teleport to nodes instead of to links, assuming uniform node weights if no such input data.", "Algorithm", true);

  api.addOptionArgument(teleportationProbability, 'p', "teleportation-probability", "Probability of teleporting to a random node or link.", ArgType::probability, "Algorithm", true);

  api.addOptionArgument(regularized, "regularized", "Effectively add a fully connected Bayesian prior network to not overfit due to missing links. Implies recorded teleportation", "Algorithm", true);

  api.addOptionArgument(regularizationStrength, "regularization-strength", "Adjust relative strength of Bayesian prior network with this multiplier.", ArgType::number, "Algorithm", true);

  api.addOptionArgument(entropyBiasCorrection, "entropy-corrected", "Correct for negative entropy bias in small samples (many modules).", "Algorithm", true);

  api.addOptionArgument(entropyBiasCorrectionMultiplier, "entropy-correction-strength", "Increase or decrease the default entropy correction with this factor.", ArgType::number, "Algorithm", true);

  api.addOptionArgument(markovTime, "markov-time", "Scales link flow to change the cost of moving between modules. Higher values results in fewer modules.", ArgType::number, "Algorithm", true);

  api.addOptionArgument(preferredNumberOfModules, "preferred-number-of-modules", "Penalize solutions the more they differ from this number.", ArgType::integer, "Algorithm", true);

  api.addOptionArgument(multilayerRelaxRate, "multilayer-relax-rate", "Probability to relax the constraint to move only in the current layer.", ArgType::probability, "Algorithm", true);

  api.addOptionArgument(multilayerRelaxLimit, "multilayer-relax-limit", "Number of neighboring layers in each direction to relax to. If negative, relax to any layer.", ArgType::integer, "Algorithm", true);

  api.addOptionArgument(multilayerRelaxLimitUp, "multilayer-relax-limit-up", "Number of neighboring layers with higher id to relax to. If negative, relax to any layer.", ArgType::integer, "Algorithm", true);

  api.addOptionArgument(multilayerRelaxLimitDown, "multilayer-relax-limit-down", "Number of neighboring layers with lower id to relax to. If negative, relax to any layer.", ArgType::integer, "Algorithm", true);

  api.addOptionArgument(multilayerRelaxByJensenShannonDivergence, "multilayer-relax-by-jsd", "Relax proportional to the out-link similarity measured by the Jensen-Shannon divergence.", "Algorithm", true);

  // --------------------- Performance and accuracy options ---------------------
  api.addOptionArgument(seedToRandomNumberGenerator, 's', "seed", "A seed (integer) to the random number generator for reproducible results.", ArgType::integer, "Accuracy");

  int _numTrials = 1;
  api.addOptionArgument(_numTrials, 'N', "num-trials", "Number of outer-most loops to run before picking the best solution.", ArgType::integer, "Accuracy");

  api.addOptionArgument(coreLoopLimit, 'M', "core-loop-limit", "Limit the number of loops that tries to move each node into the best possible module.", ArgType::integer, "Accuracy", true);

  api.addOptionArgument(levelAggregationLimit, 'L', "core-level-limit", "Limit the number of times the core loops are reapplied on existing modular network to search bigger structures.", ArgType::integer, "Accuracy", true);

  api.addOptionArgument(tuneIterationLimit, 'T', "tune-iteration-limit", "Limit the number of main iterations in the two-level partition algorithm. 0 means no limit.", ArgType::integer, "Accuracy", true);

  api.addOptionArgument(minimumCodelengthImprovement, "core-loop-codelength-threshold", "Minimum codelength threshold for accepting a new solution in core loop.", ArgType::number, "Accuracy", true);

  api.addOptionArgument(minimumRelativeTuneIterationImprovement, "tune-iteration-relative-threshold", "Set codelength improvement threshold of each new tune iteration to 'f' times the initial two-level codelength.", ArgType::number, "Accuracy", true);

  api.addIncrementalOptionArgument(fastHierarchicalSolution, 'F', "fast-hierarchical-solution", "Find top modules fast. Use -FF to keep all fast levels. Use -FFF to skip recursive part.", "Accuracy", true);

  api.addOptionArgument(preferModularSolution, "prefer-modular-solution", "Prefer modular solutions even if they are worse than putting all nodes in one module.", "Accuracy", true);

  api.addOptionArgument(innerParallelization, "inner-parallelization", "Parallelize the inner-most loop for greater speed. This may give some accuracy tradeoff.", "Accuracy", true);

  api.addOptionalNonOptionArguments(optionalOutputDir, "out_directory", "Directory to write the results to.", "Output");

  api.addIncrementalOptionArgument(verbosity, 'v', "verbose", "Verbose output on the console. Add additional 'v' flags to increase verbosity up to -vvv.", "Output");

  api.addOptionArgument(silent, "silent", "No output on the console.", "Output");

  api.parseArgs(flags);

  if (deprecated_includeSelfLinks) {
    throw std::runtime_error("The --include-self-links flag is deprecated to include self links by default. Use --no-self-links to exclude.");
  }

  if (_numTrials < 1) {
    throw std::runtime_error("Must use at least 1 trial.");
  }
  numTrials = static_cast<unsigned int>(_numTrials);

  if (!optionalOutputDir.empty())
    outDirectory = optionalOutputDir[0];

  if (!isCLI && outDirectory.empty())
    noFileOutput = true;

  if (!noFileOutput && outDirectory.empty() && isCLI) {
    throw std::runtime_error("Missing out_directory");
  }

  if (flowModelArg == "directed" || directed) {
    setFlowModel(FlowModel::directed);
  } else if (flowModelArg == "undirected") {
    setFlowModel(FlowModel::undirected);
  } else if (flowModelArg == "undirdir") {
    setFlowModel(FlowModel::undirdir);
  } else if (flowModelArg == "outdirdir") {
    setFlowModel(FlowModel::outdirdir);
  } else if (flowModelArg == "rawdir") {
    setFlowModel(FlowModel::rawdir);
  } else if (!flowModelArg.empty()) {
    throw std::runtime_error("Unrecognized flow model");
  }

  if (regularized) {
    recordedTeleportation = true;
  }

  if (*--outDirectory.end() != '/')
    outDirectory.append("/");

  if (haveOutput() && !isDirectoryWritable(outDirectory))
    throw std::runtime_error(io::Str() << "Can't write to directory '" << outDirectory << "'. Check that the directory exists and that you have write permissions.");

  if (outName.empty()) {
    outName = !networkFile.empty() ? FileURI(networkFile).getName() : "no-name";
  }

  parsedString = flags;
  parsedOptions = api.getUsedOptionArguments();

  adaptDefaults();

  Log::init(verbosity, silent, verboseNumberPrecision);
}

void Config::adaptDefaults()
{
  auto outputs = io::split(outputFormats, ',');
  for (std::string& o : outputs) {
    if (o == "clu") {
      printClu = true;
    } else if (o == "tree") {
      printTree = true;
    } else if (o == "ftree") {
      printFlowTree = true;
    } else if (o == "newick") {
      printNewick = true;
    } else if (o == "json") {
      printJson = true;
    } else if (o == "csv") {
      printCsv = true;
    } else if (o == "network") {
      printPajekNetwork = true;
    } else if (o == "flow") {
      printFlowNetwork = true;
    } else if (o == "states") {
      printStateNetwork = true;
    } else {
      throw std::runtime_error(io::Str() << "Unrecognized output format: '" << o << "'.");
    }
  }

  // Of no output format specified, use tree as default (if not used as a library).
  if (isCLI && !haveModularResultOutput()) {
    printTree = true;
  }
}

std::ostream& operator<<(std::ostream& out, FlowModel f)
{
  return out << flowModelToString(f);
}

} // namespace infomap
<|endoftext|>


<commit_before>#include "CartoAssetPackageUpdater.h"
#include "core/BinaryData.h"
#include "components/Exceptions.h"
#include "utils/GeneralUtils.h"
#include "utils/NetworkUtils.h"
#include "utils/MemoryAssetPackage.h"
#include "utils/Log.h"

#include <utility>

#include <picojson/picojson.h>

namespace carto {

    CartoAssetPackageUpdater::CartoAssetPackageUpdater(const std::string& schema, const std::string& styleName) :
        _schema(schema),
        _styleName(styleName)
    {
    }

    CartoAssetPackageUpdater::~CartoAssetPackageUpdater() {
    }

    std::shared_ptr<MemoryAssetPackage> CartoAssetPackageUpdater::update(const std::shared_ptr<AssetPackage>& assetPackage) const {
        std::string projectFileName = _styleName + ".json";

        std::shared_ptr<BinaryData> fileData1 = assetPackage->loadAsset(projectFileName);
        picojson::value projectJson1 = ExtractFileData(fileData1);
        std::map<std::string, FileInfo> files1 = ReadFileInfo(projectJson1);

        std::shared_ptr<BinaryData> fileData2 = downloadFile(projectFileName);
        picojson::value projectJson2 = ExtractFileData(fileData2);
        std::map<std::string, FileInfo> files2 = ReadFileInfo(projectJson2);

        std::map<std::string, std::shared_ptr<BinaryData> > updatedAssets = updateFiles(files1, files2);
        if (projectJson1 != projectJson2) {
            updatedAssets[projectFileName] = fileData2;
        }
        return std::make_shared<MemoryAssetPackage>(updatedAssets, assetPackage);
    }

    std::shared_ptr<BinaryData> CartoAssetPackageUpdater::downloadFile(const std::string& fileName) const {
        std::vector<std::string> pathParts = GeneralUtils::Split(_schema + "/" + fileName, '/');
        std::transform(pathParts.begin(), pathParts.end(), pathParts.begin(), NetworkUtils::URLEncode);
        std::string urlEncodedFileName = GeneralUtils::Join(pathParts, '/');
        std::string url = STYLE_SERVICE_URL + urlEncodedFileName;

        std::shared_ptr<BinaryData> responseData;
        if (!NetworkUtils::GetHTTP(url, responseData, Log::IsShowDebug())) {
            Log::Warnf("CartoAssetPackageUpdater: Failed to fetch tile style data");
        }
        return responseData;
    }

    const std::string CartoAssetPackageUpdater::STYLE_SERVICE_URL = "http://mobile-api.carto.com/styles/";

}
<commit_msg>Fixed online style updater ignoring style.json changes<commit_after>#include "CartoAssetPackageUpdater.h"
#include "core/BinaryData.h"
#include "components/Exceptions.h"
#include "utils/GeneralUtils.h"
#include "utils/NetworkUtils.h"
#include "utils/MemoryAssetPackage.h"
#include "utils/Log.h"

#include <utility>

#include <picojson/picojson.h>

namespace carto {

    CartoAssetPackageUpdater::CartoAssetPackageUpdater(const std::string& schema, const std::string& styleName) :
        _schema(schema),
        _styleName(styleName)
    {
    }

    CartoAssetPackageUpdater::~CartoAssetPackageUpdater() {
    }

    std::shared_ptr<MemoryAssetPackage> CartoAssetPackageUpdater::update(const std::shared_ptr<AssetPackage>& assetPackage) const {
        std::string projectFileName = _styleName + ".json";

        std::shared_ptr<BinaryData> projectData1 = assetPackage->loadAsset(projectFileName);
        picojson::value filesJson1 = ExtractFileData(projectData1);
        std::map<std::string, FileInfo> files1 = ReadFileInfo(filesJson1);

        std::shared_ptr<BinaryData> projectData2 = downloadFile(projectFileName);
        picojson::value filesJson2 = ExtractFileData(projectData2);
        std::map<std::string, FileInfo> files2 = ReadFileInfo(filesJson2);

        std::map<std::string, std::shared_ptr<BinaryData> > updatedAssets = updateFiles(files1, files2);
        if (projectData1 && projectData2) {
            if (*projectData1 != *projectData2) {
                updatedAssets[projectFileName] = projectData2;
            }
        }
        return std::make_shared<MemoryAssetPackage>(updatedAssets, assetPackage);
    }

    std::shared_ptr<BinaryData> CartoAssetPackageUpdater::downloadFile(const std::string& fileName) const {
        std::vector<std::string> pathParts = GeneralUtils::Split(_schema + "/" + fileName, '/');
        std::transform(pathParts.begin(), pathParts.end(), pathParts.begin(), NetworkUtils::URLEncode);
        std::string urlEncodedFileName = GeneralUtils::Join(pathParts, '/');
        std::string url = STYLE_SERVICE_URL + urlEncodedFileName;

        std::shared_ptr<BinaryData> responseData;
        if (!NetworkUtils::GetHTTP(url, responseData, Log::IsShowDebug())) {
            Log::Warnf("CartoAssetPackageUpdater: Failed to fetch tile style data");
        }
        return responseData;
    }

    const std::string CartoAssetPackageUpdater::STYLE_SERVICE_URL = "http://mobile-api.carto.com/styles/";

}
<|endoftext|>


<commit_before>//=============================================================================================================
/**
 * @file     ftheaderparser.cpp
 * @author   Gabriel Motta <gbmotta@mgh.harvard.edu>
 *           Juan Garcia-Prieto <juangpc@gmail.com>;
 * @since    0.1.9
 * @date     July, 2021
 *
 * @section  LICENSE
 *
 * Copyright (C) 2020, Gabriel Motta, Juan Garcia-Prieto. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that
 * the following conditions are met:
 *     * Redistributions of source code must retain the above copyright notice, this list of conditions and the
 *       following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
 *       the following disclaimer in the documentation and/or other materials provided with the distribution.
 *     * Neither the name of MNE-CPP authors nor the names of its contributors may be used
 *       to endorse or promote products derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 *
 * @brief    Contains the definition of the FtHeaderParser class.
 *
 */

//=============================================================================================================
// INCLUDES
//=============================================================================================================

#include "ftheaderparser.h"

//=============================================================================================================
// QT INCLUDES
//=============================================================================================================

#include <QtEndian>

//=============================================================================================================
// USED NAMESPACES
//=============================================================================================================

using namespace FTBUFFERPLUGIN;

//=============================================================================================================
// DEFINE FREE FUNCTIONS
//=============================================================================================================

void FTBUFFERPLUGIN::parseNeuromagHeader(MetaData& data, QBuffer& neuromagBuffer)
{
    qint32_be iIntToChar;
    char cCharFromInt[sizeof (qint32)];

    //Pad buffer because the fiff file we receive is missing an end tag
    iIntToChar = -1;
    memcpy(cCharFromInt, &iIntToChar, sizeof(qint32));
    neuromagBuffer.write(cCharFromInt);
    neuromagBuffer.write(cCharFromInt);
    neuromagBuffer.write(cCharFromInt);
    neuromagBuffer.write(cCharFromInt);

    neuromagBuffer.reset();

    FIFFLIB::FiffStream::SPtr pStream(new FIFFLIB::FiffStream(&neuromagBuffer));
    pStream->setByteOrder(QDataStream::LittleEndian);

    if(pStream->open()){
        FIFFLIB::FiffInfo FifInfo;
        FIFFLIB::FiffDirNode::SPtr DirNode;
        if(pStream->read_meas_info(pStream->dirtree(), FifInfo, DirNode)){
            data.setFiffinfo(FifInfo);
        }
    }
}

//=============================================================================================================

void FTBUFFERPLUGIN::parseIsotrakHeader(MetaData& data, QBuffer& isotrakBuffer)
{
    isotrakBuffer.reset();

    FIFFLIB::FiffStream stream(&isotrakBuffer);
    FIFFLIB::FiffDigitizerData digData;

    stream.open();
    stream.read_digitizer_data(stream.dirtree(), digData);
    stream.close();

    data.setFiffDigitizerData(digData);
}

//=============================================================================================================
// DEFINE MEMBER METHODS
//=============================================================================================================

FtHeaderParser::FtHeaderParser()
{
    registerMembers();
}

//=============================================================================================================

MetaData FtHeaderParser::parseHeader(QBuffer &buffer)
{
    MetaData data;
    while(!buffer.atEnd()){
        processChunk(data, buffer);
    }

    return data;
}

//=============================================================================================================

void FtHeaderParser::registerMembers()
{
    functionMap[HeaderChunk::FT_CHUNK_NEUROMAG_HEADER] = parseNeuromagHeader;
    functionMap[HeaderChunk::FT_CHUNK_NEUROMAG_ISOTRAK] = parseIsotrakHeader;
}

//=============================================================================================================

void FtHeaderParser::processChunk(MetaData& data , QBuffer& buffer)
{
    auto chunkType = getChunkType(buffer);
    auto function = functionMap.find(chunkType);

    QBuffer headerChunk;
    getSingleHeaderChunk(buffer, headerChunk);

    if (function != functionMap.end()){
        function->second(data, headerChunk);
    }
}

//=============================================================================================================

void FtHeaderParser::getSingleHeaderChunk(QBuffer &source, QBuffer &dest)
{
    qint32 iSize;
    char cSize[sizeof(qint32)];

    //read size of chunk
    source.read(cSize, sizeof(qint32));
    std::memcpy(&iSize, cSize, sizeof(qint32));

    //Read relevant chunk info
    dest.open(QIODevice::ReadWrite);
    dest.write(source.read(iSize));
}

//=============================================================================================================

HeaderChunk FtHeaderParser::getChunkType(QBuffer &buffer)
{
    qint32 iType;
    char cType[sizeof(qint32)];

    buffer.read(cType, sizeof(qint32));
    std::memcpy(&iType, cType, sizeof(qint32));

    std::cout << "Read header of type" << iType << "\n";
    return static_cast<HeaderChunk>(iType);
}

<commit_msg>change using namespace.<commit_after>//=============================================================================================================
/**
 * @file     ftheaderparser.cpp
 * @author   Gabriel Motta <gbmotta@mgh.harvard.edu>
 *           Juan Garcia-Prieto <juangpc@gmail.com>;
 * @since    0.1.9
 * @date     July, 2021
 *
 * @section  LICENSE
 *
 * Copyright (C) 2020, Gabriel Motta, Juan Garcia-Prieto. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that
 * the following conditions are met:
 *     * Redistributions of source code must retain the above copyright notice, this list of conditions and the
 *       following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
 *       the following disclaimer in the documentation and/or other materials provided with the distribution.
 *     * Neither the name of MNE-CPP authors nor the names of its contributors may be used
 *       to endorse or promote products derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 *
 * @brief    Contains the definition of the FtHeaderParser class.
 *
 */

//=============================================================================================================
// INCLUDES
//=============================================================================================================

#include "ftheaderparser.h"

//=============================================================================================================
// QT INCLUDES
//=============================================================================================================

#include <QtEndian>

//=============================================================================================================
// USED NAMESPACES
//=============================================================================================================

using FTBUFFERPLUGIN::FtHeaderParser;
using FTBUFFERPLUGIN::MetaData;

//=============================================================================================================
// DEFINE FREE FUNCTIONS
//=============================================================================================================

void FTBUFFERPLUGIN::parseNeuromagHeader(MetaData& data, QBuffer& neuromagBuffer)
{
    qint32_be iIntToChar;
    char cCharFromInt[sizeof (qint32)];

    //Pad buffer because the fiff file we receive is missing an end tag
    iIntToChar = -1;
    memcpy(cCharFromInt, &iIntToChar, sizeof(qint32));
    neuromagBuffer.write(cCharFromInt);
    neuromagBuffer.write(cCharFromInt);
    neuromagBuffer.write(cCharFromInt);
    neuromagBuffer.write(cCharFromInt);

    neuromagBuffer.reset();

    FIFFLIB::FiffStream::SPtr pStream(new FIFFLIB::FiffStream(&neuromagBuffer));
    pStream->setByteOrder(QDataStream::LittleEndian);

    if(pStream->open()){
        FIFFLIB::FiffInfo FifInfo;
        FIFFLIB::FiffDirNode::SPtr DirNode;
        if(pStream->read_meas_info(pStream->dirtree(), FifInfo, DirNode)){
            data.setFiffinfo(FifInfo);
        }
    }
}

//=============================================================================================================

void FTBUFFERPLUGIN::parseIsotrakHeader(MetaData& data, QBuffer& isotrakBuffer)
{
    isotrakBuffer.reset();

    FIFFLIB::FiffStream stream(&isotrakBuffer);
    FIFFLIB::FiffDigitizerData digData;

    stream.open();
    stream.read_digitizer_data(stream.dirtree(), digData);
    stream.close();

    data.setFiffDigitizerData(digData);
}

//=============================================================================================================
// DEFINE MEMBER METHODS
//=============================================================================================================

FtHeaderParser::FtHeaderParser()
{
    registerMembers();
}

//=============================================================================================================

MetaData FtHeaderParser::parseHeader(QBuffer &buffer)
{
    MetaData data;
    while(!buffer.atEnd()){
        processChunk(data, buffer);
    }

    return data;
}

//=============================================================================================================

void FtHeaderParser::registerMembers()
{
    functionMap[HeaderChunk::FT_CHUNK_NEUROMAG_HEADER] = parseNeuromagHeader;
    functionMap[HeaderChunk::FT_CHUNK_NEUROMAG_ISOTRAK] = parseIsotrakHeader;
}

//=============================================================================================================

void FtHeaderParser::processChunk(MetaData& data , QBuffer& buffer)
{
    auto chunkType = getChunkType(buffer);
    auto function = functionMap.find(chunkType);

    QBuffer headerChunk;
    getSingleHeaderChunk(buffer, headerChunk);

    if (function != functionMap.end()){
        function->second(data, headerChunk);
    }
}

//=============================================================================================================

void FtHeaderParser::getSingleHeaderChunk(QBuffer &source, QBuffer &dest)
{
    qint32 iSize;
    char cSize[sizeof(qint32)];

    //read size of chunk
    source.read(cSize, sizeof(qint32));
    std::memcpy(&iSize, cSize, sizeof(qint32));

    //Read relevant chunk info
    dest.open(QIODevice::ReadWrite);
    dest.write(source.read(iSize));
}

//=============================================================================================================

HeaderChunk FtHeaderParser::getChunkType(QBuffer &buffer)
{
    qint32 iType;
    char cType[sizeof(qint32)];

    buffer.read(cType, sizeof(qint32));
    std::memcpy(&iType, cType, sizeof(qint32));

    std::cout << "Read header of type" << iType << "\n";
    return static_cast<HeaderChunk>(iType);
}

<|endoftext|>