Moved to ztd library
This commit is contained in:
parent
a52826e00e
commit
88b2260b90
13 changed files with 70 additions and 1490 deletions
5
Makefile
5
Makefile
|
|
@ -12,6 +12,11 @@ CXXFLAGS= -I$(IDIR) -Wall -pedantic -std=c++17
|
||||||
ifeq ($(DEBUG),true)
|
ifeq ($(DEBUG),true)
|
||||||
CXXFLAGS += -g
|
CXXFLAGS += -g
|
||||||
endif
|
endif
|
||||||
|
ifeq ($(STATIC),true)
|
||||||
|
LDFLAGS += -l:libztd.a
|
||||||
|
else
|
||||||
|
LDFLAGS += -lztd
|
||||||
|
endif
|
||||||
|
|
||||||
$(shell mkdir -p $(ODIR))
|
$(shell mkdir -p $(ODIR))
|
||||||
$(shell mkdir -p $(BINDIR))
|
$(shell mkdir -p $(BINDIR))
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,7 @@
|
||||||
|
|
||||||
Map midi signals coming from ALSA midi devices to shell commands
|
Map midi signals coming from ALSA midi devices to shell commands
|
||||||
|
|
||||||
Soft dependencies: alsa-utils
|
Dependencies: alsa-utils , [ztd](https://github.com/zawwz/ztd)
|
||||||
Hard dependencies: aseqdump
|
|
||||||
|
|
||||||
## Installing
|
## Installing
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,191 +0,0 @@
|
||||||
#ifndef FILEDAT_H
|
|
||||||
#define FILEDAT_H
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
#include <map>
|
|
||||||
#include <iostream>
|
|
||||||
#include <fstream>
|
|
||||||
|
|
||||||
#include <cstring>
|
|
||||||
|
|
||||||
class format_error : public std::exception
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
format_error(const std::string& what, const std::string& origin, const std::string& data, int where) { desc=what; index=where; filename=origin; sdat=data; }
|
|
||||||
|
|
||||||
const char * what () const throw () {return desc.c_str();}
|
|
||||||
const int where () const throw () {return index;}
|
|
||||||
const char * data() const throw () {return sdat.c_str();}
|
|
||||||
const char * origin() const throw () {return filename.c_str();}
|
|
||||||
private:
|
|
||||||
std::string desc;
|
|
||||||
int index;
|
|
||||||
std::string filename;
|
|
||||||
std::string sdat;
|
|
||||||
};
|
|
||||||
|
|
||||||
void printErrorIndex(const char* in, const int index, const std::string& message, const std::string& origin);
|
|
||||||
inline void printFormatException(format_error& exc) { printErrorIndex(exc.data(), exc.where(), exc.what(), exc.origin()); }
|
|
||||||
|
|
||||||
class Filedat;
|
|
||||||
|
|
||||||
class AbstractChunk
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
enum typeEnum { none, val, chunk, list};
|
|
||||||
|
|
||||||
typeEnum type() { return m_type; }
|
|
||||||
|
|
||||||
AbstractChunk() { m_type=AbstractChunk::none; }
|
|
||||||
virtual ~AbstractChunk() {}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
typeEnum m_type;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Chunk
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Chunk() { m_achunk=nullptr; }
|
|
||||||
|
|
||||||
Chunk(const char* in)
|
|
||||||
{ m_achunk=nullptr; set(in, strlen(in), 0, nullptr); }
|
|
||||||
Chunk(std::string const& in)
|
|
||||||
{ m_achunk=nullptr; set(in, 0, nullptr); }
|
|
||||||
Chunk(const char* in, const int in_size, int offset=0, Filedat* data=nullptr)
|
|
||||||
{ m_achunk=nullptr; set(in, in_size, offset, data); }
|
|
||||||
Chunk(std::string const& in, int offset=0, Filedat* data=nullptr)
|
|
||||||
{ m_achunk=nullptr; set(in, offset, data); }
|
|
||||||
|
|
||||||
Chunk(Chunk const& in) { m_achunk=nullptr; set(in); }
|
|
||||||
|
|
||||||
void clear() { if(m_achunk!=nullptr) delete m_achunk; m_achunk=nullptr; }
|
|
||||||
~Chunk() { clear(); }
|
|
||||||
|
|
||||||
Filedat* parent() const { return m_parent; }
|
|
||||||
int offset() const { return m_offset; }
|
|
||||||
|
|
||||||
void set(const char* in, const int in_size, int offset=0, Filedat* data=nullptr);
|
|
||||||
void set(std::string const& in, int offset=0, Filedat* data=nullptr) { this->set(in.c_str(), in.size(), offset, data); }
|
|
||||||
|
|
||||||
void set(Chunk const& in) { this->set(in.strval(), in.offset(), in.parent()); } // TODO
|
|
||||||
|
|
||||||
std::string strval(unsigned int alignment=0, std::string const& aligner="\t") const;
|
|
||||||
|
|
||||||
|
|
||||||
void addToChunk(std::string const& name, Chunk const& val); //adds if datachunk
|
|
||||||
void addToChunk(std::vector<std::pair<std::string, Chunk>> const& vec); //adds if datachunk
|
|
||||||
void addToList(Chunk const& val); //adds if list
|
|
||||||
void addToList(std::vector<Chunk> const& vec); //adds if list
|
|
||||||
inline void add(std::string const& name, Chunk const& val) { addToChunk(name, val); } //adds if datachunk
|
|
||||||
inline void add(std::pair<std::string, Chunk> const& pair) { add(pair.first, pair.second); } //adds if datachunk
|
|
||||||
inline void add(std::vector<std::pair<std::string, Chunk>> const& vec) { addToChunk(vec); } //adds if datachunk
|
|
||||||
inline void add(Chunk const& val) { addToList(val); } //adds if list
|
|
||||||
inline void add(std::vector<Chunk> const& vec) { addToList(vec); } //adds if list
|
|
||||||
// void concatenate(Chunk const& chk); //concatenates chunks
|
|
||||||
|
|
||||||
Chunk copy() const { return Chunk(*this); }
|
|
||||||
Chunk* pcopy() const { return new Chunk(*this); }
|
|
||||||
|
|
||||||
AbstractChunk* getp() const { return m_achunk; }
|
|
||||||
AbstractChunk::typeEnum type() const { if(m_achunk!=nullptr) return m_achunk->type(); else return AbstractChunk::none; }
|
|
||||||
int listSize() const;
|
|
||||||
|
|
||||||
Chunk* subChunkPtr(std::string const& a) const; //datachunk
|
|
||||||
Chunk* subChunkPtr(unsigned int a) const; //chunklist
|
|
||||||
Chunk& subChunkRef(std::string const& a) const; //datachunk
|
|
||||||
Chunk& subChunkRef(unsigned int a) const; //chunklist
|
|
||||||
|
|
||||||
Chunk& operator[](std::string const& a) const { return subChunkRef(a); }
|
|
||||||
Chunk& operator[](unsigned int a) const { return subChunkRef(a); }
|
|
||||||
Chunk& operator=(Chunk const& a) { set(a); return *this; }
|
|
||||||
inline Chunk& operator+=(std::pair<std::string, Chunk> const& a) { add(a); return *this; }
|
|
||||||
inline Chunk& operator+=(std::vector<std::pair<std::string, Chunk>> const& a) { add(a); return *this; }
|
|
||||||
inline Chunk& operator+=(Chunk const& a) { add(a); return *this; }
|
|
||||||
inline Chunk& operator+=(std::vector<Chunk> const& a) { add(a); return *this; }
|
|
||||||
// inline bool operator*=(Chunk const& a) { concatenate(a); }
|
|
||||||
|
|
||||||
//add operator+ and operator*
|
|
||||||
|
|
||||||
|
|
||||||
protected:
|
|
||||||
Filedat* m_parent;
|
|
||||||
int m_offset;
|
|
||||||
|
|
||||||
AbstractChunk* m_achunk;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream& stream, Chunk const& a);
|
|
||||||
|
|
||||||
class DataVal : public AbstractChunk
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
DataVal() { m_type=AbstractChunk::val; }
|
|
||||||
virtual ~DataVal() {}
|
|
||||||
|
|
||||||
std::string val;
|
|
||||||
};
|
|
||||||
|
|
||||||
class DataChunk : public AbstractChunk
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
DataChunk() { m_type=AbstractChunk::chunk; }
|
|
||||||
virtual ~DataChunk();
|
|
||||||
|
|
||||||
std::map<std::string, Chunk*> values;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
class ChunkList : public AbstractChunk
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ChunkList() { m_type=AbstractChunk::list; }
|
|
||||||
virtual ~ChunkList();
|
|
||||||
|
|
||||||
std::vector<Chunk*> list;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Filedat
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Filedat();
|
|
||||||
Filedat(std::string const& in);
|
|
||||||
virtual ~Filedat();
|
|
||||||
|
|
||||||
bool readTest() const;
|
|
||||||
|
|
||||||
void import_file(const std::string& path="");
|
|
||||||
void import_stdin();
|
|
||||||
void import_string(const std::string& data);
|
|
||||||
bool export_file(std::string const& path="", std::string const& aligner="\t") const;
|
|
||||||
|
|
||||||
void clear();
|
|
||||||
|
|
||||||
inline std::string filePath() const { return m_filePath; }
|
|
||||||
inline void setFilePath(std::string const& in) { m_filePath=in; }
|
|
||||||
|
|
||||||
std::string strval(std::string const& aligner="\t") const;
|
|
||||||
|
|
||||||
inline Chunk* pchunk() const { return m_dataChunk; }
|
|
||||||
inline Chunk& chunk() const { return *m_dataChunk; }
|
|
||||||
|
|
||||||
inline Chunk* pdata() const { return m_dataChunk; }
|
|
||||||
inline Chunk& data() const { return *m_dataChunk; }
|
|
||||||
|
|
||||||
inline const std::string& stringdata() const { return m_data; }
|
|
||||||
inline const char* c_data() const { return m_data.c_str(); }
|
|
||||||
|
|
||||||
inline Chunk& operator[](const std::string& index) { return m_dataChunk->subChunkRef(index); }
|
|
||||||
inline Chunk& operator[](const int index) { return m_dataChunk->subChunkRef(index); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
//functions
|
|
||||||
void generateChunk();
|
|
||||||
//attributes
|
|
||||||
std::string m_filePath;
|
|
||||||
std::string m_data;
|
|
||||||
Chunk* m_dataChunk;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif //FILEDAT_H
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
#include "command.hpp"
|
#include "command.hpp"
|
||||||
#include "Filedat.hpp"
|
#include <ztd/filedat.hpp>
|
||||||
|
|
||||||
void sh(std::string const& string);
|
void sh(std::string const& string);
|
||||||
|
|
||||||
|
|
@ -19,8 +19,8 @@ public:
|
||||||
bool start_loop();
|
bool start_loop();
|
||||||
void run_signal(char* buff);
|
void run_signal(char* buff);
|
||||||
|
|
||||||
bool import_chunk(Chunk const& ch);
|
bool import_chunk(ztd::chunkdat const& ch);
|
||||||
Chunk export_chunk();
|
ztd::chunkdat export_chunk();
|
||||||
|
|
||||||
std::string name;
|
std::string name;
|
||||||
int client_id;
|
int client_id;
|
||||||
|
|
|
||||||
|
|
@ -1,94 +0,0 @@
|
||||||
#ifndef OPTIONS_H
|
|
||||||
#define OPTIONS_H
|
|
||||||
|
|
||||||
//DUPLICATES NOT HANDLED: takes last one
|
|
||||||
//NO ORDER: no way to know options order
|
|
||||||
//RETURNS TRANSITIONAL STATE IF ERROR
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
|
|
||||||
// Turn argc/argv into a vector<string>
|
|
||||||
std::vector<std::string> argVector(int argc, char** argv);
|
|
||||||
|
|
||||||
class Option
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/* CTOR/DTOR */
|
|
||||||
//ctors
|
|
||||||
Option();
|
|
||||||
Option(char c, bool arg, std::string helptext="", std::string argname="arg");
|
|
||||||
Option(std::string const& str, bool arg, std::string helptext="", std::string argname="arg");
|
|
||||||
Option(char c, std::string const& str, bool arg, std::string helptext="", std::string argname="arg");
|
|
||||||
//dtors
|
|
||||||
virtual ~Option();
|
|
||||||
|
|
||||||
/* FUNCTIONS */
|
|
||||||
|
|
||||||
// Print command help. Puts leftpad spaces before printing, and rightpad space until help
|
|
||||||
void printHelp(int leftpad, int rightpad);
|
|
||||||
|
|
||||||
/* PROPERTIES */
|
|
||||||
|
|
||||||
bool shortDef; // has a char definition
|
|
||||||
char charName;
|
|
||||||
|
|
||||||
bool longDef; // has a string definition
|
|
||||||
std::string strName;
|
|
||||||
|
|
||||||
bool takesArgument; // option takes an argument
|
|
||||||
|
|
||||||
std::string help_text; // text to display in printHelp
|
|
||||||
std::string arg_name; // name of the argument to display in printHelp
|
|
||||||
|
|
||||||
/* PROCESSING STATUS */
|
|
||||||
|
|
||||||
bool activated; // option was activated
|
|
||||||
|
|
||||||
std::string argument; // argument of the option
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
class OptionSet
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/* CTOR/DTOR */
|
|
||||||
OptionSet();
|
|
||||||
virtual ~OptionSet();
|
|
||||||
|
|
||||||
/* PROPERTIES */
|
|
||||||
|
|
||||||
// Stream on which errors are sent. Default stderr
|
|
||||||
std::ostream* errStream;
|
|
||||||
|
|
||||||
/* FUNCTIONS */
|
|
||||||
|
|
||||||
/*CREATION FUNCTIONS*/
|
|
||||||
//Adding an option. Refer to Option ctors
|
|
||||||
void addOption(Option opt) { m_options.push_back(opt); }
|
|
||||||
|
|
||||||
/*PRINT FUNCTIONS*/
|
|
||||||
// Print command help. Puts leftpad spaces before each line, and rightpad space until help
|
|
||||||
void printHelp(int leftpad=2, int rightpad=25);
|
|
||||||
|
|
||||||
/*QUERY FUNCTIONS*/
|
|
||||||
// Find an option with its charname
|
|
||||||
Option* findOption(char c);
|
|
||||||
// Find an option with its stringname
|
|
||||||
Option* findOption(std::string const& str);
|
|
||||||
|
|
||||||
/*PROCESSING FUNCTIONS*/
|
|
||||||
// Process through options.
|
|
||||||
// pair.first : vector with arguments that were not identified as options
|
|
||||||
// pair.second : bool indicating status. True if no error encountered, false if errors
|
|
||||||
std::pair<std::vector<std::string>,bool> getOptions(std::vector<std::string> input);
|
|
||||||
std::pair<std::vector<std::string>,bool> getOptions(int argc, char** argv) { return getOptions(argVector(argc, argv)); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::vector<Option> m_options;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif //OPTIONS_H
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
#ifndef POPEN_HPP
|
|
||||||
#define POPEN_HPP
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <signal.h>
|
|
||||||
|
|
||||||
FILE* popen2(const char* command, const char* type, pid_t* pid);
|
|
||||||
|
|
||||||
int pclose2(FILE* fp, pid_t pid);
|
|
||||||
|
|
||||||
#endif //POPEN_HPP
|
|
||||||
|
|
@ -1,14 +1,11 @@
|
||||||
#ifndef SYSTEM_HPP
|
#ifndef SYSTEM_HPP
|
||||||
#define SYSTEM_HPP
|
#define SYSTEM_HPP
|
||||||
|
|
||||||
#include "popen.h"
|
|
||||||
|
|
||||||
#define ANNOUNCE_COMMAND "aseqdump -p System:1"
|
#define ANNOUNCE_COMMAND "aseqdump -p System:1"
|
||||||
#define LIST_COMMAND "aseqdump -l | tail -n +2 | cut -c10-42 | tr -s ' '"
|
#define LIST_COMMAND "aseqdump -l | tail -n +2 | cut -c10-42 | tr -s ' '"
|
||||||
#define LIST_EXTENDED_COMMAND "aseqdump -l | tail -n +2 | cut -c-42"
|
#define LIST_EXTENDED_COMMAND "aseqdump -l | tail -n +2 | cut -c-42"
|
||||||
|
|
||||||
|
extern int announce_thread_pid;
|
||||||
extern pid_t announce_thread_pid;
|
|
||||||
|
|
||||||
void device_check();
|
void device_check();
|
||||||
|
|
||||||
|
|
|
||||||
815
src/Filedat.cpp
815
src/Filedat.cpp
|
|
@ -1,815 +0,0 @@
|
||||||
#include "Filedat.hpp"
|
|
||||||
|
|
||||||
#include <exception>
|
|
||||||
|
|
||||||
bool _isRead(char in)
|
|
||||||
{
|
|
||||||
bool out=false;
|
|
||||||
if(in>=33 && in<=126)
|
|
||||||
out=true;
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string _repeatString(const std::string& str, const unsigned int n)
|
|
||||||
{
|
|
||||||
std::string ret;
|
|
||||||
for(unsigned int i=0 ; i<n ; i++)
|
|
||||||
ret += str;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void printErrorIndex(const char* in, const int index, const std::string& message, const std::string& origin)
|
|
||||||
{
|
|
||||||
int i=0, j=0; // j: last newline
|
|
||||||
int line=1; //n: line #
|
|
||||||
int in_size=strlen(in);
|
|
||||||
if(index >= 0)
|
|
||||||
{
|
|
||||||
while(i < in_size && i < index)
|
|
||||||
{
|
|
||||||
if(in[i] == '\n')
|
|
||||||
{
|
|
||||||
line++;
|
|
||||||
j=i+1;
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
while(i < in_size && in[i]!='\n')
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(origin != "")
|
|
||||||
{
|
|
||||||
std::cerr << origin << ": Error\nLine " << line << " col " << index-j+1 << ": " << message << std::endl;
|
|
||||||
std::cerr << std::string(in+j, i-j) << std::endl;
|
|
||||||
std::cerr << _repeatString(" ", index-j) << '^' << std::endl;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::cerr << "Format Error: " << message << std::endl;
|
|
||||||
if(index >= 0)
|
|
||||||
{
|
|
||||||
std::cerr << std::string(in, i) << std::endl;
|
|
||||||
std::cerr << _repeatString(" ", index-j) << '^' << std::endl;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
std::cerr << in << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Filedat::Filedat()
|
|
||||||
{
|
|
||||||
m_dataChunk = new Chunk();
|
|
||||||
}
|
|
||||||
|
|
||||||
Filedat::Filedat(std::string const& in)
|
|
||||||
{
|
|
||||||
m_dataChunk = new Chunk();
|
|
||||||
m_filePath=in;
|
|
||||||
}
|
|
||||||
|
|
||||||
Filedat::~Filedat()
|
|
||||||
{
|
|
||||||
if(m_dataChunk!=nullptr)
|
|
||||||
delete m_dataChunk;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Filedat::clear()
|
|
||||||
{
|
|
||||||
m_data="";
|
|
||||||
if(m_dataChunk!=nullptr)
|
|
||||||
{
|
|
||||||
delete m_dataChunk;
|
|
||||||
m_dataChunk = new Chunk();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Filedat::readTest() const
|
|
||||||
{
|
|
||||||
std::ifstream stream(m_filePath);
|
|
||||||
if(!stream)
|
|
||||||
return false;
|
|
||||||
else
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Filedat::import_file(const std::string& path)
|
|
||||||
{
|
|
||||||
if(path != "")
|
|
||||||
m_filePath=path;
|
|
||||||
std::ifstream st(m_filePath);
|
|
||||||
if(!st)
|
|
||||||
throw std::runtime_error("Cannot read file '" + m_filePath + '\'');
|
|
||||||
|
|
||||||
this->clear();
|
|
||||||
std::string line;
|
|
||||||
|
|
||||||
while(st)
|
|
||||||
{
|
|
||||||
getline(st, line);
|
|
||||||
m_data += (line + '\n');
|
|
||||||
}
|
|
||||||
this->generateChunk();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Filedat::import_stdin()
|
|
||||||
{
|
|
||||||
m_filePath="stdin";
|
|
||||||
this->clear();
|
|
||||||
std::string line;
|
|
||||||
while(std::cin)
|
|
||||||
{
|
|
||||||
getline(std::cin, line);
|
|
||||||
m_data += (line + '\n');
|
|
||||||
}
|
|
||||||
this->generateChunk();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Filedat::import_string(const std::string& data)
|
|
||||||
{
|
|
||||||
this->clear();
|
|
||||||
m_data=data;
|
|
||||||
m_filePath="";
|
|
||||||
this->generateChunk();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Filedat::export_file(std::string const& path, std::string const& aligner) const
|
|
||||||
{
|
|
||||||
std::ofstream stream;
|
|
||||||
if(path=="")
|
|
||||||
stream.open(m_filePath);
|
|
||||||
else
|
|
||||||
stream.open(path);
|
|
||||||
if(!stream)
|
|
||||||
return false;
|
|
||||||
stream << this->strval(aligner);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Filedat::strval(std::string const& aligner) const
|
|
||||||
{
|
|
||||||
if(m_dataChunk == nullptr)
|
|
||||||
return "";
|
|
||||||
else
|
|
||||||
return m_dataChunk->strval(0, aligner);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Filedat::generateChunk()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if(m_dataChunk != nullptr)
|
|
||||||
delete m_dataChunk;
|
|
||||||
m_dataChunk = new Chunk(m_data.c_str(), m_data.size(), 0, this);
|
|
||||||
}
|
|
||||||
catch(format_error& e)
|
|
||||||
{
|
|
||||||
throw format_error(e.what(), m_filePath, m_data, e.where());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string _getname(const char* in, const int in_size, int* start, int* val_size, int* end)
|
|
||||||
{
|
|
||||||
int i=0;
|
|
||||||
|
|
||||||
*start = in_size; //default no value
|
|
||||||
*end = in_size; //default end
|
|
||||||
*val_size=0; //default no value
|
|
||||||
|
|
||||||
while(i<in_size)
|
|
||||||
{
|
|
||||||
if(i+1<in_size && in[i] == '/' && in[i+1] == '/')
|
|
||||||
while(i<in_size && in[i] != '\n')
|
|
||||||
i++;
|
|
||||||
|
|
||||||
if(_isRead(in[i]))
|
|
||||||
break;
|
|
||||||
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
if(i >= in_size) //ends without value
|
|
||||||
return "";
|
|
||||||
|
|
||||||
int j=i; //name start
|
|
||||||
while(i<in_size && in[i] != '=') //skip to =
|
|
||||||
i++;
|
|
||||||
if(i >= in_size) //no =
|
|
||||||
throw format_error("Tag has no value", "", std::string(in, in_size), j);
|
|
||||||
|
|
||||||
if(i == j) //nothing preceding =
|
|
||||||
throw format_error("Value has no tag", "", std::string(in, in_size), i);
|
|
||||||
|
|
||||||
int k=i-1; //name end
|
|
||||||
while( !_isRead(in[k]) )
|
|
||||||
k--;
|
|
||||||
std::string name=std::string(in+j, k-j+1);
|
|
||||||
|
|
||||||
i++;
|
|
||||||
while(i < in_size && !_isRead(in[i]))
|
|
||||||
i++;
|
|
||||||
if(i >= in_size) //no value
|
|
||||||
{
|
|
||||||
*start=i;
|
|
||||||
*val_size=0;
|
|
||||||
*end=i;
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
if(in[i] == '\"') //"" val
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
*start=i; //value starts
|
|
||||||
j=0; //size
|
|
||||||
while(i+j < in_size && in[i+j]!='\"')
|
|
||||||
{
|
|
||||||
if(in[i]+j=='\\')
|
|
||||||
j++;
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
if(i+j >= in_size) // no closing "
|
|
||||||
throw format_error("Double quote does not close", "", std::string(in, in_size), i-1);
|
|
||||||
*val_size=j;
|
|
||||||
*end=i+j+1;
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
if(in[i] == '\'') //"" val
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
*start=i; //value starts
|
|
||||||
j=0; //size
|
|
||||||
while(i+j < in_size && in[i+j]!='\'')
|
|
||||||
{
|
|
||||||
if(in[i]+j=='\\')
|
|
||||||
j++;
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
if(i+j >= in_size) // no closing '
|
|
||||||
throw format_error("Single quote does not close", "", std::string(in, in_size), i-1);
|
|
||||||
*val_size=j;
|
|
||||||
*end=i+j+1;
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
if(in[i] == '{')
|
|
||||||
{
|
|
||||||
*start=i;
|
|
||||||
j=1;
|
|
||||||
int counter=0;
|
|
||||||
while( i+j < in_size && !( counter == 0 && in[i+j]=='}') )
|
|
||||||
{
|
|
||||||
if(i+j+1<in_size && in[i+j] == '/' && in[i+j+1] == '/')
|
|
||||||
while(i+j<in_size && in[i+j] != '\n')
|
|
||||||
j++;
|
|
||||||
if(in[i+j]=='\\')
|
|
||||||
j++;
|
|
||||||
if(in[i+j]=='{')
|
|
||||||
counter++;
|
|
||||||
if(in[i+j]=='}')
|
|
||||||
counter--;
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
if(i+j >= in_size) //reached end without closing
|
|
||||||
throw format_error("Brace does not close", "", std::string(in, in_size), i);
|
|
||||||
j++;
|
|
||||||
*val_size=j;
|
|
||||||
*end=i+j;
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
if(in[i] == '[')
|
|
||||||
{
|
|
||||||
*start=i;
|
|
||||||
j=1;
|
|
||||||
int counter=0;
|
|
||||||
while( i+j < in_size && !( counter == 0 && in[i+j]==']') )
|
|
||||||
{
|
|
||||||
if(i+j+1<in_size && in[i+j] == '/' && in[i+j+1] == '/')
|
|
||||||
while(i+j<in_size && in[i+j] != '\n')
|
|
||||||
j++;
|
|
||||||
if(in[i+j]=='\\')
|
|
||||||
j++;
|
|
||||||
if(in[i+j]=='[')
|
|
||||||
counter++;
|
|
||||||
if(in[i+j]==']')
|
|
||||||
counter--;
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
if(i+j >= in_size) //reached end without closing
|
|
||||||
throw format_error("Bracket does not close", "", std::string(in, in_size), i);
|
|
||||||
j++;
|
|
||||||
*val_size=j;
|
|
||||||
*end=i+j;
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
{ // no encapsulation: go to end of line
|
|
||||||
*start=i; //value starts
|
|
||||||
j=0; //size
|
|
||||||
while(i+j < in_size && in[i+j]!='\n')
|
|
||||||
{
|
|
||||||
if(in[i]+j=='\\')
|
|
||||||
j++;
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
while( !_isRead(in[i+j]) )
|
|
||||||
j--;
|
|
||||||
*val_size=j+1;
|
|
||||||
*end=i+j+1;
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string _getlist(const char* in, const int in_size, int* start, int* end)
|
|
||||||
{
|
|
||||||
int i=0;
|
|
||||||
std::string ret;
|
|
||||||
|
|
||||||
while(i<in_size)
|
|
||||||
{
|
|
||||||
if(i+1<in_size && in[i] == '/' && in[i+1] == '/')
|
|
||||||
while(i<in_size && in[i] != '\n')
|
|
||||||
i++;
|
|
||||||
|
|
||||||
if(_isRead(in[i]))
|
|
||||||
break;
|
|
||||||
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
*start=i;
|
|
||||||
if(i >= in_size) //ends without value
|
|
||||||
{
|
|
||||||
*end = in_size;
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
if(in[i] == ',') //value is empty
|
|
||||||
{
|
|
||||||
*end=i+1;
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
int j=0;
|
|
||||||
if(in[i] == '\"') //"" val
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
j=0; //size
|
|
||||||
while(i+j < in_size && in[i+j]!='\"')
|
|
||||||
{
|
|
||||||
if(in[i]+j=='\\')
|
|
||||||
j++;
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
if(i+j >= in_size) // no closing "
|
|
||||||
throw format_error("Double quote does not close", "", std::string(in, in_size), i-1);
|
|
||||||
ret = std::string(in+i, j);
|
|
||||||
*end=i+j+1;
|
|
||||||
}
|
|
||||||
else if(in[i] == '\'') //"" val
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
j=0; //size
|
|
||||||
while(i+j < in_size && in[i+j]!='\'')
|
|
||||||
{
|
|
||||||
if(in[i]+j=='\\')
|
|
||||||
j++;
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
if(i+j >= in_size) // no closing '
|
|
||||||
throw format_error("Single quote does not close", "", std::string(in, in_size), i-1);
|
|
||||||
ret = std::string(in+i, j);
|
|
||||||
*end=i+j+1;
|
|
||||||
}
|
|
||||||
else if(in[i] == '{')
|
|
||||||
{
|
|
||||||
j=1;
|
|
||||||
int counter=0;
|
|
||||||
while( i+j < in_size && !( counter == 0 && in[i+j]=='}') )
|
|
||||||
{
|
|
||||||
if(i+j+1<in_size && in[i+j] == '/' && in[i+j+1] == '/')
|
|
||||||
while(i+j<in_size && in[i+j] != '\n')
|
|
||||||
j++;
|
|
||||||
if(in[i+j]=='\\')
|
|
||||||
j++;
|
|
||||||
if(in[i+j]=='{')
|
|
||||||
counter++;
|
|
||||||
if(in[i+j]=='}')
|
|
||||||
counter--;
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
if(i+j >= in_size) //reached end without closing
|
|
||||||
throw format_error("Brace does not close", "", std::string(in, in_size), i);
|
|
||||||
j++;
|
|
||||||
ret = std::string(in+i, j);
|
|
||||||
*end=i+j;
|
|
||||||
}
|
|
||||||
else if(in[i] == '[')
|
|
||||||
{
|
|
||||||
j=1;
|
|
||||||
int counter=0;
|
|
||||||
while( i+j < in_size && !( counter == 0 && in[i+j]==']') )
|
|
||||||
{
|
|
||||||
if(i+j+1<in_size && in[i+j] == '/' && in[i+j+1] == '/')
|
|
||||||
while(i+j<in_size && in[i+j] != '\n')
|
|
||||||
j++;
|
|
||||||
if(in[i+j]=='\\')
|
|
||||||
j++;
|
|
||||||
if(in[i+j]=='[')
|
|
||||||
counter++;
|
|
||||||
if(in[i+j]==']')
|
|
||||||
counter--;
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
if(i+j >= in_size) //reached end without closing
|
|
||||||
throw format_error("Bracket does not close", "", std::string(in, in_size), i);
|
|
||||||
j++;
|
|
||||||
ret = std::string(in+i, j);
|
|
||||||
*end=i+j;
|
|
||||||
}
|
|
||||||
else // no encapsulation: go to next ,
|
|
||||||
{
|
|
||||||
j=0; //size
|
|
||||||
while(i+j < in_size && in[i+j]!=',')
|
|
||||||
{
|
|
||||||
if(in[i+j]=='\\')
|
|
||||||
j++;
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
if(i+j < in_size)
|
|
||||||
{
|
|
||||||
while( !_isRead(in[i+j]) )
|
|
||||||
j--;
|
|
||||||
}
|
|
||||||
ret = std::string(in+i,j);
|
|
||||||
*end=i+j;
|
|
||||||
}
|
|
||||||
|
|
||||||
i = *end;
|
|
||||||
while(i < in_size && !_isRead(in[i]))
|
|
||||||
i++;
|
|
||||||
if( i>= in_size ) //last char
|
|
||||||
{
|
|
||||||
*end=i;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
else if(in[i] ==',') //comma as expected
|
|
||||||
{
|
|
||||||
*end=i+1;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
else //Unexpected char
|
|
||||||
throw format_error("Expecting comma", "", std::string(in, in_size), i);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void Chunk::set(const char* in, const int in_size, int offset, Filedat* data)
|
|
||||||
{
|
|
||||||
this->clear(); //reset everything
|
|
||||||
this->m_parent=data;
|
|
||||||
this->m_offset=offset;
|
|
||||||
|
|
||||||
int i=0;
|
|
||||||
|
|
||||||
while(i<in_size && !_isRead(in[i])) //skip unread char
|
|
||||||
i++;
|
|
||||||
|
|
||||||
if(i >= in_size) //empty: make an empty strval
|
|
||||||
{
|
|
||||||
DataVal* cv = new DataVal();
|
|
||||||
m_achunk=cv;
|
|
||||||
cv->val = "";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if( in[i] == '{')
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
int val_end=in_size-1;
|
|
||||||
while(!_isRead(in[val_end])) //skip unread char
|
|
||||||
val_end--;
|
|
||||||
if(in[val_end] != '}')
|
|
||||||
throw format_error("Expecting closing brace", "", std::string(in, in_size), val_end+1);
|
|
||||||
|
|
||||||
DataChunk* tch = new DataChunk();
|
|
||||||
m_achunk = tch;
|
|
||||||
|
|
||||||
std::string name;
|
|
||||||
std::string val;
|
|
||||||
while(i < val_end)
|
|
||||||
{
|
|
||||||
int start=0;
|
|
||||||
int _size=0;
|
|
||||||
int end=0;
|
|
||||||
|
|
||||||
while(!_isRead(in[i]))
|
|
||||||
i++;
|
|
||||||
|
|
||||||
std::string newstr=std::string(in+i, val_end-i);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
name = _getname(newstr.c_str(), newstr.size(), &start, &_size, &end);
|
|
||||||
val = newstr.substr(start, _size);
|
|
||||||
}
|
|
||||||
catch(format_error& e)
|
|
||||||
{
|
|
||||||
throw format_error(e.what(), "", std::string(in, in_size), e.where()+i);
|
|
||||||
}
|
|
||||||
|
|
||||||
if( name == "" ) //no more values
|
|
||||||
break;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Chunk* chk = new Chunk(val.c_str(),val.size(), offset + start+i, m_parent);
|
|
||||||
if(!tch->values.insert( std::make_pair(name, chk ) ).second)
|
|
||||||
{
|
|
||||||
delete chk;
|
|
||||||
throw format_error("Key '" + name + "' already present", "", std::string(in, in_size), 0 - start );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(format_error& e)
|
|
||||||
{
|
|
||||||
throw format_error(e.what(), "", std::string(in, in_size), e.where() + start + i );
|
|
||||||
}
|
|
||||||
|
|
||||||
i += end;
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
else if( in[i] == '[')
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
int val_end=in_size-1;
|
|
||||||
while(!_isRead(in[val_end])) //skip unread char
|
|
||||||
val_end--;
|
|
||||||
if(in[val_end] != ']')
|
|
||||||
throw format_error("Expecting closing bracket", "", std::string(in, in_size), val_end+1);
|
|
||||||
|
|
||||||
ChunkList* tch = new ChunkList();
|
|
||||||
m_achunk = tch;
|
|
||||||
|
|
||||||
int end=0,start=0;
|
|
||||||
while( i < val_end )
|
|
||||||
{
|
|
||||||
std::string val;
|
|
||||||
std::string newstr=std::string(in+i, val_end-i);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
val = _getlist(newstr.c_str(), newstr.size(), &start, &end);
|
|
||||||
}
|
|
||||||
catch(format_error& e)
|
|
||||||
{
|
|
||||||
throw format_error(e.what(), "", std::string(in, in_size), e.where()+i);
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
tch->list.push_back(new Chunk(val.c_str(),val.size(), offset + start+i, m_parent) );
|
|
||||||
}
|
|
||||||
catch(format_error& e)
|
|
||||||
{
|
|
||||||
throw format_error(e.what(), "", std::string(in, in_size), e.where() + start + i );
|
|
||||||
}
|
|
||||||
|
|
||||||
i+=end;
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
else // string value
|
|
||||||
{
|
|
||||||
int val_end=in_size;
|
|
||||||
val_end--;
|
|
||||||
while(!_isRead(in[val_end])) //skip unread char
|
|
||||||
val_end--;
|
|
||||||
|
|
||||||
DataVal* tch = new DataVal();
|
|
||||||
m_achunk = tch;
|
|
||||||
|
|
||||||
tch->val = std::string(in+i,val_end-i+1);
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Chunk::addToChunk(std::string const& name, Chunk const& val)
|
|
||||||
{
|
|
||||||
if(this->type()==AbstractChunk::chunk)
|
|
||||||
{
|
|
||||||
DataChunk* cp = dynamic_cast<DataChunk*>(m_achunk);
|
|
||||||
Chunk* chk = new Chunk(val);
|
|
||||||
if( !cp->values.insert( std::make_pair(name,chk) ).second )
|
|
||||||
{
|
|
||||||
delete chk;
|
|
||||||
throw format_error("Key '" + name + "' already present", "", this->strval(), -1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(this->type() == AbstractChunk::none)
|
|
||||||
{
|
|
||||||
DataChunk* cp = new DataChunk();
|
|
||||||
m_achunk=cp;
|
|
||||||
cp->values.insert(std::make_pair(name , new Chunk(val)));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw format_error("Cannot add keys to non-map chunks", "", this->strval(), -1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Chunk::addToChunk(std::vector<std::pair<std::string, Chunk>> const& vec)
|
|
||||||
{
|
|
||||||
for(auto it : vec)
|
|
||||||
this->addToChunk(it.first, it.second);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Chunk::addToList(Chunk const& val)
|
|
||||||
{
|
|
||||||
if(this->type()==AbstractChunk::list)
|
|
||||||
{
|
|
||||||
ChunkList* lp = dynamic_cast<ChunkList*>(m_achunk);
|
|
||||||
lp->list.push_back(new Chunk(val));
|
|
||||||
}
|
|
||||||
else if(this->type() == AbstractChunk::none)
|
|
||||||
{
|
|
||||||
ChunkList* lp = new ChunkList();
|
|
||||||
m_achunk=lp;
|
|
||||||
lp->list.push_back(new Chunk(val));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw format_error("Cannot add elements to non-list chunks", "", this->strval(), -1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Chunk::addToList(std::vector<Chunk> const& vec)
|
|
||||||
{
|
|
||||||
for(auto it : vec)
|
|
||||||
this->addToList(it);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Chunk::strval(unsigned int alignment, std::string const& aligner) const
|
|
||||||
{
|
|
||||||
if(this->type()==AbstractChunk::val)
|
|
||||||
{
|
|
||||||
DataVal* vp = dynamic_cast<DataVal*>(m_achunk);
|
|
||||||
return vp->val;
|
|
||||||
}
|
|
||||||
else if(this->type()==AbstractChunk::chunk)
|
|
||||||
{
|
|
||||||
DataChunk* cp = dynamic_cast<DataChunk*>(m_achunk);
|
|
||||||
std::string ret="{\n";
|
|
||||||
for(auto it : cp->values)
|
|
||||||
{
|
|
||||||
ret += _repeatString(aligner,alignment+1);
|
|
||||||
ret += it.first;
|
|
||||||
ret += '=';
|
|
||||||
if(it.second!=nullptr)
|
|
||||||
ret += it.second->strval(alignment+1, aligner);
|
|
||||||
ret += '\n';
|
|
||||||
}
|
|
||||||
ret += _repeatString(aligner, alignment);
|
|
||||||
ret += '}';
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
else if(this->type()==AbstractChunk::list)
|
|
||||||
{
|
|
||||||
ChunkList* lp = dynamic_cast<ChunkList*>(m_achunk);
|
|
||||||
std::string ret="[\n";
|
|
||||||
for(auto it : lp->list)
|
|
||||||
{
|
|
||||||
ret += _repeatString(aligner, alignment+1);
|
|
||||||
if(it!=nullptr)
|
|
||||||
ret += it->strval(alignment+1, aligner);
|
|
||||||
ret += ",\n";
|
|
||||||
}
|
|
||||||
ret.erase(ret.end()-2);
|
|
||||||
ret += _repeatString(aligner, alignment);
|
|
||||||
ret += ']';
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
int Chunk::listSize() const
|
|
||||||
{
|
|
||||||
if(this->type() != AbstractChunk::list)
|
|
||||||
return -1;
|
|
||||||
ChunkList* cl = dynamic_cast<ChunkList*>(m_achunk);
|
|
||||||
return cl->list.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
Chunk* Chunk::subChunkPtr(std::string const& in) const
|
|
||||||
{
|
|
||||||
if(this->type()==AbstractChunk::chunk)
|
|
||||||
{
|
|
||||||
DataChunk* dc = dynamic_cast<DataChunk*>(m_achunk);
|
|
||||||
auto fi = dc->values.find(in);
|
|
||||||
if(fi == dc->values.end()) //none found
|
|
||||||
return nullptr;
|
|
||||||
return fi->second;
|
|
||||||
}
|
|
||||||
else //not a chunk
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Chunk* Chunk::subChunkPtr(unsigned int a) const
|
|
||||||
{
|
|
||||||
if(this->type()==AbstractChunk::list)
|
|
||||||
{
|
|
||||||
ChunkList* cl = dynamic_cast<ChunkList*>(m_achunk);
|
|
||||||
if(a >= cl->list.size()) //outside of range
|
|
||||||
return nullptr;
|
|
||||||
return cl->list[a];
|
|
||||||
}
|
|
||||||
else //not a list
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Chunk& Chunk::subChunkRef(std::string const& in) const
|
|
||||||
{
|
|
||||||
if(this->type()!=AbstractChunk::chunk)
|
|
||||||
{
|
|
||||||
if(m_parent != nullptr)
|
|
||||||
{
|
|
||||||
throw format_error("Chunk isn't a map", m_parent->filePath(), m_parent->stringdata(), m_offset );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw format_error("Chunk isn't a map", "", this->strval(), -1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DataChunk* dc = dynamic_cast<DataChunk*>(m_achunk);
|
|
||||||
auto fi = dc->values.find(in);
|
|
||||||
if(fi == dc->values.end())
|
|
||||||
{
|
|
||||||
if(m_parent != nullptr)
|
|
||||||
{
|
|
||||||
throw format_error("Map doesn't have '" + in + "' flag", m_parent->filePath(), m_parent->stringdata(), m_offset );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw format_error("Map doesn't have '" + in + "' flag", "", this->strval(), -1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return *fi->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
Chunk& Chunk::subChunkRef(unsigned int a) const
|
|
||||||
{
|
|
||||||
if(this->type()!=AbstractChunk::list)
|
|
||||||
{
|
|
||||||
if(m_parent != nullptr)
|
|
||||||
{
|
|
||||||
throw format_error("Chunk isn't a list", m_parent->filePath(), m_parent->stringdata(), m_offset );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw format_error("Chunk isn't a list", "", this->strval(), -1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ChunkList* cl = dynamic_cast<ChunkList*>(m_achunk);
|
|
||||||
if(a >= cl->list.size())
|
|
||||||
{
|
|
||||||
if(m_parent != nullptr)
|
|
||||||
{
|
|
||||||
throw format_error("List size is below " + std::to_string(a), m_parent->filePath(), m_parent->stringdata(), m_offset );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw format_error("List size is below " + std::to_string(a), "", this->strval(), -1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return *cl->list[a];
|
|
||||||
}
|
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream& stream, Chunk const& a)
|
|
||||||
{
|
|
||||||
stream << a.strval();
|
|
||||||
return stream;
|
|
||||||
}
|
|
||||||
|
|
||||||
DataChunk::~DataChunk()
|
|
||||||
{
|
|
||||||
for(auto it : values)
|
|
||||||
{
|
|
||||||
if(it.second != nullptr)
|
|
||||||
delete it.second;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ChunkList::~ChunkList()
|
|
||||||
{
|
|
||||||
for(auto it : list)
|
|
||||||
{
|
|
||||||
if(it!=nullptr)
|
|
||||||
delete it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -3,11 +3,11 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <ztd/shell.hpp>
|
||||||
|
|
||||||
#include "log.hpp"
|
#include "log.hpp"
|
||||||
#include "popen.h"
|
|
||||||
|
|
||||||
std::vector<Device*> device_list;
|
std::vector<Device*> device_list;
|
||||||
|
|
||||||
|
|
@ -44,9 +44,9 @@ bool Device::start_loop()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<int32_t,int32_t> importRange(Chunk const& ch, std::string const& tag, int32_t low, int32_t high)
|
std::pair<int32_t,int32_t> importRange(ztd::chunkdat const& ch, std::string const& tag, int32_t low, int32_t high)
|
||||||
{
|
{
|
||||||
Chunk* pch=ch.subChunkPtr(tag);
|
ztd::chunkdat* pch=ch.subChunkPtr(tag);
|
||||||
if(pch != nullptr)
|
if(pch != nullptr)
|
||||||
{
|
{
|
||||||
std::string str=pch->strval();
|
std::string str=pch->strval();
|
||||||
|
|
@ -70,9 +70,9 @@ std::pair<int32_t,int32_t> importRange(Chunk const& ch, std::string const& tag,
|
||||||
return std::make_pair(low, high);
|
return std::make_pair(low, high);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<float,float> importRangeFloat(Chunk const& ch, std::string const& tag, float low, float high)
|
std::pair<float,float> importRangeFloat(ztd::chunkdat const& ch, std::string const& tag, float low, float high)
|
||||||
{
|
{
|
||||||
Chunk* pch=ch.subChunkPtr(tag);
|
ztd::chunkdat* pch=ch.subChunkPtr(tag);
|
||||||
if(pch != nullptr)
|
if(pch != nullptr)
|
||||||
{
|
{
|
||||||
std::string str=pch->strval();
|
std::string str=pch->strval();
|
||||||
|
|
@ -94,9 +94,9 @@ std::pair<float,float> importRangeFloat(Chunk const& ch, std::string const& tag,
|
||||||
return std::make_pair(low, high);
|
return std::make_pair(low, high);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool importBool(Chunk const& ch, std::string const& tag, bool defbool)
|
bool importBool(ztd::chunkdat const& ch, std::string const& tag, bool defbool)
|
||||||
{
|
{
|
||||||
Chunk* pch=ch.subChunkPtr(tag);
|
ztd::chunkdat* pch=ch.subChunkPtr(tag);
|
||||||
if(pch != nullptr)
|
if(pch != nullptr)
|
||||||
{
|
{
|
||||||
std::string str=pch->strval();
|
std::string str=pch->strval();
|
||||||
|
|
@ -108,13 +108,13 @@ bool importBool(Chunk const& ch, std::string const& tag, bool defbool)
|
||||||
return defbool;
|
return defbool;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Device::import_chunk(Chunk const& ch)
|
bool Device::import_chunk(ztd::chunkdat const& ch)
|
||||||
{
|
{
|
||||||
Chunk& cch = ch["commands"];
|
ztd::chunkdat& cch = ch["commands"];
|
||||||
this->name=ch["name"].strval();
|
this->name=ch["name"].strval();
|
||||||
for(int i=0 ; i<cch.listSize() ; i++)
|
for(int i=0 ; i<cch.listSize() ; i++)
|
||||||
{
|
{
|
||||||
Chunk& tch=cch[i];
|
ztd::chunkdat& tch=cch[i];
|
||||||
std::string tstr=tch["type"].strval();
|
std::string tstr=tch["type"].strval();
|
||||||
if(tstr == "system") //type system
|
if(tstr == "system") //type system
|
||||||
{
|
{
|
||||||
|
|
@ -417,7 +417,7 @@ void Device::loop(Device* dev)
|
||||||
char* buff = NULL;
|
char* buff = NULL;
|
||||||
size_t buff_size = 0;
|
size_t buff_size = 0;
|
||||||
std::string command = "aseqdump -p '" + std::to_string(dev->client_id) + '\'';
|
std::string command = "aseqdump -p '" + std::to_string(dev->client_id) + '\'';
|
||||||
FILE *stream = popen2(command.c_str(), "r", &dev->thread_pid);
|
FILE *stream = ztd::popen2(command.c_str(), "r", &dev->thread_pid);
|
||||||
|
|
||||||
log("Device '" + dev->name + "' connected\n");
|
log("Device '" + dev->name + "' connected\n");
|
||||||
|
|
||||||
|
|
@ -438,7 +438,7 @@ void Device::loop(Device* dev)
|
||||||
|
|
||||||
log("Device '" + dev->name + "' disconnected\n");
|
log("Device '" + dev->name + "' disconnected\n");
|
||||||
|
|
||||||
pclose2(stream, dev->thread_pid);
|
ztd::pclose2(stream, dev->thread_pid);
|
||||||
dev->thread_pid=-1;
|
dev->thread_pid=-1;
|
||||||
free(buff);
|
free(buff);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
77
src/main.cpp
77
src/main.cpp
|
|
@ -8,17 +8,16 @@
|
||||||
#include "log.hpp"
|
#include "log.hpp"
|
||||||
#include "help.h"
|
#include "help.h"
|
||||||
|
|
||||||
#include "Filedat.hpp"
|
#include <ztd/filedat.hpp>
|
||||||
#include "options.hpp"
|
#include <ztd/options.hpp>
|
||||||
#include "popen.h"
|
#include <ztd/shell.hpp>
|
||||||
|
|
||||||
|
ztd::option_set options;
|
||||||
OptionSet options;
|
|
||||||
|
|
||||||
void help()
|
void help()
|
||||||
{
|
{
|
||||||
printf("zmidimap [options] <midimap file>\n\nOptions:\n");
|
printf("zmidimap [options] <midimap file>\n\nOptions:\n");
|
||||||
options.printHelp(2, 25);
|
options.print_help(2, 25);
|
||||||
printf("\nSee --file-format --command-tags --shell-format options for details on map file format\n");
|
printf("\nSee --file-format --command-tags --shell-format options for details on map file format\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -26,7 +25,7 @@ void option_p(const std::string& port)
|
||||||
{
|
{
|
||||||
std::string command="aseqdump -p '" + port + '\'';
|
std::string command="aseqdump -p '" + port + '\'';
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
FILE *stream = popen2(command.c_str(), "r", &pid);
|
FILE *stream = ztd::popen2(command.c_str(), "r", &pid);
|
||||||
char* buff = NULL;
|
char* buff = NULL;
|
||||||
size_t buff_size = 0;
|
size_t buff_size = 0;
|
||||||
while (getline(&buff, &buff_size, stream) > 0)
|
while (getline(&buff, &buff_size, stream) > 0)
|
||||||
|
|
@ -38,7 +37,7 @@ void option_p(const std::string& port)
|
||||||
else
|
else
|
||||||
printf("%s", buff);
|
printf("%s", buff);
|
||||||
}
|
}
|
||||||
pclose2(stream, pid);
|
ztd::pclose2(stream, pid);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cleanup()
|
void cleanup()
|
||||||
|
|
@ -68,68 +67,72 @@ int main(int argc, char* argv[])
|
||||||
if (!isatty(fileno(stdin)))
|
if (!isatty(fileno(stdin)))
|
||||||
piped = true;
|
piped = true;
|
||||||
|
|
||||||
options.addOption(Option('h',"help", false, "Display this help message"));
|
options.add(ztd::option('h',"help", false, "Display this help message"));
|
||||||
options.addOption(Option("file-format", false, "Display file format help"));
|
options.add(ztd::option("file-format", false, "Display file format help"));
|
||||||
options.addOption(Option("command-tags", false, "Display for command tag help"));
|
options.add(ztd::option("command-tags", false, "Display for command tag help"));
|
||||||
options.addOption(Option("shell-format", false, "Display for shell format help"));
|
options.add(ztd::option("shell-format", false, "Display for shell format help"));
|
||||||
options.addOption(Option('l',"list", false, "List detected devices"));
|
options.add(ztd::option('l',"list", false, "List detected devices"));
|
||||||
options.addOption(Option('L',"full-list", false, "Print whole device list details"));
|
options.add(ztd::option('L',"full-list", false, "Print whole device list details"));
|
||||||
options.addOption(Option('p',"port", true, "Connect to device and output to console", "device"));
|
options.add(ztd::option('p',"port", true, "Connect to device and output to console", "device"));
|
||||||
options.addOption(Option("no-log", false, "Disable console logging"));
|
options.add(ztd::option("no-log", false, "Disable console logging"));
|
||||||
// options.addOption(Option('i',"interactive", false, "Start in interactive mode"));
|
// options.add(ztd::option('i',"interactive", false, "Start in interactive mode"));
|
||||||
|
|
||||||
auto argvec = argVector(argc, argv);
|
std::vector<std::string> arg;
|
||||||
|
try
|
||||||
auto t = options.getOptions(argvec);
|
{
|
||||||
std::vector<std::string> arg=t.first;
|
arg = options.process(argc, argv);
|
||||||
if( !t.second ) //invalid option
|
}
|
||||||
return 1;
|
catch(ztd::option_error& err)
|
||||||
|
{
|
||||||
|
printf("Option error: %s\n", err.what());
|
||||||
|
stop(1);
|
||||||
|
}
|
||||||
|
|
||||||
//exit options
|
//exit options
|
||||||
Option* op=nullptr;
|
ztd::option* op=nullptr;
|
||||||
op = options.findOption('h');
|
op = options.find('h');
|
||||||
if( op->activated )
|
if( op->activated )
|
||||||
{
|
{
|
||||||
help();
|
help();
|
||||||
stop(0);
|
stop(0);
|
||||||
}
|
}
|
||||||
op = options.findOption("file-format");
|
op = options.find("file-format");
|
||||||
if( op->activated )
|
if( op->activated )
|
||||||
{
|
{
|
||||||
printf("%s\n", FILE_FORMAT);
|
printf("%s\n", FILE_FORMAT);
|
||||||
stop(0);
|
stop(0);
|
||||||
}
|
}
|
||||||
op = options.findOption("command-tags");
|
op = options.find("command-tags");
|
||||||
if( op->activated )
|
if( op->activated )
|
||||||
{
|
{
|
||||||
printf("%s\n", COMMAND_TAGS);
|
printf("%s\n", COMMAND_TAGS);
|
||||||
stop(0);
|
stop(0);
|
||||||
}
|
}
|
||||||
op = options.findOption("shell-format");
|
op = options.find("shell-format");
|
||||||
if( op->activated )
|
if( op->activated )
|
||||||
{
|
{
|
||||||
printf("%s\n", SHELL_FORMAT);
|
printf("%s\n", SHELL_FORMAT);
|
||||||
stop(0);
|
stop(0);
|
||||||
}
|
}
|
||||||
op = options.findOption('h');
|
op = options.find('h');
|
||||||
if( op->activated )
|
if( op->activated )
|
||||||
{
|
{
|
||||||
help();
|
help();
|
||||||
stop(0);
|
stop(0);
|
||||||
}
|
}
|
||||||
op = options.findOption('L');
|
op = options.find('L');
|
||||||
if( op->activated )
|
if( op->activated )
|
||||||
{
|
{
|
||||||
sh("aseqdump -l");
|
sh("aseqdump -l");
|
||||||
stop(0);
|
stop(0);
|
||||||
}
|
}
|
||||||
op = options.findOption('l');
|
op = options.find('l');
|
||||||
if( op->activated )
|
if( op->activated )
|
||||||
{
|
{
|
||||||
sh(LIST_COMMAND);
|
sh(LIST_COMMAND);
|
||||||
stop(0);
|
stop(0);
|
||||||
}
|
}
|
||||||
op = options.findOption('p');
|
op = options.find('p');
|
||||||
if( op->activated )
|
if( op->activated )
|
||||||
{
|
{
|
||||||
option_p(op->argument);
|
option_p(op->argument);
|
||||||
|
|
@ -137,14 +140,14 @@ int main(int argc, char* argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
//behavioral options
|
//behavioral options
|
||||||
op = options.findOption("no-log");
|
op = options.find("no-log");
|
||||||
if( op->activated )
|
if( op->activated )
|
||||||
{
|
{
|
||||||
log_on=false;
|
log_on=false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//no argument: display help
|
//no argument: display help
|
||||||
Filedat file;
|
ztd::filedat file;
|
||||||
bool no_arg=false;
|
bool no_arg=false;
|
||||||
if (arg.size() <= 0 || arg[0] == "")
|
if (arg.size() <= 0 || arg[0] == "")
|
||||||
{
|
{
|
||||||
|
|
@ -176,7 +179,7 @@ int main(int argc, char* argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
//create commands
|
//create commands
|
||||||
for(int i=0 ; i<file.chunk().listSize() ; i++)
|
for(int i=0 ; i<file.data().listSize() ; i++)
|
||||||
{
|
{
|
||||||
Device *newDevice = new Device;
|
Device *newDevice = new Device;
|
||||||
newDevice->import_chunk(file[i]);
|
newDevice->import_chunk(file[i]);
|
||||||
|
|
@ -188,9 +191,9 @@ int main(int argc, char* argv[])
|
||||||
log("Starting scan for devices\n");
|
log("Starting scan for devices\n");
|
||||||
announce_loop();
|
announce_loop();
|
||||||
}
|
}
|
||||||
catch (format_error& e)
|
catch (ztd::format_error& e)
|
||||||
{
|
{
|
||||||
printFormatException(e);
|
ztd::printFormatException(e);
|
||||||
cleanup();
|
cleanup();
|
||||||
stop(11);
|
stop(11);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
235
src/options.cpp
235
src/options.cpp
|
|
@ -1,235 +0,0 @@
|
||||||
#include "options.hpp"
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
std::vector<std::string> argVector(int argc, char** argv)
|
|
||||||
{
|
|
||||||
std::vector<std::string> out;
|
|
||||||
for(int i=1;i<argc; i++)
|
|
||||||
{
|
|
||||||
out.push_back(std::string(argv[i]));
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
Option::Option()
|
|
||||||
{
|
|
||||||
shortDef=false;
|
|
||||||
longDef=false;
|
|
||||||
takesArgument=false;
|
|
||||||
activated=false;
|
|
||||||
charName=0;
|
|
||||||
}
|
|
||||||
Option::~Option()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Option::Option(char c, bool arg, std::string helptext, std::string argname)
|
|
||||||
{
|
|
||||||
shortDef=true;
|
|
||||||
longDef=false;
|
|
||||||
takesArgument=arg;
|
|
||||||
activated=false;
|
|
||||||
charName=c;
|
|
||||||
arg_name=argname;
|
|
||||||
help_text=helptext;
|
|
||||||
}
|
|
||||||
|
|
||||||
Option::Option(std::string const& str, bool arg, std::string helptext, std::string argname)
|
|
||||||
{
|
|
||||||
shortDef=false;
|
|
||||||
longDef=true;
|
|
||||||
takesArgument=arg;
|
|
||||||
activated=false;
|
|
||||||
charName=0;
|
|
||||||
strName=str;
|
|
||||||
arg_name=argname;
|
|
||||||
help_text=helptext;
|
|
||||||
}
|
|
||||||
Option::Option(char c, std::string const& str, bool arg, std::string helptext, std::string argname)
|
|
||||||
{
|
|
||||||
shortDef=true;
|
|
||||||
longDef=true;
|
|
||||||
takesArgument=arg;
|
|
||||||
activated=false;
|
|
||||||
charName=c;
|
|
||||||
strName=str;
|
|
||||||
arg_name=argname;
|
|
||||||
help_text=helptext;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Option::printHelp(int leftpad, int rightpad)
|
|
||||||
{
|
|
||||||
//prepadding
|
|
||||||
printf("%*s", -1*leftpad, "");
|
|
||||||
|
|
||||||
//short def
|
|
||||||
if(this->shortDef)
|
|
||||||
{
|
|
||||||
printf("-%c ", this->charName);
|
|
||||||
rightpad -= 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
//longdef
|
|
||||||
if(this->longDef)
|
|
||||||
{
|
|
||||||
printf("--%s ", this->strName.c_str());
|
|
||||||
rightpad -= 3 + this->strName.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
//argument
|
|
||||||
if(this->takesArgument)
|
|
||||||
{
|
|
||||||
printf(" <%s>", arg_name.c_str());
|
|
||||||
rightpad -= arg_name.size() + 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("%*s%s", -1*rightpad, "", help_text.c_str());
|
|
||||||
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void OptionSet::printHelp(int leftpad, int rightpad)
|
|
||||||
{
|
|
||||||
for(auto it : this->m_options)
|
|
||||||
{
|
|
||||||
it.printHelp(leftpad,rightpad);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
OptionSet::OptionSet()
|
|
||||||
{
|
|
||||||
errStream = &(std::cerr);
|
|
||||||
}
|
|
||||||
|
|
||||||
OptionSet::~OptionSet()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Option* OptionSet::findOption(char c)
|
|
||||||
{
|
|
||||||
for( auto it=m_options.begin() ; it!=m_options.end() ; it++ )
|
|
||||||
{
|
|
||||||
if((*it).shortDef && (*it).charName == c)
|
|
||||||
return &(*it);
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
Option* OptionSet::findOption(std::string const& str)
|
|
||||||
{
|
|
||||||
for( auto it=m_options.begin() ; it!=m_options.end() ; it++ )
|
|
||||||
{
|
|
||||||
if((*it).longDef && (*it).strName == str)
|
|
||||||
return &(*it);
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::pair<std::vector<std::string>, bool> OptionSet::getOptions(std::vector<std::string> input)
|
|
||||||
{
|
|
||||||
std::vector<std::string> out;
|
|
||||||
unsigned int i=0;
|
|
||||||
for( auto it = input.begin(); it!=input.end() ; it++ )
|
|
||||||
{
|
|
||||||
if( (*it).size()>0 && (*it)[0]=='-' )
|
|
||||||
{
|
|
||||||
if((*it).size()>1 && (*it)[1]=='-')
|
|
||||||
{
|
|
||||||
std::size_t eqn=(*it).find('=');
|
|
||||||
if(eqn == std::string::npos)
|
|
||||||
{
|
|
||||||
Option* popt = this->findOption( (*it).substr( 2,(*it).size()-2) );
|
|
||||||
if(popt == nullptr)
|
|
||||||
{
|
|
||||||
(*errStream) << "Unknown option: " << (*it).substr(0,eqn) << std::endl;
|
|
||||||
return std::make_pair(out, false);
|
|
||||||
}
|
|
||||||
if(popt->takesArgument)
|
|
||||||
{
|
|
||||||
if( ++it == input.end() ) //finishes here
|
|
||||||
{
|
|
||||||
(*errStream) << "No argument given to option --" << popt->strName << std::endl;
|
|
||||||
return std::make_pair(out, false);
|
|
||||||
}
|
|
||||||
popt->activated = true;
|
|
||||||
popt->argument = (*it);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
popt->activated = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Option* popt = this->findOption( (*it).substr(2,eqn-2) );
|
|
||||||
if(popt == nullptr)
|
|
||||||
{
|
|
||||||
(*errStream) << "Unknown option: " << (*it).substr(2,eqn-2) << std::endl;
|
|
||||||
return std::make_pair(out, false);
|
|
||||||
}
|
|
||||||
if(!popt->takesArgument)
|
|
||||||
{
|
|
||||||
(*errStream) << "Option " << popt->strName << " doesn't take an argument" << std::endl;
|
|
||||||
return std::make_pair(out, false);
|
|
||||||
}
|
|
||||||
popt->argument = (*it).substr(eqn+1,(*it).size()-eqn-1 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
i=1;
|
|
||||||
Option* popt=nullptr;
|
|
||||||
bool tstop=false;
|
|
||||||
while( !tstop && it!=input.end() && (*it).size()>i )
|
|
||||||
{
|
|
||||||
popt=this->findOption((*it)[i]);
|
|
||||||
if(popt==nullptr) //not found: error
|
|
||||||
{
|
|
||||||
(*errStream) << "Unknown option: -" << (*it)[i] << std::endl;
|
|
||||||
return std::make_pair(out, false);
|
|
||||||
}
|
|
||||||
if(popt->takesArgument) //no argument
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
if((*it).size()<=i) //finishes here
|
|
||||||
{
|
|
||||||
if( ++it == input.end() )
|
|
||||||
{
|
|
||||||
(*errStream) << "No argument given to option -" << popt->charName << std::endl;
|
|
||||||
return std::make_pair(out, false);
|
|
||||||
}
|
|
||||||
popt->activated = true;
|
|
||||||
popt->argument = (*it);
|
|
||||||
tstop = true;
|
|
||||||
}
|
|
||||||
else //continue
|
|
||||||
{
|
|
||||||
if( (*it)[i] != '=') //incorrect
|
|
||||||
{
|
|
||||||
(*errStream) << "No argument given to option -" << popt->charName << std::endl;
|
|
||||||
return std::make_pair(out, false);
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
popt->argument = (*it).substr(i , (*it).size()-i );
|
|
||||||
popt->activated = true;
|
|
||||||
tstop=true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else //no argument
|
|
||||||
{
|
|
||||||
popt->activated = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
out.push_back(*it);
|
|
||||||
}
|
|
||||||
if(it == input.end())
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return std::make_pair(out, true);
|
|
||||||
}
|
|
||||||
80
src/popen.c
80
src/popen.c
|
|
@ -1,80 +0,0 @@
|
||||||
#include "popen.h"
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <strings.h>
|
|
||||||
#include <sys/wait.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#define READ 0
|
|
||||||
#define WRITE 1
|
|
||||||
|
|
||||||
FILE* popen2(const char* command, const char* type, int* pid)
|
|
||||||
{
|
|
||||||
pid_t child_pid;
|
|
||||||
int fd[2];
|
|
||||||
pipe(fd);
|
|
||||||
|
|
||||||
if((child_pid = fork()) == -1)
|
|
||||||
{
|
|
||||||
perror("fork");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* child process */
|
|
||||||
if (child_pid == 0)
|
|
||||||
{
|
|
||||||
if ( index(type, 'r') != NULL )
|
|
||||||
{
|
|
||||||
close(fd[READ]); //Close the READ end of the pipe since the child's fd is write-only
|
|
||||||
dup2(fd[WRITE], 1); //Redirect stdout to pipe
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
close(fd[WRITE]); //Close the WRITE end of the pipe since the child's fd is read-only
|
|
||||||
dup2(fd[READ], 0); //Redirect stdin to pipe
|
|
||||||
}
|
|
||||||
|
|
||||||
setpgid(child_pid, child_pid); //Needed so negative PIDs can kill children of /bin/sh
|
|
||||||
execl("/bin/sh", "/bin/sh", "-c", command, NULL);
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if ( index(type, 'r') != NULL )
|
|
||||||
{
|
|
||||||
close(fd[WRITE]); //Close the WRITE end of the pipe since parent's fd is read-only
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
close(fd[READ]); //Close the READ end of the pipe since parent's fd is write-only
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(pid != NULL)
|
|
||||||
*pid = child_pid;
|
|
||||||
|
|
||||||
if ( index(type, 'r') != NULL )
|
|
||||||
{
|
|
||||||
return fdopen(fd[READ], "r");
|
|
||||||
}
|
|
||||||
|
|
||||||
return fdopen(fd[WRITE], "w");
|
|
||||||
}
|
|
||||||
|
|
||||||
int pclose2(FILE* fp, pid_t pid)
|
|
||||||
{
|
|
||||||
int stat;
|
|
||||||
|
|
||||||
fclose(fp);
|
|
||||||
while (waitpid(pid, &stat, 0) == -1)
|
|
||||||
{
|
|
||||||
if (errno != EINTR)
|
|
||||||
{
|
|
||||||
stat = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return stat;
|
|
||||||
}
|
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
#include "system.hpp"
|
#include "system.hpp"
|
||||||
|
|
||||||
#include "device.hpp"
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
@ -9,7 +7,11 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
pid_t announce_thread_pid = 0;
|
#include <ztd/shell.hpp>
|
||||||
|
|
||||||
|
#include "device.hpp"
|
||||||
|
|
||||||
|
int announce_thread_pid = 0;
|
||||||
|
|
||||||
void device_check()
|
void device_check()
|
||||||
{
|
{
|
||||||
|
|
@ -65,7 +67,7 @@ void announce_loop()
|
||||||
{
|
{
|
||||||
char* buff = NULL;
|
char* buff = NULL;
|
||||||
size_t buff_size = 0;
|
size_t buff_size = 0;
|
||||||
FILE* stream = popen2(ANNOUNCE_COMMAND, "r", &announce_thread_pid);
|
FILE* stream = ztd::popen2(ANNOUNCE_COMMAND, "r", &announce_thread_pid);
|
||||||
|
|
||||||
if (stream == NULL)
|
if (stream == NULL)
|
||||||
{
|
{
|
||||||
|
|
@ -79,7 +81,7 @@ void announce_loop()
|
||||||
device_check();
|
device_check();
|
||||||
}
|
}
|
||||||
|
|
||||||
pclose2(stream, announce_thread_pid);
|
ztd::pclose2(stream, announce_thread_pid);
|
||||||
|
|
||||||
if(buff != NULL)
|
if(buff != NULL)
|
||||||
free(buff);
|
free(buff);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue