<commit_before>/*
*
*   Copyright © 2018 Luxon Jean-Pierre
*   https://gumichan01.github.io/
*
*   This library is under the MIT license
*
*   Luxon Jean-Pierre (Gumichan01)
*   luxon.jean.pierre@gmail.com
*
*/

#ifndef UTF8_ITERATOR_HPP_INCLUDED
#define UTF8_ITERATOR_HPP_INCLUDED

/**
*   @file utf8_iterator.hpp
*   @brief This is a UTF-8 string library header
*/

class UTF8string;

/**
*   @class UTF8iterator
*   @brief Iterator on UTF8 string
*
*   This class defines the iterator of UTF-8 string
*/
class UTF8iterator
{
    size_t index = 0;
    UTF8string data;

    char& operator ->();

public:

    /**
    *   @fn explicit UTF8iterator(const UTF8string& u) noexcept
    *   Build an iterator object using a UTF8string object
    *   @param u utf-8 string
    */
    explicit UTF8iterator(const UTF8string& u) noexcept;

    /**
    *   @fn UTF8iterator(const UTF8iterator& it) noexcept
    *   @param it The iterator to copy
    */
    UTF8iterator(const UTF8iterator& it) noexcept;

    /**
    *   @fn UTF8iterator& operator ++() noexcept
    *   Prefix incrementation
    *   @return The same iterator, but it has moved forward
    */
    UTF8iterator& operator ++() noexcept;

    /**
    *   @fn UTF8iterator& operator ++(int) noexcept
    *
    *   Postfix incrementation
    *
    *   @return The same iterator before it has moved forward
    */
    UTF8iterator operator ++(int) noexcept;

    /**
    *   @fn UTF8iterator& operator --() noexcept
    *   Prefix derementation
    *   @return The same iterator, but it has moved backward
    */
    UTF8iterator& operator --() noexcept;

    /**
    *   @fn UTF8iterator operator --(int) noexcept
    *
    *   Postfix decrementation
    *
    *   @return The same iterator before it has moved backward
    */
    UTF8iterator operator --(int) noexcept;

    /**
    *   @fn UTF8iterator& operator =(const UTF8iterator& it) noexcept
    *   Asignement
    *   @param it The iterator that wille be assigned
    *   @return The same iterator as the argument
    */
    UTF8iterator& operator =(const UTF8iterator& it) noexcept;

    /**
    *   @fn bool operator ==(const UTF8iterator& it) const noexcept
    *
    *   Check if the current iterator is pointing to the same position as
    *   the iterator given in argument equals.
    *
    *   @param it The iterator to compare with
    *   @return TRUE if they are pointing to the same position, FALSE otherwise
    */
    bool operator ==(const UTF8iterator& it) const noexcept;

    /**
    *   @fn bool operator !=(const UTF8iterator& it) const noexcept
    *
    *   Check if the current iterator is pointing to a different position
    *   from the iterator given in argument equals.
    *
    *   @param it The iterator to compare with
    *   @return TRUE if they are not pointing to the same position,
    *           FALSE otherwise
    */
    bool operator !=(const UTF8iterator& it) const noexcept;

    /**
    *   @fn UTF8iterator operator +(const size_t n) const noexcept
    *
    *   Returns an iterator which has been moved n positions forward
    *
    *   @param n the number of step to move forward
    *   @return The same iterator that moved forward
    */
    UTF8iterator operator +(const size_t n) const noexcept;

    /**
    *   @fn UTF8iterator operator -(const size_t n) const noexcept
    *
    *   Returns an iterator which has been moved n positions backward
    *
    *   @param n the number of steps to move backward
    *   @return The same iterator that moved backward
    */
    UTF8iterator operator -(const size_t n) const noexcept;

    /**
    *   @fn const std::string operator *() const
    *
    *   Dereferences the pointer returning the codepoint
    *   pointed by the iterator at its current potision
    *
    *   @return The codepoint
    *   @note This function will throw an *std::out_of_range* exception
    *         if the iterator does not point to a codepoint
    */
    const std::string operator *() const;

    ~UTF8iterator() = default;
};

#endif // UTF8_ITERATOR_HPP_INCLUDED
<commit_msg>utf8iterator: remove the defeult constructor<commit_after>/*
*
*   Copyright © 2018 Luxon Jean-Pierre
*   https://gumichan01.github.io/
*
*   This library is under the MIT license
*
*   Luxon Jean-Pierre (Gumichan01)
*   luxon.jean.pierre@gmail.com
*
*/

#ifndef UTF8_ITERATOR_HPP_INCLUDED
#define UTF8_ITERATOR_HPP_INCLUDED

/**
*   @file utf8_iterator.hpp
*   @brief This is a UTF-8 string library header
*/

class UTF8string;

/**
*   @class UTF8iterator
*   @brief Iterator on UTF8 string
*
*   This class defines the iterator of UTF-8 string
*/
class UTF8iterator
{
    size_t index = 0;
    UTF8string data;

    char& operator ->();

public:

    UTF8iterator() = delete;

    /**
    *   @fn explicit UTF8iterator(const UTF8string& u) noexcept
    *   Build an iterator object using a UTF8string object
    *   @param u utf-8 string
    */
    explicit UTF8iterator(const UTF8string& u) noexcept;

    /**
    *   @fn UTF8iterator(const UTF8iterator& it) noexcept
    *   @param it The iterator to copy
    */
    UTF8iterator(const UTF8iterator& it) noexcept;

    /**
    *   @fn UTF8iterator& operator ++() noexcept
    *   Prefix incrementation
    *   @return The same iterator, but it has moved forward
    */
    UTF8iterator& operator ++() noexcept;

    /**
    *   @fn UTF8iterator& operator ++(int) noexcept
    *
    *   Postfix incrementation
    *
    *   @return The same iterator before it has moved forward
    */
    UTF8iterator operator ++(int) noexcept;

    /**
    *   @fn UTF8iterator& operator --() noexcept
    *   Prefix derementation
    *   @return The same iterator, but it has moved backward
    */
    UTF8iterator& operator --() noexcept;

    /**
    *   @fn UTF8iterator operator --(int) noexcept
    *
    *   Postfix decrementation
    *
    *   @return The same iterator before it has moved backward
    */
    UTF8iterator operator --(int) noexcept;

    /**
    *   @fn UTF8iterator& operator =(const UTF8iterator& it) noexcept
    *   Asignement
    *   @param it The iterator that wille be assigned
    *   @return The same iterator as the argument
    */
    UTF8iterator& operator =(const UTF8iterator& it) noexcept;

    /**
    *   @fn bool operator ==(const UTF8iterator& it) const noexcept
    *
    *   Check if the current iterator is pointing to the same position as
    *   the iterator given in argument equals.
    *
    *   @param it The iterator to compare with
    *   @return TRUE if they are pointing to the same position, FALSE otherwise
    */
    bool operator ==(const UTF8iterator& it) const noexcept;

    /**
    *   @fn bool operator !=(const UTF8iterator& it) const noexcept
    *
    *   Check if the current iterator is pointing to a different position
    *   from the iterator given in argument equals.
    *
    *   @param it The iterator to compare with
    *   @return TRUE if they are not pointing to the same position,
    *           FALSE otherwise
    */
    bool operator !=(const UTF8iterator& it) const noexcept;

    /**
    *   @fn UTF8iterator operator +(const size_t n) const noexcept
    *
    *   Returns an iterator which has been moved n positions forward
    *
    *   @param n the number of step to move forward
    *   @return The same iterator that moved forward
    */
    UTF8iterator operator +(const size_t n) const noexcept;

    /**
    *   @fn UTF8iterator operator -(const size_t n) const noexcept
    *
    *   Returns an iterator which has been moved n positions backward
    *
    *   @param n the number of steps to move backward
    *   @return The same iterator that moved backward
    */
    UTF8iterator operator -(const size_t n) const noexcept;

    /**
    *   @fn const std::string operator *() const
    *
    *   Dereferences the pointer returning the codepoint
    *   pointed by the iterator at its current potision
    *
    *   @return The codepoint
    *   @note This function will throw an *std::out_of_range* exception
    *         if the iterator does not point to a codepoint
    */
    const std::string operator *() const;

    ~UTF8iterator() = default;
};

#endif // UTF8_ITERATOR_HPP_INCLUDED
<|endoftext|>


<commit_before>/*
What is our "Hello world!" app?

An agent orbits around the origin emitting the audio line input. The camera
view can be switched between a freely navigable keyboard/mouse controlled mode
and a sphere follow mode.

Requirements:
2 channels of spatial sound
2 windows, one front view, one back view
stereographic rendering
*/

#include "allocore/al_Allocore.hpp"
#include "al_NavControl.hpp"
using namespace al;

struct Agent : public SoundSource, public gfx::Drawable{

	Agent()
	: oscPhase(0)
	{}

	virtual ~Agent(){}

	virtual void onProcess(AudioIOData& io){
		while(io()){
			//float s = io.in(0);
			//float s = rnd::uniform(); // make noise, just to hear something
			float s = sin(oscPhase * M_2PI);
			//float s = phase * 2 - 1;
			oscPhase += 440./io.framesPerSecond();
			if(oscPhase >= 1) oscPhase -= 1;
			writeSample(s*0.2);
		}
	}

	virtual void onUpdateNav(){
		smooth(0.9);
		//if((phase+=0.01) >= M_2PI) phase -= M_2PI;
		//pos(cos(phase), sin(phase), 0);
		//pos(0,0,0);

		spin(0.3, 0.011, 0.417);
		//moveF(0.01);
		step();
	}

	virtual void onDraw(gfx::Graphics& g){

		g.pushMatrix();
		g.multMatrix(matrix());

		g.begin(gfx::TRIANGLES);
			float ds = 0.5;
			g.vertex(    0, 0, ds*2);
			g.vertex( ds/2, 0,-ds);
			g.vertex(-ds/2, 0,-ds);

			g.color(1,1,1);
			g.color(1,1,0);
			g.color(1,0,1);
		g.end();

		g.popMatrix();
	}

	double oscPhase;
};

#define AUDIO_BLOCK_SIZE 256
AudioScene scene(3, 1, AUDIO_BLOCK_SIZE);
Listener * listener;
Nav navMaster(Vec3d(0,0,-4), 0.95);
std::vector<Agent> agents(1);
gfx::Stereographic stereo;

void audioCB(AudioIOData& io){
	int numFrames = io.framesPerBuffer();

	for(unsigned i=0; i<agents.size(); ++i){
		io.frame(0);
		agents[i].onUpdateNav();
		agents[i].onProcess(io);
	}

	navMaster.step(0.5);

	scene.encode(numFrames, io.framesPerSecond());
	scene.render(&io.out(0,0), numFrames);

	//printf("%g\n", io.out(0,0));
}

struct MyWindow : public Window, public gfx::Drawable{

	MyWindow(): gl(new gfx::GraphicsBackendOpenGL){}

	bool onFrame(){

		Pose pose(navMaster * transform);

		listener->pos(pose.pos());

		gfx::Viewport vp(dimensions().w, dimensions().h);
		stereo.draw(gl, cam, pose, vp, *this);

		return true;
	}

	virtual void onDraw(gfx::Graphics& g){

		for(unsigned i=0; i<agents.size(); ++i){
			agents[i].onDraw(g);
		}
	}

	gfx::Graphics gl;
	Pose transform;
	Camera cam;
};

int main (int argc, char * argv[]){

	listener = &scene.createListener(2);

	listener->speakerPos(0,0,-90);
	listener->speakerPos(1,1, 90);
//	listener->speakerPos(0,0,-45);
//	listener->speakerPos(1,1, 45);

	for(unsigned i=0; i<agents.size(); ++i) scene.addSource(agents[i]);

	MyWindow windows[2];

	for(int i=0; i<2; ++i){
		windows[i].add(new StandardWindowKeyControls);
		windows[i].add(new NavInputControl(&navMaster));
		windows[i].create(Window::Dim(600,480,i*650), "Hello Virtual World!");
		windows[i].transform.quat(Quatd::fromAxisAngle(i*180, 0, 1, 0));
	}

	AudioIO audioIO(AUDIO_BLOCK_SIZE, 44100, audioCB, 0, 2, 1);
	audioIO.start();

	MainLoop::start();
	return 0;
}
<commit_msg>updated virtualworld<commit_after>/*
What is our "Hello world!" app?

An agent orbits around the origin emitting the audio line input. The camera
view can be switched between a freely navigable keyboard/mouse controlled mode
and a sphere follow mode.

Requirements:
2 channels of spatial sound
2 windows, one front view, one back view
stereographic rendering
*/

#include "allocore/al_Allocore.hpp"
#include "al_NavControl.hpp"
using namespace al;

struct Agent : public SoundSource, public gfx::Drawable{

	Agent()
	: oscPhase(0)
	{}

	virtual ~Agent(){}

	virtual void onProcess(AudioIOData& io){
		while(io()){
			//float s = io.in(0);
			//float s = rnd::uniform(); // make noise, just to hear something
			float s = sin(oscPhase * M_2PI);
			//float s = phase * 2 - 1;
			oscPhase += 440./io.framesPerSecond();
			if(oscPhase >= 1) oscPhase -= 1;
			writeSample(s*1);
		}
	}

	virtual void onUpdateNav(){
		smooth(0.9);
		//if((phase+=0.01) >= M_2PI) phase -= M_2PI;
		//pos(cos(phase), sin(phase), 0);
		//pos(0,0,0);

		spin(0.3, 0.011, 0.417);
		//moveF(0.01);
		step();
	}

	virtual void onDraw(gfx::Graphics& g){

		g.pushMatrix();
		g.multMatrix(matrix());

		g.begin(gfx::TRIANGLES);
			float ds = 0.5;
			g.vertex(    0, 0, ds*2);
			g.vertex( ds/2, 0,-ds);
			g.vertex(-ds/2, 0,-ds);

			g.color(1,1,1);
			g.color(1,1,0);
			g.color(1,0,1);
		g.end();

		g.popMatrix();
	}

	double oscPhase;
};

#define AUDIO_BLOCK_SIZE 256
AudioScene scene(3, 1, AUDIO_BLOCK_SIZE);
Listener * listener;
Nav navMaster(Vec3d(0,0,-4), 0.95);
std::vector<Agent> agents(1);
gfx::Stereographic stereo;

void audioCB(AudioIOData& io){
	int numFrames = io.framesPerBuffer();

	for(unsigned i=0; i<agents.size(); ++i){
		io.frame(0);
		agents[i].onUpdateNav();
		agents[i].onProcess(io);
	}

	navMaster.step(0.5);
	listener->pos(navMaster.pos());

	scene.encode(numFrames, io.framesPerSecond());
	scene.render(&io.out(0,0), numFrames);

	//printf("%g\n", io.out(0,0));
}

struct MyWindow : public Window, public gfx::Drawable{

	MyWindow(): gl(new gfx::GraphicsBackendOpenGL){}

	bool onFrame(){

		Pose pose(navMaster * transform);

		//listener->pos(pose.pos());

		gfx::Viewport vp(dimensions().w, dimensions().h);
		stereo.draw(gl, cam, pose, vp, *this);

		return true;
	}

	bool onKeyDown(const Keyboard& k) {

		if (k.key() == Key::Tab) {
			stereo.stereo(!stereo.stereo());
		}

		return true;
	}

	virtual void onDraw(gfx::Graphics& g){

		for(unsigned i=0; i<agents.size(); ++i){
			agents[i].onDraw(g);
		}
	}

	gfx::Graphics gl;
	Pose transform;
	Camera cam;
};

int main (int argc, char * argv[]){

	listener = &scene.createListener(2);

	listener->speakerPos(0,0,-90);
	listener->speakerPos(1,1, 90);
//	listener->speakerPos(0,0,-45);
//	listener->speakerPos(1,1, 45);

	for(unsigned i=0; i<agents.size(); ++i) scene.addSource(agents[i]);

	MyWindow windows[2];

	for(int i=0; i<2; ++i){
		windows[i].add(new StandardWindowKeyControls);
		windows[i].add(new NavInputControl(&navMaster));
		windows[i].create(Window::Dim(600,480,i*650), "Hello Virtual World!");
		windows[i].transform.quat(Quatd::fromAxisAngle(i*180, 0, 1, 0));
	}

	AudioIO audioIO(AUDIO_BLOCK_SIZE, 44100, audioCB, 0, 2, 1);
	audioIO.start();

	MainLoop::start();
	return 0;
}
<|endoftext|>


<commit_before>// Copyright 2015-2020 Elviss Strazdins. All rights reserved.

#ifndef OUZEL_GRAPHICS_OBJECT_HPP
#define OUZEL_GRAPHICS_OBJECT_HPP

#include <memory>
#include "Material.hpp"

namespace ouzel::graphics
{
    class Object final
    {
    public:
        Object() = default;

        Object(const Object&) = delete;
        Object& operator=(const Object&) = delete;

        Object(Object&&) = delete;
        Object& operator=(Object&&) = delete;

        const Material* material = nullptr;
    };
}

#endif // OUZEL_GRAPHICS_OBJECT_HPP
<commit_msg>Add buffers and transform to Object<commit_after>// Copyright 2015-2020 Elviss Strazdins. All rights reserved.

#ifndef OUZEL_GRAPHICS_OBJECT_HPP
#define OUZEL_GRAPHICS_OBJECT_HPP

#include <memory>
#include "Buffer.hpp"
#include "Material.hpp"
#include "../math/Matrix.hpp"

namespace ouzel::graphics
{
    class Object final
    {
    public:
        Object() = default;

        Object(const Object&) = delete;
        Object& operator=(const Object&) = delete;

        Object(Object&&) = delete;
        Object& operator=(Object&&) = delete;

        const Buffer* indexBuffer = nullptr;
        const Buffer* vertexBuffer = nullptr;
        const Material* material = nullptr;
        Matrix4F transform;
    };
}

#endif // OUZEL_GRAPHICS_OBJECT_HPP
<|endoftext|>


<commit_before><commit_msg>Set TOFChi2 to -1 in Run3 converter<commit_after><|endoftext|>


<commit_before>#include "stft_client_storage.h"

#include <cinder/CinderMath.h>

namespace cieq {
namespace stft {

ClientStorage::ClientStorage(const Client::Format& fmt)
	: mFftSize(fmt.getFftSize())
	, mWindowType(fmt.getWindowType())
	, mWindowSize(fmt.getWindowSize())
	, mChannelSize(fmt.getChannelSize())
	, mSmoothingFactor(0.5f)
{
	if (mFftSize < mWindowSize)
		mFftSize = mWindowSize;
	if (!ci::isPowerOf2(mFftSize))
		mFftSize = ci::nextPowerOf2(static_cast<uint32_t>(mFftSize));

	mFft = std::make_unique<ci::audio::dsp::Fft>(mFftSize);
	mFftBuffer = ci::audio::Buffer(mFftSize, mChannelSize);
	mCopiedBuffer = ci::audio::Buffer(mFftSize, mChannelSize);
	mBufferSpectral = ci::audio::BufferSpectral(mFftSize);
	mMagSpectrum.resize(mFftSize / 2);

	if (!mWindowSize)
		mWindowSize = mFftSize;
	else if (!ci::isPowerOf2(mWindowSize))
		mWindowSize = ci::nextPowerOf2(static_cast<uint32_t>(mWindowSize));

	mWindowingTable = ci::audio::makeAlignedArray<float>(mWindowSize);
	generateWindow(mWindowType, mWindowingTable.get(), mWindowSize);
}

}} //!cieq::stft<commit_msg>Some housekeeping here<commit_after>#include "stft_client_storage.h"

#include <cinder/CinderMath.h>

namespace cieq {
namespace stft {

ClientStorage::ClientStorage(const Client::Format& fmt)
	: mFftSize(fmt.getFftSize())
	, mWindowType(fmt.getWindowType())
	, mWindowSize(fmt.getWindowSize())
	, mChannelSize(fmt.getChannelSize())
	, mSmoothingFactor(0.5f)
{
	// There's no point of having FFT size of less than a window size!
	if (mFftSize < mWindowSize)
		mFftSize = mWindowSize;

	// This makes sure that we are zero padding
	mFftSize = ci::nextPowerOf2(static_cast<uint32_t>(mFftSize));

	// The actual FFT processor instance
	mFft = std::make_unique<ci::audio::dsp::Fft>(mFftSize);

	// The FFT buffer, the one that will be filled AFTER FFT is performed on data
	mFftBuffer = ci::audio::Buffer(mFftSize, mChannelSize);

	// Copied buffer. the one that will be filled by raw audio chunks BEFORE FFT
	mCopiedBuffer = ci::audio::Buffer(mFftSize, mChannelSize);

	// Intermediate buffer passed to FFT processor
	mBufferSpectral = ci::audio::BufferSpectral(mFftSize);

	// The floating point array that contains all the FFT data, will be passed to renderer
	mMagSpectrum.resize(mFftSize / 2);

	// Window table.
	mWindowingTable = ci::audio::makeAlignedArray<float>(mWindowSize);
	generateWindow(mWindowType, mWindowingTable.get(), mWindowSize);
}

}} //!cieq::stft<|endoftext|>


<commit_before><commit_msg>Zastosowanie pętli c++11<commit_after><|endoftext|>


<commit_before>#include "../adapter.hpp"
#include "../values.hpp"

namespace rev {

  value_t::p Vector_Printable_str(value_t::p self) {
    auto v = as<vector_t>(self);
    std::string s = "[";
    if (auto fst = imu::first(v)) {
      s += str(*fst);
      imu::for_each([&](const value_t::p& v) {
          auto str = rev::str(v);
          s += " " + str;
        }, imu::rest(v));
    }
    s += "]";
    return imu::nu<string_t>(s);
  }

  value_t::p Vector_Seqable_seq(value_t::p self) {
    auto v = as<vector_t>(self);
    if (imu::count(v) > 0) {
      return imu::nu<seq_adapter_t<vector_t>>(v);
    }
    return nullptr;
  }

  value_t::p Vector_Collection_conj(value_t::p self, value_t::p o) {
    return imu::conj(as<vector_t>(self), o);
  }

  value_t::p Vector_Associative_contains_key(value_t::p self, value_t::p k) {
    return sym_t::false_;
  }

  value_t::p Vector_Associative_assoc(
    value_t::p self, value_t::p k, value_t::p val) {

    auto v = as<vector_t>(self);
    auto n = as<int_t>(k);
    return imu::assoc(v, n->value, val);
  }

  value_t::p Vector_IIndexed_nth2(value_t::p self, value_t::p n) {
    return as<vector_t>(self)->nth(as<int_t>(n)->value);
  }

  value_t::p Vector_IIndexed_nth3(value_t::p self, value_t::p n, value_t::p d) {
    auto i = as<int_t>(n)->value;
    auto v = as<vector_t>(self);
    if (i >= 0 && i < imu::count(v)) {
      return v->nth(i);
    }
    return d;
  }

  value_t::p Vector_Lookup_lookup2(value_t::p s, value_t::p k) {
    return Vector_IIndexed_nth2(s, k);
  }

  value_t::p Vector_Lookup_lookup3(value_t::p s, value_t::p k, value_t::p d) {
    return Vector_IIndexed_nth3(s, k, d);
  }

  value_t::p VectorSeq_Seqable_seq(value_t::p self) {
    return self;
  }

  value_t::p VectorSeq_Seq_first(value_t::p self) {
    auto seq = as<seq_adapter_t<vector_t>>(self)->seq();
    if (!imu::is_empty(seq)) {
      return seq->first();
    }
    return nullptr;
  }

  value_t::p VectorSeq_Seq_rest(value_t::p self) {
    auto seq = as<seq_adapter_t<vector_t>>(self)->seq();
    if (!imu::is_empty(seq)) {
      if (auto rest = seq->rest()) {
        return imu::nu<seq_adapter_t<vector_t>>(rest);
      }
    }
    return nullptr;
  }

  value_t::p VectorSeq_Next_next(value_t::p self) {
    auto seq = as<seq_adapter_t<vector_t>>(self)->seq();
    if (!imu::is_empty(seq)) {
      if (auto rest = seq->rest()) {
        return imu::nu<seq_adapter_t<vector_t>>(rest);
      }
    }
    return nullptr;
  }

  value_t::p Vector_MapEntry_key(value_t::p self) {
    return as<vector_t>(self)->nth(0);
  }

  value_t::p Vector_MapEntry_val(value_t::p self) {
    return as<vector_t>(self)->nth(1);
  }

  value_t::p Vector_Equiv_equiv(value_t::p self, value_t::p other) {
    equal_to eq;
    return imu::seqs::equiv(imu::seq(as<vector_t>(self)), rt_seq_t::seq(other), eq) ? sym_t::true_ : sym_t::false_;
  }

  struct type_t::impl_t Vector_printable[] = {
    {0, (intptr_t) Vector_Printable_str, 0, 0, 0, 0, 0, 0}
  };

  struct type_t::impl_t Vector_seqable[] = {
    {0, (intptr_t) Vector_Seqable_seq, 0, 0, 0, 0, 0, 0}
  };

  struct type_t::impl_t Vector_coll[] = {
    {0, 0, (intptr_t) Vector_Collection_conj, 0, 0, 0, 0, 0}
  };

  struct type_t::impl_t Vector_associative[] = {
    {0, 0, (intptr_t) Vector_Associative_contains_key, 0, 0, 0, 0, 0},
    {0, 0, 0, (intptr_t) Vector_Associative_assoc, 0, 0, 0, 0}
  };

  struct type_t::impl_t Vector_iindexed[] = {
    {0, 0,
     (intptr_t) Vector_IIndexed_nth2,
     (intptr_t) Vector_IIndexed_nth3,
     0, 0, 0, 0}
  };

  struct type_t::impl_t Vector_lookup[] = {
    {0, 0,
     (intptr_t) Vector_Lookup_lookup2,
     (intptr_t) Vector_Lookup_lookup3,
     0, 0, 0, 0}
  };

  struct type_t::impl_t Vector_mapentry[] = {
    {0, (intptr_t) Vector_MapEntry_key, 0, 0, 0, 0, 0, 0},
    {0, (intptr_t) Vector_MapEntry_val,  0, 0, 0, 0, 0, 0}
  };

  struct type_t::impl_t Vector_equiv[] = {
    {0, 0, (intptr_t) Vector_Equiv_equiv, 0, 0, 0, 0, 0},
  };

  struct type_t::impl_t VectorSeq_seqable[] = {
    {0, (intptr_t) VectorSeq_Seqable_seq, 0, 0, 0, 0, 0, 0}
  };

  struct type_t::impl_t VectorSeq_seq[] = {
    {0, (intptr_t) VectorSeq_Seq_first, 0, 0, 0, 0, 0, 0},
    {0, (intptr_t) VectorSeq_Seq_rest,  0, 0, 0, 0, 0, 0}
  };

  struct type_t::impl_t VectorSeq_next[] = {
    {0, (intptr_t) VectorSeq_Next_next, 0, 0, 0, 0, 0, 0}
  };

  struct type_t::ext_t Vector_methods[] = {
    {protocol_t::str,         Vector_printable},
    {protocol_t::seqable,     Vector_seqable},
    {protocol_t::ivector,     nullptr},
    {protocol_t::coll,        Vector_coll},
    {protocol_t::associative, Vector_associative},
    {protocol_t::indexed,     Vector_iindexed},
    {protocol_t::equiv,       Vector_equiv}
    {protocol_t::lookup,      Vector_lookup},
    {protocol_t::mapentry,    Vector_mapentry}
  };

  struct type_t::ext_t VectorSeq_methods[] = {
    {protocol_t::seqable, VectorSeq_seqable},
    {protocol_t::seq,     VectorSeq_seq},
    {protocol_t::next,    VectorSeq_next}
  };

  static const uint64_t vec_size =
    sizeof(Vector_methods) / sizeof(Vector_methods[0]);

  static const uint64_t seq_size =
    sizeof(VectorSeq_methods) / sizeof(VectorSeq_methods[0]);

  template<>
  type_t value_base_t<vector_tag_t>::prototype(
    "PersistentVector.0", Vector_methods, vec_size);

  template<>
  type_t value_base_t<seq_adapter_t<vector_t>>::prototype(
    "VectorSeq.0", VectorSeq_methods, seq_size);
}
<commit_msg>Add missing ,<commit_after>#include "../adapter.hpp"
#include "../values.hpp"

namespace rev {

  value_t::p Vector_Printable_str(value_t::p self) {
    auto v = as<vector_t>(self);
    std::string s = "[";
    if (auto fst = imu::first(v)) {
      s += str(*fst);
      imu::for_each([&](const value_t::p& v) {
          auto str = rev::str(v);
          s += " " + str;
        }, imu::rest(v));
    }
    s += "]";
    return imu::nu<string_t>(s);
  }

  value_t::p Vector_Seqable_seq(value_t::p self) {
    auto v = as<vector_t>(self);
    if (imu::count(v) > 0) {
      return imu::nu<seq_adapter_t<vector_t>>(v);
    }
    return nullptr;
  }

  value_t::p Vector_Collection_conj(value_t::p self, value_t::p o) {
    return imu::conj(as<vector_t>(self), o);
  }

  value_t::p Vector_Associative_contains_key(value_t::p self, value_t::p k) {
    return sym_t::false_;
  }

  value_t::p Vector_Associative_assoc(
    value_t::p self, value_t::p k, value_t::p val) {

    auto v = as<vector_t>(self);
    auto n = as<int_t>(k);
    return imu::assoc(v, n->value, val);
  }

  value_t::p Vector_IIndexed_nth2(value_t::p self, value_t::p n) {
    return as<vector_t>(self)->nth(as<int_t>(n)->value);
  }

  value_t::p Vector_IIndexed_nth3(value_t::p self, value_t::p n, value_t::p d) {
    auto i = as<int_t>(n)->value;
    auto v = as<vector_t>(self);
    if (i >= 0 && i < imu::count(v)) {
      return v->nth(i);
    }
    return d;
  }

  value_t::p Vector_Lookup_lookup2(value_t::p s, value_t::p k) {
    return Vector_IIndexed_nth2(s, k);
  }

  value_t::p Vector_Lookup_lookup3(value_t::p s, value_t::p k, value_t::p d) {
    return Vector_IIndexed_nth3(s, k, d);
  }

  value_t::p VectorSeq_Seqable_seq(value_t::p self) {
    return self;
  }

  value_t::p VectorSeq_Seq_first(value_t::p self) {
    auto seq = as<seq_adapter_t<vector_t>>(self)->seq();
    if (!imu::is_empty(seq)) {
      return seq->first();
    }
    return nullptr;
  }

  value_t::p VectorSeq_Seq_rest(value_t::p self) {
    auto seq = as<seq_adapter_t<vector_t>>(self)->seq();
    if (!imu::is_empty(seq)) {
      if (auto rest = seq->rest()) {
        return imu::nu<seq_adapter_t<vector_t>>(rest);
      }
    }
    return nullptr;
  }

  value_t::p VectorSeq_Next_next(value_t::p self) {
    auto seq = as<seq_adapter_t<vector_t>>(self)->seq();
    if (!imu::is_empty(seq)) {
      if (auto rest = seq->rest()) {
        return imu::nu<seq_adapter_t<vector_t>>(rest);
      }
    }
    return nullptr;
  }

  value_t::p Vector_MapEntry_key(value_t::p self) {
    return as<vector_t>(self)->nth(0);
  }

  value_t::p Vector_MapEntry_val(value_t::p self) {
    return as<vector_t>(self)->nth(1);
  }

  value_t::p Vector_Equiv_equiv(value_t::p self, value_t::p other) {
    equal_to eq;
    return imu::seqs::equiv(imu::seq(as<vector_t>(self)), rt_seq_t::seq(other), eq) ? sym_t::true_ : sym_t::false_;
  }

  struct type_t::impl_t Vector_printable[] = {
    {0, (intptr_t) Vector_Printable_str, 0, 0, 0, 0, 0, 0}
  };

  struct type_t::impl_t Vector_seqable[] = {
    {0, (intptr_t) Vector_Seqable_seq, 0, 0, 0, 0, 0, 0}
  };

  struct type_t::impl_t Vector_coll[] = {
    {0, 0, (intptr_t) Vector_Collection_conj, 0, 0, 0, 0, 0}
  };

  struct type_t::impl_t Vector_associative[] = {
    {0, 0, (intptr_t) Vector_Associative_contains_key, 0, 0, 0, 0, 0},
    {0, 0, 0, (intptr_t) Vector_Associative_assoc, 0, 0, 0, 0}
  };

  struct type_t::impl_t Vector_iindexed[] = {
    {0, 0,
     (intptr_t) Vector_IIndexed_nth2,
     (intptr_t) Vector_IIndexed_nth3,
     0, 0, 0, 0}
  };

  struct type_t::impl_t Vector_lookup[] = {
    {0, 0,
     (intptr_t) Vector_Lookup_lookup2,
     (intptr_t) Vector_Lookup_lookup3,
     0, 0, 0, 0}
  };

  struct type_t::impl_t Vector_mapentry[] = {
    {0, (intptr_t) Vector_MapEntry_key, 0, 0, 0, 0, 0, 0},
    {0, (intptr_t) Vector_MapEntry_val,  0, 0, 0, 0, 0, 0}
  };

  struct type_t::impl_t Vector_equiv[] = {
    {0, 0, (intptr_t) Vector_Equiv_equiv, 0, 0, 0, 0, 0},
  };

  struct type_t::impl_t VectorSeq_seqable[] = {
    {0, (intptr_t) VectorSeq_Seqable_seq, 0, 0, 0, 0, 0, 0}
  };

  struct type_t::impl_t VectorSeq_seq[] = {
    {0, (intptr_t) VectorSeq_Seq_first, 0, 0, 0, 0, 0, 0},
    {0, (intptr_t) VectorSeq_Seq_rest,  0, 0, 0, 0, 0, 0}
  };

  struct type_t::impl_t VectorSeq_next[] = {
    {0, (intptr_t) VectorSeq_Next_next, 0, 0, 0, 0, 0, 0}
  };

  struct type_t::ext_t Vector_methods[] = {
    {protocol_t::str,         Vector_printable},
    {protocol_t::seqable,     Vector_seqable},
    {protocol_t::ivector,     nullptr},
    {protocol_t::coll,        Vector_coll},
    {protocol_t::associative, Vector_associative},
    {protocol_t::indexed,     Vector_iindexed},
    {protocol_t::equiv,       Vector_equiv},
    {protocol_t::lookup,      Vector_lookup},
    {protocol_t::mapentry,    Vector_mapentry}
  };

  struct type_t::ext_t VectorSeq_methods[] = {
    {protocol_t::seqable, VectorSeq_seqable},
    {protocol_t::seq,     VectorSeq_seq},
    {protocol_t::next,    VectorSeq_next}
  };

  static const uint64_t vec_size =
    sizeof(Vector_methods) / sizeof(Vector_methods[0]);

  static const uint64_t seq_size =
    sizeof(VectorSeq_methods) / sizeof(VectorSeq_methods[0]);

  template<>
  type_t value_base_t<vector_tag_t>::prototype(
    "PersistentVector.0", Vector_methods, vec_size);

  template<>
  type_t value_base_t<seq_adapter_t<vector_t>>::prototype(
    "VectorSeq.0", VectorSeq_methods, seq_size);
}
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////
//
// Copyright 2016 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////

#include "sync/impl/sync_file.hpp"

#include "util/time.hpp"

#include <realm/util/file.hpp>
#include <realm/util/scope_exit.hpp>

#include <iomanip>
#include <sstream>
#include <system_error>
#include <fstream>

#ifdef _WIN32
#include <io.h>
#include <fcntl.h>

inline static int mkstemp(char* _template) { return _open(_mktemp(_template), _O_CREAT | _O_TEMPORARY, _S_IREAD | _S_IWRITE); }
#else
#include <unistd.h>
#endif

using File = realm::util::File;

namespace realm {

namespace {

uint8_t value_of_hex_digit(char hex_digit)
{
    if (hex_digit >= '0' && hex_digit <= '9') {
        return hex_digit - '0';
    } else if (hex_digit >= 'A' && hex_digit <= 'F') {
        return 10 + hex_digit - 'A';
    } else if (hex_digit >= 'a' && hex_digit <= 'f') {
        return 10 + hex_digit - 'a';
    } else {
        throw std::invalid_argument("Cannot get the value of a character that isn't a hex digit.");
    }
}

bool filename_is_reserved(const std::string& filename) {
    return (filename == "." || filename == "..");
}

bool character_is_unreserved(char character)
{
    bool is_capital_letter = (character >= 'A' && character <= 'Z');
    bool is_lowercase_letter = (character >= 'a' && character <= 'z');
    bool is_number = (character >= '0' && character <= '9');
    bool is_allowed_symbol = (character == '-' || character == '_' || character == '.');
    return is_capital_letter || is_lowercase_letter || is_number || is_allowed_symbol;
}

char decoded_char_for(const std::string& percent_encoding, size_t index)
{
    if (index+2 >= percent_encoding.length()) {
        throw std::invalid_argument("Malformed string: not enough characters after '%' before end of string.");
    }
    REALM_ASSERT(percent_encoding[index] == '%');
    return (16*value_of_hex_digit(percent_encoding[index + 1])) + value_of_hex_digit(percent_encoding[index + 2]);
}

} // (anonymous namespace)

namespace util {

std::string make_percent_encoded_string(const std::string& raw_string)
{
    std::string buffer;
    buffer.reserve(raw_string.size());
    for (size_t i=0; i<raw_string.size(); i++) {
        unsigned char character = raw_string[i];
        if (character_is_unreserved(character)) {
            buffer.push_back(character);
        } else {
            buffer.resize(buffer.size() + 3);
            // Format string must resolve to exactly 3 characters.
            sprintf(&buffer.back() - 2, "%%%2X", character);
        }
    }
    return buffer;
}

std::string make_raw_string(const std::string& percent_encoded_string)
{
    std::string buffer;
    size_t input_len = percent_encoded_string.length();
    buffer.reserve(input_len);
    size_t idx = 0;
    while (idx < input_len) {
        char current = percent_encoded_string[idx];
        if (current == '%') {
            // Decode. +3.
            buffer.push_back(decoded_char_for(percent_encoded_string, idx));
            idx += 3;
        } else {
            // No need to decode. +1.
            if (!character_is_unreserved(current)) {
                throw std::invalid_argument("Input string is invalid: contains reserved characters.");
            }
            buffer.push_back(current);
            idx++;
        }
    }
    return buffer;
}

std::string file_path_by_appending_component(const std::string& path, const std::string& component, FilePathType path_type)
{
    // FIXME: Does this have to be changed to accomodate Windows platforms?
    std::string buffer;
    buffer.reserve(2 + path.length() + component.length());
    buffer.append(path);
    std::string terminal = "";
    if (path_type == FilePathType::Directory && component[component.length() - 1] != '/') {
        terminal = "/";
    }
    char path_last = path[path.length() - 1];
    char component_first = component[0];
    if (path_last == '/' && component_first == '/') {
        buffer.append(component.substr(1));
        buffer.append(terminal);
    } else if (path_last == '/' || component_first == '/') {
        buffer.append(component);
        buffer.append(terminal);
    } else {
        buffer.append("/");
        buffer.append(component);
        buffer.append(terminal);
    }
    return buffer;
}

std::string file_path_by_appending_extension(const std::string& path, const std::string& extension)
{
    std::string buffer;
    buffer.reserve(1 + path.length() + extension.length());
    buffer.append(path);
    char path_last = path[path.length() - 1];
    char extension_first = extension[0];
    if (path_last == '.' && extension_first == '.') {
        buffer.append(extension.substr(1));
    } else if (path_last == '.' || extension_first == '.') {
        buffer.append(extension);
    } else {
        buffer.append(".");
        buffer.append(extension);
    }
    return buffer;
}

std::string create_timestamped_template(const std::string& prefix, int wildcard_count)
{
    constexpr int WILDCARD_MAX = 20;
    constexpr int WILDCARD_MIN = 6;
    wildcard_count = std::min(WILDCARD_MAX, std::max(WILDCARD_MIN, wildcard_count));
    std::time_t time = std::time(nullptr);
    std::stringstream stream;
    stream << prefix << "-" << util::put_time(time, "%Y%m%d-%H%M%S") << "-" << std::string(wildcard_count, 'X');
    return stream.str();
}

std::string reserve_unique_file_name(const std::string& path, const std::string& template_string)
{
    REALM_ASSERT_DEBUG(template_string.find("XXXXXX") != std::string::npos);
    std::string path_buffer = file_path_by_appending_component(path, template_string, FilePathType::File);
    int fd = mkstemp(&path_buffer[0]);
    if (fd < 0) {
        int err = errno;
        throw std::system_error(err, std::system_category());
    }
    // Remove the file so we can use the name for our own file.
    close(fd);
    unlink(path_buffer.c_str());
    return path_buffer;
}

} // util

constexpr const char SyncFileManager::c_sync_directory[];
constexpr const char SyncFileManager::c_utility_directory[];
constexpr const char SyncFileManager::c_recovery_directory[];
constexpr const char SyncFileManager::c_metadata_directory[];
constexpr const char SyncFileManager::c_metadata_realm[];
constexpr const char SyncFileManager::c_user_info_file[];

std::string SyncFileManager::get_special_directory(std::string directory_name) const
{
    auto dir_path = file_path_by_appending_component(get_base_sync_directory(),
                                                     directory_name,
                                                     util::FilePathType::Directory);
    util::try_make_dir(dir_path);
    return dir_path;
}

std::string SyncFileManager::get_base_sync_directory() const
{
    auto sync_path = file_path_by_appending_component(m_base_path,
                                                      c_sync_directory,
                                                      util::FilePathType::Directory);
    util::try_make_dir(sync_path);
    return sync_path;
}

std::string SyncFileManager::user_directory(const std::string& local_identity,
                                            util::Optional<SyncUserIdentifier> user_info) const
{
    REALM_ASSERT(local_identity.length() > 0);
    std::string escaped = util::make_percent_encoded_string(local_identity);
    if (filename_is_reserved(escaped))
        throw std::invalid_argument("A user can't have an identifier reserved by the filesystem.");

    auto user_path = file_path_by_appending_component(get_base_sync_directory(),
                                                      escaped,
                                                      util::FilePathType::Directory);
    bool dir_created = util::try_make_dir(user_path);
    if (dir_created && user_info) {
        // Add a text file in the user directory containing the user identity, for backup purposes.
        // Only do this the first time the directory is created.
        auto info_path = util::file_path_by_appending_component(user_path, c_user_info_file);
        std::ofstream info_file;
        info_file.open(info_path.c_str());
        if (info_file.is_open()) {
            info_file << user_info->user_id << "\n" << user_info->auth_server_url << "\n";
            info_file.close();
        }
    }
    return user_path;
}

void SyncFileManager::remove_user_directory(const std::string& local_identity) const
{
    REALM_ASSERT(local_identity.length() > 0);
    const auto& escaped = util::make_percent_encoded_string(local_identity);
    if (filename_is_reserved(escaped))
        throw std::invalid_argument("A user can't have an identifier reserved by the filesystem.");

    auto user_path = file_path_by_appending_component(get_base_sync_directory(),
                                                      escaped,
                                                      util::FilePathType::Directory);
    util::try_remove_dir_recursive(user_path);
}

bool SyncFileManager::try_rename_user_directory(const std::string& old_name, const std::string& new_name) const
{
    REALM_ASSERT_DEBUG(old_name.length() > 0 && new_name.length() > 0);
    const auto& old_name_escaped = util::make_percent_encoded_string(old_name);
    const auto& new_name_escaped = util::make_percent_encoded_string(new_name);
    const std::string& base = get_base_sync_directory();
    if (filename_is_reserved(old_name_escaped) || filename_is_reserved(new_name_escaped))
        throw std::invalid_argument("A user directory can't be renamed using a reserved identifier.");

    const auto& old_path = file_path_by_appending_component(base, old_name_escaped, util::FilePathType::Directory);
    const auto& new_path = file_path_by_appending_component(base, new_name_escaped, util::FilePathType::Directory);

    try {
        File::move(old_path, new_path);
    } catch (File::NotFound const&) {
        return false;
    }
    return true;
}

bool SyncFileManager::remove_realm(const std::string& absolute_path) const
{
    REALM_ASSERT(absolute_path.length() > 0);
    bool success = true;
    // Remove the Realm file (e.g. "example.realm").
    success = File::try_remove(absolute_path);
    // Remove the lock file (e.g. "example.realm.lock").
    auto lock_path = util::file_path_by_appending_extension(absolute_path, "lock");
    success = File::try_remove(lock_path);
    // Remove the management directory (e.g. "example.realm.management").
    auto management_path = util::file_path_by_appending_extension(absolute_path, "management");
    try {
        util::try_remove_dir_recursive(management_path);
    }
    catch (File::AccessError const&) {
        success = false;
    }
    return success;
}

bool SyncFileManager::copy_realm_file(const std::string& old_path, const std::string& new_path) const
{
    REALM_ASSERT(old_path.length() > 0);
    try {
        if (File::exists(new_path)) {
            return false;
        }
        File::copy(old_path, new_path);
    }
    catch (File::NotFound const&) {
        return false;
    }
    catch (File::AccessError const&) {
        return false;
    }
    return true;
}

bool SyncFileManager::remove_realm(const std::string& local_identity, const std::string& raw_realm_path) const
{
    REALM_ASSERT(local_identity.length() > 0);
    REALM_ASSERT(raw_realm_path.length() > 0);
    if (filename_is_reserved(local_identity) || filename_is_reserved(raw_realm_path))
        throw std::invalid_argument("A user or Realm can't have an identifier reserved by the filesystem.");

    auto escaped = util::make_percent_encoded_string(raw_realm_path);
    auto realm_path = util::file_path_by_appending_component(user_directory(local_identity), escaped);
    return remove_realm(realm_path);
}

std::string SyncFileManager::path(const std::string& local_identity, const std::string& raw_realm_path,
                                  util::Optional<SyncUserIdentifier> user_info) const
{
    REALM_ASSERT(local_identity.length() > 0);
    REALM_ASSERT(raw_realm_path.length() > 0);
    if (filename_is_reserved(local_identity) || filename_is_reserved(raw_realm_path))
        throw std::invalid_argument("A user or Realm can't have an identifier reserved by the filesystem.");

    auto escaped = util::make_percent_encoded_string(raw_realm_path);
    auto realm_path = util::file_path_by_appending_component(user_directory(local_identity, user_info), escaped);
    return realm_path;
}

std::string SyncFileManager::metadata_path() const
{
    auto dir_path = file_path_by_appending_component(get_utility_directory(),
                                                     c_metadata_directory,
                                                     util::FilePathType::Directory);
    util::try_make_dir(dir_path);
    return util::file_path_by_appending_component(dir_path, c_metadata_realm);
}

bool SyncFileManager::remove_metadata_realm() const
{
    auto dir_path = file_path_by_appending_component(get_utility_directory(),
                                                     c_metadata_directory,
                                                     util::FilePathType::Directory);
    try {
        util::try_remove_dir_recursive(dir_path);
        return true;
    }
    catch (File::AccessError const&) {
        return false;
    }
}

} // realm
<commit_msg>Don't use POSIX on Windows (#619)<commit_after>////////////////////////////////////////////////////////////////////////////
//
// Copyright 2016 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////

#include "sync/impl/sync_file.hpp"

#include "util/time.hpp"

#include <realm/util/file.hpp>
#include <realm/util/scope_exit.hpp>

#include <iomanip>
#include <sstream>
#include <system_error>
#include <fstream>

#ifdef _WIN32
#include <io.h>
#include <fcntl.h>

inline static int mkstemp(char* _template) { return _open(_mktemp(_template), _O_CREAT | _O_TEMPORARY, _S_IREAD | _S_IWRITE); }
#else
#include <unistd.h>
#endif

using File = realm::util::File;

namespace realm {

namespace {

uint8_t value_of_hex_digit(char hex_digit)
{
    if (hex_digit >= '0' && hex_digit <= '9') {
        return hex_digit - '0';
    } else if (hex_digit >= 'A' && hex_digit <= 'F') {
        return 10 + hex_digit - 'A';
    } else if (hex_digit >= 'a' && hex_digit <= 'f') {
        return 10 + hex_digit - 'a';
    } else {
        throw std::invalid_argument("Cannot get the value of a character that isn't a hex digit.");
    }
}

bool filename_is_reserved(const std::string& filename) {
    return (filename == "." || filename == "..");
}

bool character_is_unreserved(char character)
{
    bool is_capital_letter = (character >= 'A' && character <= 'Z');
    bool is_lowercase_letter = (character >= 'a' && character <= 'z');
    bool is_number = (character >= '0' && character <= '9');
    bool is_allowed_symbol = (character == '-' || character == '_' || character == '.');
    return is_capital_letter || is_lowercase_letter || is_number || is_allowed_symbol;
}

char decoded_char_for(const std::string& percent_encoding, size_t index)
{
    if (index+2 >= percent_encoding.length()) {
        throw std::invalid_argument("Malformed string: not enough characters after '%' before end of string.");
    }
    REALM_ASSERT(percent_encoding[index] == '%');
    return (16*value_of_hex_digit(percent_encoding[index + 1])) + value_of_hex_digit(percent_encoding[index + 2]);
}

} // (anonymous namespace)

namespace util {

std::string make_percent_encoded_string(const std::string& raw_string)
{
    std::string buffer;
    buffer.reserve(raw_string.size());
    for (size_t i=0; i<raw_string.size(); i++) {
        unsigned char character = raw_string[i];
        if (character_is_unreserved(character)) {
            buffer.push_back(character);
        } else {
            buffer.resize(buffer.size() + 3);
            // Format string must resolve to exactly 3 characters.
            sprintf(&buffer.back() - 2, "%%%2X", character);
        }
    }
    return buffer;
}

std::string make_raw_string(const std::string& percent_encoded_string)
{
    std::string buffer;
    size_t input_len = percent_encoded_string.length();
    buffer.reserve(input_len);
    size_t idx = 0;
    while (idx < input_len) {
        char current = percent_encoded_string[idx];
        if (current == '%') {
            // Decode. +3.
            buffer.push_back(decoded_char_for(percent_encoded_string, idx));
            idx += 3;
        } else {
            // No need to decode. +1.
            if (!character_is_unreserved(current)) {
                throw std::invalid_argument("Input string is invalid: contains reserved characters.");
            }
            buffer.push_back(current);
            idx++;
        }
    }
    return buffer;
}

std::string file_path_by_appending_component(const std::string& path, const std::string& component, FilePathType path_type)
{
    // FIXME: Does this have to be changed to accomodate Windows platforms?
    std::string buffer;
    buffer.reserve(2 + path.length() + component.length());
    buffer.append(path);
    std::string terminal = "";
    if (path_type == FilePathType::Directory && component[component.length() - 1] != '/') {
        terminal = "/";
    }
    char path_last = path[path.length() - 1];
    char component_first = component[0];
    if (path_last == '/' && component_first == '/') {
        buffer.append(component.substr(1));
        buffer.append(terminal);
    } else if (path_last == '/' || component_first == '/') {
        buffer.append(component);
        buffer.append(terminal);
    } else {
        buffer.append("/");
        buffer.append(component);
        buffer.append(terminal);
    }
    return buffer;
}

std::string file_path_by_appending_extension(const std::string& path, const std::string& extension)
{
    std::string buffer;
    buffer.reserve(1 + path.length() + extension.length());
    buffer.append(path);
    char path_last = path[path.length() - 1];
    char extension_first = extension[0];
    if (path_last == '.' && extension_first == '.') {
        buffer.append(extension.substr(1));
    } else if (path_last == '.' || extension_first == '.') {
        buffer.append(extension);
    } else {
        buffer.append(".");
        buffer.append(extension);
    }
    return buffer;
}

std::string create_timestamped_template(const std::string& prefix, int wildcard_count)
{
    constexpr int WILDCARD_MAX = 20;
    constexpr int WILDCARD_MIN = 6;
    wildcard_count = std::min(WILDCARD_MAX, std::max(WILDCARD_MIN, wildcard_count));
    std::time_t time = std::time(nullptr);
    std::stringstream stream;
    stream << prefix << "-" << util::put_time(time, "%Y%m%d-%H%M%S") << "-" << std::string(wildcard_count, 'X');
    return stream.str();
}

std::string reserve_unique_file_name(const std::string& path, const std::string& template_string)
{
    REALM_ASSERT_DEBUG(template_string.find("XXXXXX") != std::string::npos);
    std::string path_buffer = file_path_by_appending_component(path, template_string, FilePathType::File);
    int fd = mkstemp(&path_buffer[0]);
    if (fd < 0) {
        int err = errno;
        throw std::system_error(err, std::system_category());
    }
    // Remove the file so we can use the name for our own file.
#ifdef _WIN32
    _close(fd);
    _unlink(path_buffer.c_str());
#else
    close(fd);
    unlink(path_buffer.c_str());
#endif
    return path_buffer;
}

} // util

constexpr const char SyncFileManager::c_sync_directory[];
constexpr const char SyncFileManager::c_utility_directory[];
constexpr const char SyncFileManager::c_recovery_directory[];
constexpr const char SyncFileManager::c_metadata_directory[];
constexpr const char SyncFileManager::c_metadata_realm[];
constexpr const char SyncFileManager::c_user_info_file[];

std::string SyncFileManager::get_special_directory(std::string directory_name) const
{
    auto dir_path = file_path_by_appending_component(get_base_sync_directory(),
                                                     directory_name,
                                                     util::FilePathType::Directory);
    util::try_make_dir(dir_path);
    return dir_path;
}

std::string SyncFileManager::get_base_sync_directory() const
{
    auto sync_path = file_path_by_appending_component(m_base_path,
                                                      c_sync_directory,
                                                      util::FilePathType::Directory);
    util::try_make_dir(sync_path);
    return sync_path;
}

std::string SyncFileManager::user_directory(const std::string& local_identity,
                                            util::Optional<SyncUserIdentifier> user_info) const
{
    REALM_ASSERT(local_identity.length() > 0);
    std::string escaped = util::make_percent_encoded_string(local_identity);
    if (filename_is_reserved(escaped))
        throw std::invalid_argument("A user can't have an identifier reserved by the filesystem.");

    auto user_path = file_path_by_appending_component(get_base_sync_directory(),
                                                      escaped,
                                                      util::FilePathType::Directory);
    bool dir_created = util::try_make_dir(user_path);
    if (dir_created && user_info) {
        // Add a text file in the user directory containing the user identity, for backup purposes.
        // Only do this the first time the directory is created.
        auto info_path = util::file_path_by_appending_component(user_path, c_user_info_file);
        std::ofstream info_file;
        info_file.open(info_path.c_str());
        if (info_file.is_open()) {
            info_file << user_info->user_id << "\n" << user_info->auth_server_url << "\n";
            info_file.close();
        }
    }
    return user_path;
}

void SyncFileManager::remove_user_directory(const std::string& local_identity) const
{
    REALM_ASSERT(local_identity.length() > 0);
    const auto& escaped = util::make_percent_encoded_string(local_identity);
    if (filename_is_reserved(escaped))
        throw std::invalid_argument("A user can't have an identifier reserved by the filesystem.");

    auto user_path = file_path_by_appending_component(get_base_sync_directory(),
                                                      escaped,
                                                      util::FilePathType::Directory);
    util::try_remove_dir_recursive(user_path);
}

bool SyncFileManager::try_rename_user_directory(const std::string& old_name, const std::string& new_name) const
{
    REALM_ASSERT_DEBUG(old_name.length() > 0 && new_name.length() > 0);
    const auto& old_name_escaped = util::make_percent_encoded_string(old_name);
    const auto& new_name_escaped = util::make_percent_encoded_string(new_name);
    const std::string& base = get_base_sync_directory();
    if (filename_is_reserved(old_name_escaped) || filename_is_reserved(new_name_escaped))
        throw std::invalid_argument("A user directory can't be renamed using a reserved identifier.");

    const auto& old_path = file_path_by_appending_component(base, old_name_escaped, util::FilePathType::Directory);
    const auto& new_path = file_path_by_appending_component(base, new_name_escaped, util::FilePathType::Directory);

    try {
        File::move(old_path, new_path);
    } catch (File::NotFound const&) {
        return false;
    }
    return true;
}

bool SyncFileManager::remove_realm(const std::string& absolute_path) const
{
    REALM_ASSERT(absolute_path.length() > 0);
    bool success = true;
    // Remove the Realm file (e.g. "example.realm").
    success = File::try_remove(absolute_path);
    // Remove the lock file (e.g. "example.realm.lock").
    auto lock_path = util::file_path_by_appending_extension(absolute_path, "lock");
    success = File::try_remove(lock_path);
    // Remove the management directory (e.g. "example.realm.management").
    auto management_path = util::file_path_by_appending_extension(absolute_path, "management");
    try {
        util::try_remove_dir_recursive(management_path);
    }
    catch (File::AccessError const&) {
        success = false;
    }
    return success;
}

bool SyncFileManager::copy_realm_file(const std::string& old_path, const std::string& new_path) const
{
    REALM_ASSERT(old_path.length() > 0);
    try {
        if (File::exists(new_path)) {
            return false;
        }
        File::copy(old_path, new_path);
    }
    catch (File::NotFound const&) {
        return false;
    }
    catch (File::AccessError const&) {
        return false;
    }
    return true;
}

bool SyncFileManager::remove_realm(const std::string& local_identity, const std::string& raw_realm_path) const
{
    REALM_ASSERT(local_identity.length() > 0);
    REALM_ASSERT(raw_realm_path.length() > 0);
    if (filename_is_reserved(local_identity) || filename_is_reserved(raw_realm_path))
        throw std::invalid_argument("A user or Realm can't have an identifier reserved by the filesystem.");

    auto escaped = util::make_percent_encoded_string(raw_realm_path);
    auto realm_path = util::file_path_by_appending_component(user_directory(local_identity), escaped);
    return remove_realm(realm_path);
}

std::string SyncFileManager::path(const std::string& local_identity, const std::string& raw_realm_path,
                                  util::Optional<SyncUserIdentifier> user_info) const
{
    REALM_ASSERT(local_identity.length() > 0);
    REALM_ASSERT(raw_realm_path.length() > 0);
    if (filename_is_reserved(local_identity) || filename_is_reserved(raw_realm_path))
        throw std::invalid_argument("A user or Realm can't have an identifier reserved by the filesystem.");

    auto escaped = util::make_percent_encoded_string(raw_realm_path);
    auto realm_path = util::file_path_by_appending_component(user_directory(local_identity, user_info), escaped);
    return realm_path;
}

std::string SyncFileManager::metadata_path() const
{
    auto dir_path = file_path_by_appending_component(get_utility_directory(),
                                                     c_metadata_directory,
                                                     util::FilePathType::Directory);
    util::try_make_dir(dir_path);
    return util::file_path_by_appending_component(dir_path, c_metadata_realm);
}

bool SyncFileManager::remove_metadata_realm() const
{
    auto dir_path = file_path_by_appending_component(get_utility_directory(),
                                                     c_metadata_directory,
                                                     util::FilePathType::Directory);
    try {
        util::try_remove_dir_recursive(dir_path);
        return true;
    }
    catch (File::AccessError const&) {
        return false;
    }
}

} // realm
<|endoftext|>


<commit_before>// @(#)root/thread:$Id$
// Authors: Enric Tejedor, Enrico Guiraud CERN 05/06/2018

/*************************************************************************
 * Copyright (C) 1995-2016, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#ifndef ROOT_TTreeProcessorMT
#define ROOT_TTreeProcessorMT

#include "TKey.h"
#include "TTree.h"
#include "TFile.h"
#include "TChain.h"
#include "TEntryList.h"
#include "TTreeReader.h"
#include "TError.h"
#include "TEntryList.h"
#include "TFriendElement.h"
#include "ROOT/RMakeUnique.hxx"
#include "ROOT/TThreadedObject.hxx"
#include "ROOT/TThreadExecutor.hxx"

#include <functional>
#include <utility> // std::pair
#include <vector>

/** \class TTreeView
    \brief A helper class that encapsulates a file and a tree.

A helper class that encapsulates a TFile and a TTree, along with their names.
It is used together with TTProcessor and ROOT::TThreadedObject, so that
in the TTProcessor::Process method each thread can work on its own
<TFile,TTree> pair.

This class can also be used with a collection of file names or a TChain, in case
the tree is stored in more than one file. A view will always contain only the
current (active) tree and file objects.

A copy constructor is defined for TTreeView to work with ROOT::TThreadedObject.
The latter makes a copy of a model object every time a new thread accesses
the threaded object.
*/

namespace ROOT {
namespace Internal {
/// Names, aliases, and file names of a TTree's or TChain's friends
using NameAlias = std::pair<std::string, std::string>;
struct FriendInfo {
   /// Pairs of names and aliases of friend trees/chains
   std::vector<Internal::NameAlias> fFriendNames;
   /// Names of the files where each friend is stored. fFriendFileNames[i] is the list of files for friend with
   /// name fFriendNames[i]
   std::vector<std::vector<std::string>> fFriendFileNames;
};

class TTreeView {
private:
   std::vector<std::unique_ptr<TChain>> fFriends; ///< Friends of the tree/chain, if present
   std::unique_ptr<TEntryList> fEntryList;        ///< TEntryList for fChain, if present
   // NOTE: fFriends and fEntryList MUST come before fChain to be deleted after it, because neither friend trees nor
   // entrylists are deregistered from the main tree at destruction (ROOT-9283 tracks the issue for friends).
   std::unique_ptr<TChain> fChain;                ///< Chain on which to operate

   void MakeChain(const std::vector<std::string> &treeName, const std::vector<std::string> &fileNames,
                  const FriendInfo &friendInfo, const std::vector<Long64_t> &nEntries,
                  const std::vector<std::vector<Long64_t>> &friendEntries);

public:
   TTreeView() = default;
   // no-op, we don't want to copy the local TChains
   TTreeView(const TTreeView &) {}
   std::unique_ptr<TTreeReader> GetTreeReader(Long64_t start, Long64_t end, const std::vector<std::string> &treeName,
                                              const std::vector<std::string> &fileNames, const FriendInfo &friendInfo,
                                              const TEntryList &entryList, const std::vector<Long64_t> &nEntries,
                                              const std::vector<std::vector<Long64_t>> &friendEntries);
};
} // End of namespace Internal

class TTreeProcessorMT {
private:
   const std::vector<std::string> fFileNames; ///< Names of the files
   const std::vector<std::string> fTreeNames; ///< TTree names (always same size and ordering as fFileNames)
   /// User-defined selection of entry numbers to be processed, empty if none was provided
   TEntryList fEntryList;
   const Internal::FriendInfo fFriendInfo;
   ROOT::TThreadExecutor fPool; ///<! Thread pool for processing.

   /// Thread-local TreeViews
   // Must be declared after fPool, for IMT to be initialized first!
   ROOT::TThreadedObject<ROOT::Internal::TTreeView> fTreeView{TNumSlots{ROOT::GetThreadPoolSize()}};

   Internal::FriendInfo GetFriendInfo(TTree &tree);
   std::vector<std::string> FindTreeNames();
   static unsigned int fgMaxTasksPerFilePerWorker;
   static unsigned int fgTasksPerWorkerHint;

public:
   TTreeProcessorMT(std::string_view filename, std::string_view treename = "", UInt_t nThreads = 0u);
   TTreeProcessorMT(const std::vector<std::string_view> &filenames, std::string_view treename = "",
                    UInt_t nThreads = 0u);
   TTreeProcessorMT(TTree &tree, const TEntryList &entries, UInt_t nThreads = 0u);
   TTreeProcessorMT(TTree &tree, UInt_t nThreads = 0u);

   void Process(std::function<void(TTreeReader &)> func);
   static void SetMaxTasksPerFilePerWorker(unsigned int m);
   static unsigned int GetMaxTasksPerFilePerWorker();
   static void SetTasksPerWorkerHint(unsigned int m);
   static unsigned int GetTasksPerWorkerHint();
};

} // End of namespace ROOT

#endif // defined TTreeProcessorMT
<commit_msg>[TreeProcMT] Deprecate {G,S}etMaxTasksPerFilePerWorker<commit_after>// @(#)root/thread:$Id$
// Authors: Enric Tejedor, Enrico Guiraud CERN 05/06/2018

/*************************************************************************
 * Copyright (C) 1995-2016, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#ifndef ROOT_TTreeProcessorMT
#define ROOT_TTreeProcessorMT

#include "TKey.h"
#include "TTree.h"
#include "TFile.h"
#include "TChain.h"
#include "TEntryList.h"
#include "TTreeReader.h"
#include "TError.h"
#include "TEntryList.h"
#include "TFriendElement.h"
#include "ROOT/RMakeUnique.hxx"
#include "ROOT/TThreadedObject.hxx"
#include "ROOT/TThreadExecutor.hxx"

#include <functional>
#include <utility> // std::pair
#include <vector>

/** \class TTreeView
    \brief A helper class that encapsulates a file and a tree.

A helper class that encapsulates a TFile and a TTree, along with their names.
It is used together with TTProcessor and ROOT::TThreadedObject, so that
in the TTProcessor::Process method each thread can work on its own
<TFile,TTree> pair.

This class can also be used with a collection of file names or a TChain, in case
the tree is stored in more than one file. A view will always contain only the
current (active) tree and file objects.

A copy constructor is defined for TTreeView to work with ROOT::TThreadedObject.
The latter makes a copy of a model object every time a new thread accesses
the threaded object.
*/

namespace ROOT {
namespace Internal {
/// Names, aliases, and file names of a TTree's or TChain's friends
using NameAlias = std::pair<std::string, std::string>;
struct FriendInfo {
   /// Pairs of names and aliases of friend trees/chains
   std::vector<Internal::NameAlias> fFriendNames;
   /// Names of the files where each friend is stored. fFriendFileNames[i] is the list of files for friend with
   /// name fFriendNames[i]
   std::vector<std::vector<std::string>> fFriendFileNames;
};

class TTreeView {
private:
   std::vector<std::unique_ptr<TChain>> fFriends; ///< Friends of the tree/chain, if present
   std::unique_ptr<TEntryList> fEntryList;        ///< TEntryList for fChain, if present
   // NOTE: fFriends and fEntryList MUST come before fChain to be deleted after it, because neither friend trees nor
   // entrylists are deregistered from the main tree at destruction (ROOT-9283 tracks the issue for friends).
   std::unique_ptr<TChain> fChain;                ///< Chain on which to operate

   void MakeChain(const std::vector<std::string> &treeName, const std::vector<std::string> &fileNames,
                  const FriendInfo &friendInfo, const std::vector<Long64_t> &nEntries,
                  const std::vector<std::vector<Long64_t>> &friendEntries);

public:
   TTreeView() = default;
   // no-op, we don't want to copy the local TChains
   TTreeView(const TTreeView &) {}
   std::unique_ptr<TTreeReader> GetTreeReader(Long64_t start, Long64_t end, const std::vector<std::string> &treeName,
                                              const std::vector<std::string> &fileNames, const FriendInfo &friendInfo,
                                              const TEntryList &entryList, const std::vector<Long64_t> &nEntries,
                                              const std::vector<std::vector<Long64_t>> &friendEntries);
};
} // End of namespace Internal

class TTreeProcessorMT {
private:
   const std::vector<std::string> fFileNames; ///< Names of the files
   const std::vector<std::string> fTreeNames; ///< TTree names (always same size and ordering as fFileNames)
   /// User-defined selection of entry numbers to be processed, empty if none was provided
   TEntryList fEntryList;
   const Internal::FriendInfo fFriendInfo;
   ROOT::TThreadExecutor fPool; ///<! Thread pool for processing.

   /// Thread-local TreeViews
   // Must be declared after fPool, for IMT to be initialized first!
   ROOT::TThreadedObject<ROOT::Internal::TTreeView> fTreeView{TNumSlots{ROOT::GetThreadPoolSize()}};

   Internal::FriendInfo GetFriendInfo(TTree &tree);
   std::vector<std::string> FindTreeNames();
   static unsigned int fgMaxTasksPerFilePerWorker;
   static unsigned int fgTasksPerWorkerHint;

public:
   TTreeProcessorMT(std::string_view filename, std::string_view treename = "", UInt_t nThreads = 0u);
   TTreeProcessorMT(const std::vector<std::string_view> &filenames, std::string_view treename = "",
                    UInt_t nThreads = 0u);
   TTreeProcessorMT(TTree &tree, const TEntryList &entries, UInt_t nThreads = 0u);
   TTreeProcessorMT(TTree &tree, UInt_t nThreads = 0u);

   void Process(std::function<void(TTreeReader &)> func);

   R__DEPRECATED(6, 26, "Please use SetTasksPerWorkerHint instead. This setting will be ignored.")
   static void SetMaxTasksPerFilePerWorker(unsigned int m);
   R__DEPRECATED(6, 26, "Please use SetTasksPerWorkerHint and GetTasksPerWorkerHint instead. This setting is ignored.")
   static unsigned int GetMaxTasksPerFilePerWorker();
   static void SetTasksPerWorkerHint(unsigned int m);
   static unsigned int GetTasksPerWorkerHint();
};

} // End of namespace ROOT

#endif // defined TTreeProcessorMT
<|endoftext|>


<commit_before>#include "Graphics/Engine.h"
#include "EngineInternal.h"
#include "vulkan/vulkan.hpp"
#include <exception>
#include <iostream>
#include <memory>
#include <vector>

using namespace CR::Graphics;
using namespace std;
using namespace std::string_literals;

namespace {
	constexpr uint MajorVersion = 0;    // 64K max
	constexpr uint MinorVersion = 1;    // 256 max
	constexpr uint PatchVersion = 1;    // 256 max
	constexpr uint Version      = (MajorVersion << 16) || (MajorVersion << 8) || (PatchVersion);

	class Engine {
	  public:
		Engine(const EngineSettings& a_settings);
		~Engine();
		Engine(const Engine&) = delete;
		Engine& operator=(const Engine&) = delete;

		// private: internal so private anyway
		vk::Instance m_Instance;
		vk::Device m_Device;
	};

	unique_ptr<Engine> g_Engine;
}    // namespace

Engine::Engine(const EngineSettings& a_settings) {
	vector<string> enabledLayers;
	if(a_settings.EnableDebug) {
		vector<vk::LayerProperties> layers = vk::enumerateInstanceLayerProperties();
		for(const auto& layer : layers) {
			if("VK_LAYER_LUNARG_standard_validation"s == layer.layerName) { enabledLayers.push_back(layer.layerName); }
		}
	}

	vk::ApplicationInfo appInfo;
	appInfo.pApplicationName   = a_settings.ApplicationName.c_str();
	appInfo.applicationVersion = a_settings.ApplicationVersion;
	appInfo.pEngineName        = "Conjure";
	appInfo.engineVersion      = Version;
	appInfo.apiVersion         = VK_API_VERSION_1_0;

	vector<const char*> enabledLayersPtrs;
	for(auto& layer : enabledLayers) { enabledLayersPtrs.push_back(layer.c_str()); }

	vk::InstanceCreateInfo createInfo;
	createInfo.pApplicationInfo        = &appInfo;
	createInfo.enabledLayerCount       = (uint32_t)size(enabledLayersPtrs);
	createInfo.ppEnabledLayerNames     = data(enabledLayersPtrs);
	createInfo.enabledExtensionCount   = 0;
	createInfo.ppEnabledExtensionNames = nullptr;

	m_Instance = vk::createInstance(createInfo);

	vector<vk::PhysicalDevice> physicalDevices = m_Instance.enumeratePhysicalDevices();

	vk::PhysicalDevice selectedDevice;
	bool foundDevice       = false;
	int graphicsQueueIndex = -1;
	int transferQueueIndex = -1;
	for(auto& device : physicalDevices) {
		auto props = device.getProperties();
		cout << "Device Name: " << props.deviceName << endl;
		auto memProps = device.getMemoryProperties();
		for(uint32_t i = 0; i < memProps.memoryTypeCount; ++i) {
			if(memProps.memoryTypes[i].propertyFlags & vk::MemoryPropertyFlagBits::eDeviceLocal) {
				cout << "Device Local Memory Amount: "
				     << memProps.memoryHeaps[memProps.memoryTypes[i].heapIndex].size / (1024 * 1024) << "MB" << endl;
			}
		}

		vector<vk::QueueFamilyProperties> queueProps = device.getQueueFamilyProperties();
		bool supportsGraphics                        = false;
		bool supportsTransfer                        = false;
		for(uint32_t i = 0; i < queueProps.size(); ++i) {
			// This one should only be false for tesla compute cards and similiar
			if((queueProps[i].queueFlags & vk::QueueFlagBits::eGraphics) && queueProps[i].queueCount >= 1) {
				supportsGraphics   = true;
				graphicsQueueIndex = i;
			}
			if((queueProps[i].queueFlags & vk::QueueFlagBits::eTransfer) && queueProps[i].queueCount >= 1) {
				supportsTransfer   = true;
				transferQueueIndex = i;
			}
		}

		auto features = device.getFeatures();

		// TODO: We dont have a good heuristic for selecting a device, for now just take first one that supports
		// graphics and hope for the best.  My machine has only one, so cant test a better implementation.
		if(supportsGraphics && supportsTransfer && features.textureCompressionBC && features.fullDrawIndexUint32) {
			foundDevice    = true;
			selectedDevice = device;
			break;
		}
	}
	if(!foundDevice) { throw runtime_error("Could not find a valid vulkan device"); }

	vk::PhysicalDeviceFeatures requiredFeatures;
	requiredFeatures.textureCompressionBC = true;
	requiredFeatures.fullDrawIndexUint32  = true;

	float graphicsPriority = 1.0f;
	float transferPriority = 0.0f;
	vk::DeviceQueueCreateInfo queueInfos[2];
	queueInfos[0].queueFamilyIndex = graphicsQueueIndex;
	queueInfos[0].queueCount       = 1;
	queueInfos[0].pQueuePriorities = &graphicsPriority;
	queueInfos[1]                  = queueInfos[0];
	queueInfos[1].queueFamilyIndex = transferQueueIndex;
	queueInfos[1].pQueuePriorities = &transferPriority;

	vk::DeviceCreateInfo createLogDevInfo;
	createLogDevInfo.queueCreateInfoCount    = (int)size(queueInfos);
	createLogDevInfo.pQueueCreateInfos       = queueInfos;
	createLogDevInfo.pEnabledFeatures        = &requiredFeatures;
	createLogDevInfo.enabledLayerCount       = 0;
	createLogDevInfo.ppEnabledLayerNames     = nullptr;
	createLogDevInfo.enabledExtensionCount   = 0;
	createLogDevInfo.ppEnabledExtensionNames = nullptr;

	m_Device = selectedDevice.createDevice(createLogDevInfo);
}

Engine::~Engine() {
	m_Device.destroy();
	m_Instance.destroy();
}

void CR::Graphics::CreateEngine(const EngineSettings& a_settings) {
	g_Engine = make_unique<Engine>(a_settings);
}

void CR::Graphics::ShutdownEngine() {
	g_Engine.reset();
}

vk::Device& CR::Graphics::GetDevice() {
	assert(g_Engine.get());
	return g_Engine->m_Device;
}
<commit_msg>log texture maximum sizes<commit_after>#include "Graphics/Engine.h"
#include "EngineInternal.h"
#include "vulkan/vulkan.hpp"
#include <exception>
#include <iostream>
#include <memory>
#include <vector>

using namespace CR::Graphics;
using namespace std;
using namespace std::string_literals;

namespace {
	constexpr uint MajorVersion = 0;    // 64K max
	constexpr uint MinorVersion = 1;    // 256 max
	constexpr uint PatchVersion = 1;    // 256 max
	constexpr uint Version      = (MajorVersion << 16) || (MajorVersion << 8) || (PatchVersion);

	class Engine {
	  public:
		Engine(const EngineSettings& a_settings);
		~Engine();
		Engine(const Engine&) = delete;
		Engine& operator=(const Engine&) = delete;

		// private: internal so private anyway
		vk::Instance m_Instance;
		vk::Device m_Device;
	};

	unique_ptr<Engine> g_Engine;
}    // namespace

Engine::Engine(const EngineSettings& a_settings) {
	vector<string> enabledLayers;
	if(a_settings.EnableDebug) {
		vector<vk::LayerProperties> layers = vk::enumerateInstanceLayerProperties();
		for(const auto& layer : layers) {
			if("VK_LAYER_LUNARG_standard_validation"s == layer.layerName) { enabledLayers.push_back(layer.layerName); }
		}
	}

	vk::ApplicationInfo appInfo;
	appInfo.pApplicationName   = a_settings.ApplicationName.c_str();
	appInfo.applicationVersion = a_settings.ApplicationVersion;
	appInfo.pEngineName        = "Conjure";
	appInfo.engineVersion      = Version;
	appInfo.apiVersion         = VK_API_VERSION_1_0;

	vector<const char*> enabledLayersPtrs;
	for(auto& layer : enabledLayers) { enabledLayersPtrs.push_back(layer.c_str()); }

	vk::InstanceCreateInfo createInfo;
	createInfo.pApplicationInfo        = &appInfo;
	createInfo.enabledLayerCount       = (uint32_t)size(enabledLayersPtrs);
	createInfo.ppEnabledLayerNames     = data(enabledLayersPtrs);
	createInfo.enabledExtensionCount   = 0;
	createInfo.ppEnabledExtensionNames = nullptr;

	m_Instance = vk::createInstance(createInfo);

	vector<vk::PhysicalDevice> physicalDevices = m_Instance.enumeratePhysicalDevices();

	vk::PhysicalDevice selectedDevice;
	bool foundDevice       = false;
	int graphicsQueueIndex = -1;
	int transferQueueIndex = -1;
	for(auto& device : physicalDevices) {
		auto props = device.getProperties();
		cout << "Device Name: " << props.deviceName << endl;
		auto memProps = device.getMemoryProperties();
		for(uint32_t i = 0; i < memProps.memoryTypeCount; ++i) {
			if(memProps.memoryTypes[i].propertyFlags & vk::MemoryPropertyFlagBits::eDeviceLocal) {
				cout << "Device Local Memory Amount: "
				     << memProps.memoryHeaps[memProps.memoryTypes[i].heapIndex].size / (1024 * 1024) << "MB" << endl;
			}
		}

		vector<vk::QueueFamilyProperties> queueProps = device.getQueueFamilyProperties();
		bool supportsGraphics                        = false;
		bool supportsTransfer                        = false;
		for(uint32_t i = 0; i < queueProps.size(); ++i) {
			// This one should only be false for tesla compute cards and similiar
			if((queueProps[i].queueFlags & vk::QueueFlagBits::eGraphics) && queueProps[i].queueCount >= 1) {
				supportsGraphics   = true;
				graphicsQueueIndex = i;
			}
			if((queueProps[i].queueFlags & vk::QueueFlagBits::eTransfer) && queueProps[i].queueCount >= 1) {
				supportsTransfer   = true;
				transferQueueIndex = i;
			}
		}

		auto features = device.getFeatures();

		// TODO: We dont have a good heuristic for selecting a device, for now just take first one that supports
		// graphics and hope for the best.  My machine has only one, so cant test a better implementation.
		if(supportsGraphics && supportsTransfer && features.textureCompressionBC && features.fullDrawIndexUint32) {
			foundDevice    = true;
			selectedDevice = device;
			break;
		}
	}
	if(!foundDevice) { throw runtime_error("Could not find a valid vulkan device"); }

	vk::Format formatsToLog[] = {vk::Format::eBc1RgbSrgbBlock, vk::Format::eBc3SrgbBlock, vk::Format::eBc4UnormBlock,
	                             vk::Format::eBc5SnormBlock, vk::Format::eA8B8G8R8SrgbPack32};
	for(auto& format : formatsToLog) {
		auto formatProps = selectedDevice.getImageFormatProperties(
		    format, vk::ImageType::e2D, vk::ImageTiling::eOptimal, vk::ImageUsageFlagBits::eSampled,
		    vk::ImageCreateFlagBits::e2DArrayCompatible);
		cout << to_string(format) << " - Max width: " << formatProps.maxExtent.width
		     << " Max height: " << formatProps.maxExtent.height << " Max array size: " << formatProps.maxArrayLayers
		     << endl;
	}

	vk::PhysicalDeviceFeatures requiredFeatures;
	requiredFeatures.textureCompressionBC = true;
	requiredFeatures.fullDrawIndexUint32  = true;

	float graphicsPriority = 1.0f;
	float transferPriority = 0.0f;
	vk::DeviceQueueCreateInfo queueInfos[2];
	queueInfos[0].queueFamilyIndex = graphicsQueueIndex;
	queueInfos[0].queueCount       = 1;
	queueInfos[0].pQueuePriorities = &graphicsPriority;
	queueInfos[1]                  = queueInfos[0];
	queueInfos[1].queueFamilyIndex = transferQueueIndex;
	queueInfos[1].pQueuePriorities = &transferPriority;

	vk::DeviceCreateInfo createLogDevInfo;
	createLogDevInfo.queueCreateInfoCount    = (int)size(queueInfos);
	createLogDevInfo.pQueueCreateInfos       = queueInfos;
	createLogDevInfo.pEnabledFeatures        = &requiredFeatures;
	createLogDevInfo.enabledLayerCount       = 0;
	createLogDevInfo.ppEnabledLayerNames     = nullptr;
	createLogDevInfo.enabledExtensionCount   = 0;
	createLogDevInfo.ppEnabledExtensionNames = nullptr;

	m_Device = selectedDevice.createDevice(createLogDevInfo);
}

Engine::~Engine() {
	m_Device.destroy();
	m_Instance.destroy();
}

void CR::Graphics::CreateEngine(const EngineSettings& a_settings) {
	g_Engine = make_unique<Engine>(a_settings);
}

void CR::Graphics::ShutdownEngine() {
	g_Engine.reset();
}

vk::Device& CR::Graphics::GetDevice() {
	assert(g_Engine.get());
	return g_Engine->m_Device;
}
<|endoftext|>


<commit_before>/*
 * InputSystem.cpp
 *
 *  Created on: 15/07/2014
 *      Author: vitor
 */

#include "InputSystem.h"

void InputSystem::process_entities(std::map<uint64_t, EntityPtr>& entities,
		double dt) {
	SDL_Event event;
	while (SDL_PollEvent(&event)) {
		switch (event.type) {
		case SDL_QUIT:
			world_ptr->get_event_manager().broadcast<Quit>();
			break;
		case SDL_KEYDOWN:
			if (!event.key.repeat) {
				world_ptr->get_event_manager().broadcast<KeyboardDown>(
						event.key.keysym.scancode);
			}
			break;
		case SDL_KEYUP:
			if (!event.key.repeat) {
				world_ptr->get_event_manager().broadcast<KeyboardUp>(
						event.key.keysym.scancode);
			}
			break;
		default:
			break;
		}
	}
}

void InputSystem::process_entity(Entity& entity, double dt) {
}
<commit_msg>Removed unnecessary repeat check for KEYUP.<commit_after>/*
 * InputSystem.cpp
 *
 *  Created on: 15/07/2014
 *      Author: vitor
 */

#include "InputSystem.h"

void InputSystem::process_entities(std::map<uint64_t, EntityPtr>& entities,
		double dt) {
	SDL_Event event;
	while (SDL_PollEvent(&event)) {
		switch (event.type) {
		case SDL_QUIT:
			world_ptr->get_event_manager().broadcast<Quit>();
			break;
		case SDL_KEYDOWN:
			if (!event.key.repeat) {
				world_ptr->get_event_manager().broadcast<KeyboardDown>(
						event.key.keysym.scancode);
			}
			break;
		case SDL_KEYUP:
			world_ptr->get_event_manager().broadcast<KeyboardUp>(
					event.key.keysym.scancode);
			break;
		default:
			break;
		}
	}
}

void InputSystem::process_entity(Entity& entity, double dt) {
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2019-present ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#include "seastarx.hh"

#include "db/timeout_clock.hh"
#include "schema_fwd.hh"

namespace seastar {
    class file;
} // namespace seastar

struct reader_resources {
    int count = 0;
    ssize_t memory = 0;

    static reader_resources with_memory(ssize_t memory) { return reader_resources(0, memory); }

    reader_resources() = default;

    reader_resources(int count, ssize_t memory)
        : count(count)
        , memory(memory) {
    }

    bool operator>=(const reader_resources& other) const {
        return count >= other.count && memory >= other.memory;
    }

    reader_resources operator-(const reader_resources& other) const {
        return reader_resources{count - other.count, memory - other.memory};
    }

    reader_resources& operator-=(const reader_resources& other) {
        count -= other.count;
        memory -= other.memory;
        return *this;
    }

    reader_resources operator+(const reader_resources& other) const {
        return reader_resources{count + other.count, memory + other.memory};
    }

    reader_resources& operator+=(const reader_resources& other) {
        count += other.count;
        memory += other.memory;
        return *this;
    }

    explicit operator bool() const {
        return count > 0 || memory > 0;
    }
};

inline bool operator==(const reader_resources& a, const reader_resources& b) {
    return a.count == b.count && a.memory == b.memory;
}

class reader_concurrency_semaphore;

/// A permit for a specific read.
///
/// Used to track the read's resource consumption and wait for admission to read
/// from the disk.
/// Use `consume_memory()` to register memory usage. Use `wait_admission()` to
/// wait for admission, before reading from the disk. Both methods return a
/// `resource_units` RAII object that should be held onto while the respective
/// resources are in use.
class reader_permit {
    friend class reader_concurrency_semaphore;

public:
    class resource_units;

    enum class state {
        waiting, // waiting for admission
        active,
        inactive,
        evicted,
    };

    class impl;

private:
    shared_ptr<impl> _impl;

private:
    explicit reader_permit(reader_concurrency_semaphore& semaphore, const schema* const schema, std::string_view op_name);
    explicit reader_permit(reader_concurrency_semaphore& semaphore, const schema* const schema, sstring&& op_name);

    void on_waiting();
    void on_admission();

public:
    ~reader_permit();

    reader_permit(const reader_permit&) = default;
    reader_permit(reader_permit&&) = default;

    reader_permit& operator=(const reader_permit&) = default;
    reader_permit& operator=(reader_permit&&) = default;

    bool operator==(const reader_permit& o) const {
        return _impl == o._impl;
    }

    reader_concurrency_semaphore& semaphore();

    future<resource_units> wait_admission(size_t memory, db::timeout_clock::time_point timeout);

    void consume(reader_resources res);

    void signal(reader_resources res);

    resource_units consume_memory(size_t memory = 0);

    resource_units consume_resources(reader_resources res);

    reader_resources consumed_resources() const;

    sstring description() const;
};

class reader_permit::resource_units {
    reader_permit _permit;
    reader_resources _resources;

    friend class reader_permit;
    friend class reader_concurrency_semaphore;
private:
    resource_units(reader_permit permit, reader_resources res) noexcept;
public:
    resource_units(const resource_units&) = delete;
    resource_units(resource_units&&) noexcept;
    ~resource_units();
    resource_units& operator=(const resource_units&) = delete;
    resource_units& operator=(resource_units&&) noexcept;
    void add(resource_units&& o);
    void reset(reader_resources res = {});
    reader_permit permit() const { return _permit; }
    reader_resources resources() const { return _resources; }
};

template <typename Char>
temporary_buffer<Char> make_tracked_temporary_buffer(temporary_buffer<Char> buf, reader_permit& permit) {
    return temporary_buffer<Char>(buf.get_write(), buf.size(),
            make_deleter(buf.release(), [units = permit.consume_memory(buf.size())] () mutable { units.reset(); }));
}

file make_tracked_file(file f, reader_permit p);

template <typename T>
class tracking_allocator {
public:
    using value_type = T;
    using propagate_on_container_move_assignment = std::true_type;
    using is_always_equal = std::false_type;

private:
    reader_permit _permit;
    std::allocator<T> _alloc;

public:
    tracking_allocator(reader_permit permit) noexcept : _permit(std::move(permit)) { }

    T* allocate(size_t n) {
        auto p = _alloc.allocate(n);
        _permit.consume(reader_resources::with_memory(n * sizeof(T)));
        return p;
    }
    void deallocate(T* p, size_t n) {
        _alloc.deallocate(p, n);
        if (n) {
            _permit.signal(reader_resources::with_memory(n * sizeof(T)));
        }
    }

    template <typename U>
    friend bool operator==(const tracking_allocator<U>& a, const tracking_allocator<U>& b);
};

template <typename T>
bool operator==(const tracking_allocator<T>& a, const tracking_allocator<T>& b) {
    return a._semaphore == b._semaphore;
}
<commit_msg>reader_permit: add reader_permit_opt<commit_after>/*
 * Copyright (C) 2019-present ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#include <seastar/util/optimized_optional.hh>
#include "seastarx.hh"

#include "db/timeout_clock.hh"
#include "schema_fwd.hh"

namespace seastar {
    class file;
} // namespace seastar

struct reader_resources {
    int count = 0;
    ssize_t memory = 0;

    static reader_resources with_memory(ssize_t memory) { return reader_resources(0, memory); }

    reader_resources() = default;

    reader_resources(int count, ssize_t memory)
        : count(count)
        , memory(memory) {
    }

    bool operator>=(const reader_resources& other) const {
        return count >= other.count && memory >= other.memory;
    }

    reader_resources operator-(const reader_resources& other) const {
        return reader_resources{count - other.count, memory - other.memory};
    }

    reader_resources& operator-=(const reader_resources& other) {
        count -= other.count;
        memory -= other.memory;
        return *this;
    }

    reader_resources operator+(const reader_resources& other) const {
        return reader_resources{count + other.count, memory + other.memory};
    }

    reader_resources& operator+=(const reader_resources& other) {
        count += other.count;
        memory += other.memory;
        return *this;
    }

    explicit operator bool() const {
        return count > 0 || memory > 0;
    }
};

inline bool operator==(const reader_resources& a, const reader_resources& b) {
    return a.count == b.count && a.memory == b.memory;
}

class reader_concurrency_semaphore;

/// A permit for a specific read.
///
/// Used to track the read's resource consumption and wait for admission to read
/// from the disk.
/// Use `consume_memory()` to register memory usage. Use `wait_admission()` to
/// wait for admission, before reading from the disk. Both methods return a
/// `resource_units` RAII object that should be held onto while the respective
/// resources are in use.
class reader_permit {
    friend class reader_concurrency_semaphore;

public:
    class resource_units;

    enum class state {
        waiting, // waiting for admission
        active,
        inactive,
        evicted,
    };

    class impl;

private:
    shared_ptr<impl> _impl;

private:
    reader_permit() = default;
    explicit reader_permit(reader_concurrency_semaphore& semaphore, const schema* const schema, std::string_view op_name);
    explicit reader_permit(reader_concurrency_semaphore& semaphore, const schema* const schema, sstring&& op_name);

    void on_waiting();
    void on_admission();

    operator bool() const { return bool(_impl); }

    friend class optimized_optional<reader_permit>;

public:
    ~reader_permit();

    reader_permit(const reader_permit&) = default;
    reader_permit(reader_permit&&) = default;

    reader_permit& operator=(const reader_permit&) = default;
    reader_permit& operator=(reader_permit&&) = default;

    bool operator==(const reader_permit& o) const {
        return _impl == o._impl;
    }

    reader_concurrency_semaphore& semaphore();

    future<resource_units> wait_admission(size_t memory, db::timeout_clock::time_point timeout);

    void consume(reader_resources res);

    void signal(reader_resources res);

    resource_units consume_memory(size_t memory = 0);

    resource_units consume_resources(reader_resources res);

    reader_resources consumed_resources() const;

    sstring description() const;
};

using reader_permit_opt = optimized_optional<reader_permit>;

class reader_permit::resource_units {
    reader_permit _permit;
    reader_resources _resources;

    friend class reader_permit;
    friend class reader_concurrency_semaphore;
private:
    resource_units(reader_permit permit, reader_resources res) noexcept;
public:
    resource_units(const resource_units&) = delete;
    resource_units(resource_units&&) noexcept;
    ~resource_units();
    resource_units& operator=(const resource_units&) = delete;
    resource_units& operator=(resource_units&&) noexcept;
    void add(resource_units&& o);
    void reset(reader_resources res = {});
    reader_permit permit() const { return _permit; }
    reader_resources resources() const { return _resources; }
};

template <typename Char>
temporary_buffer<Char> make_tracked_temporary_buffer(temporary_buffer<Char> buf, reader_permit& permit) {
    return temporary_buffer<Char>(buf.get_write(), buf.size(),
            make_deleter(buf.release(), [units = permit.consume_memory(buf.size())] () mutable { units.reset(); }));
}

file make_tracked_file(file f, reader_permit p);

template <typename T>
class tracking_allocator {
public:
    using value_type = T;
    using propagate_on_container_move_assignment = std::true_type;
    using is_always_equal = std::false_type;

private:
    reader_permit _permit;
    std::allocator<T> _alloc;

public:
    tracking_allocator(reader_permit permit) noexcept : _permit(std::move(permit)) { }

    T* allocate(size_t n) {
        auto p = _alloc.allocate(n);
        _permit.consume(reader_resources::with_memory(n * sizeof(T)));
        return p;
    }
    void deallocate(T* p, size_t n) {
        _alloc.deallocate(p, n);
        if (n) {
            _permit.signal(reader_resources::with_memory(n * sizeof(T)));
        }
    }

    template <typename U>
    friend bool operator==(const tracking_allocator<U>& a, const tracking_allocator<U>& b);
};

template <typename T>
bool operator==(const tracking_allocator<T>& a, const tracking_allocator<T>& b) {
    return a._semaphore == b._semaphore;
}
<|endoftext|>