Compare commits
36 Commits
template_c
...
master
29 changed files with 2730 additions and 2983 deletions
@ -0,0 +1,34 @@ |
|||||||
|
#!/bin/bash |
||||||
|
|
||||||
|
MAKEMAP="${1:-/tmp/save/build/src/makemap}" |
||||||
|
TPATH=tests |
||||||
|
|
||||||
|
SCRW=`tput cols` |
||||||
|
|
||||||
|
set -o pipefail |
||||||
|
|
||||||
|
for n in "$TPATH"/*; do |
||||||
|
status=`cat $n|grep "# Status: "|sed "s/# Status: //"` |
||||||
|
desc=`cat $n|grep "# Description: "|sed "s/# Description: //"` |
||||||
|
hash=`cat $n|grep "# Output hash: "|sed "s/.*: //"` |
||||||
|
while [ ${#desc} -lt $((SCRW-5)) ]; do desc+=" "; done |
||||||
|
echo -n "$desc" |
||||||
|
t=`mktemp` |
||||||
|
grep -v -E "# .*: " "$n">$t |
||||||
|
thash=`$MAKEMAP "$t" 2>&1 | sha256sum|sed "s/ .*//"` |
||||||
|
ret=$? |
||||||
|
if [ "$status" == "ok" ]; then |
||||||
|
if [ "$hash" == "$thash" -a "$ret" == "0" ]; then |
||||||
|
echo -e "\033[32mOk \033[0m" |
||||||
|
else |
||||||
|
echo -e "\033[31mFail\033[0m" |
||||||
|
fi |
||||||
|
else |
||||||
|
if [ "$hash" == "$thash" -a "$ret" != "0" ]; then |
||||||
|
echo -e "\033[32mOk \033[0m" |
||||||
|
else |
||||||
|
echo -e "\033[31mFail\033[0m" |
||||||
|
fi |
||||||
|
fi |
||||||
|
rm $t |
||||||
|
done |
@ -0,0 +1,34 @@ |
|||||||
|
#!/bin/bash |
||||||
|
|
||||||
|
name="$1" |
||||||
|
desc="$2" |
||||||
|
TLOC="${3:-/tmp/save/test}" |
||||||
|
MAKEMAP="${4:-/tmp/save/build/src/makemap}" |
||||||
|
|
||||||
|
if [ -f tests/"$name" ]; then |
||||||
|
echo "Test $name already exist." |
||||||
|
exit 1 |
||||||
|
fi |
||||||
|
|
||||||
|
if [ ! -f "$TLOC" ]; then |
||||||
|
echo "Configuration file $TLOC not found." |
||||||
|
exit 2 |
||||||
|
fi |
||||||
|
|
||||||
|
if [ ! -x "$MAKEMAP" ]; then |
||||||
|
echo "Can't exec file $MAKEMAP." |
||||||
|
exit 3 |
||||||
|
fi |
||||||
|
|
||||||
|
echo "# Description: $desc" >tests/$name |
||||||
|
if "$MAKEMAP" "$TLOC" &>/dev/null; then |
||||||
|
hash=`"$MAKEMAP" "$TLOC" 2>/dev/null|sha256sum|sed "s/ .*//"` |
||||||
|
status=ok |
||||||
|
else |
||||||
|
hash=`"$MAKEMAP" "$TLOC" 2>&1|sha256sum|sed "s/ .*//"` |
||||||
|
status=fail |
||||||
|
fi |
||||||
|
echo "# Status: $status" >>tests/$name |
||||||
|
echo "# Output hash: $hash" >>tests/$name |
||||||
|
cat "$TLOC" >>tests/$name |
||||||
|
|
@ -1,130 +0,0 @@ |
|||||||
#include <iostream> |
|
||||||
#include <set> |
|
||||||
#include <string> |
|
||||||
#include <vector> |
|
||||||
|
|
||||||
bool CmpStrEx(const std::string& expr, const std::string& str) |
|
||||||
{ |
|
||||||
if(expr.empty() || str.empty()) return false; |
|
||||||
|
|
||||||
struct State |
|
||||||
{ |
|
||||||
struct Block |
|
||||||
{ |
|
||||||
const size_t b,len; |
|
||||||
const bool optional; |
|
||||||
Block(const size_t bb,const size_t ee,const bool o):b(bb),len(ee-bb),optional(o) {} |
|
||||||
}; |
|
||||||
|
|
||||||
struct Cursor |
|
||||||
{ |
|
||||||
size_t block,offset; |
|
||||||
bool operator <(const struct Cursor& c) const |
|
||||||
{ |
|
||||||
if(block<c.block) return true; |
|
||||||
if(block>c.block) return false; |
|
||||||
if(offset<c.offset) return true; |
|
||||||
return false; |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
typedef std::set<struct Cursor> Cursors; |
|
||||||
typedef std::set<struct Cursor>::iterator pCursor; |
|
||||||
|
|
||||||
std::vector<struct Block> blockchain; |
|
||||||
Cursors cursors; |
|
||||||
const std::string& s; |
|
||||||
|
|
||||||
Cursors InitCursors(size_t block) const |
|
||||||
{ |
|
||||||
Cursors cs; |
|
||||||
for(size_t i=block; i<blockchain.size(); ++i) |
|
||||||
{ |
|
||||||
cs.insert({i,0}); |
|
||||||
if(!blockchain[i].optional) break; |
|
||||||
} |
|
||||||
return cs; |
|
||||||
} |
|
||||||
|
|
||||||
State(const std::string& str):s(str) |
|
||||||
{ |
|
||||||
size_t cur=0; |
|
||||||
size_t bpos=0; |
|
||||||
|
|
||||||
// Parse blocks
|
|
||||||
while(cur<s.length()) |
|
||||||
{ |
|
||||||
if('['==s[cur] || ']'==s[cur]) |
|
||||||
{ |
|
||||||
// Add current block to blockchain
|
|
||||||
if(cur>bpos) blockchain.push_back(Block(bpos,cur,(']'==s[cur]))); |
|
||||||
cur++; |
|
||||||
bpos=cur; |
|
||||||
continue; |
|
||||||
} |
|
||||||
cur++; |
|
||||||
} |
|
||||||
// Add last block
|
|
||||||
if(bpos<s.length()) blockchain.push_back(Block(bpos,s.length(),false)); |
|
||||||
|
|
||||||
// Creating cursors for the first symbol
|
|
||||||
cursors=InitCursors(0); |
|
||||||
} |
|
||||||
|
|
||||||
bool CmpSmb(const char c) |
|
||||||
{ |
|
||||||
pCursor p=cursors.begin(); |
|
||||||
bool res=false; |
|
||||||
|
|
||||||
// Compare symbol with all cursors
|
|
||||||
while(p!=cursors.end()) |
|
||||||
{ |
|
||||||
const Block& bl=blockchain[p->block]; |
|
||||||
if(c==s[bl.b+p->offset]) {res=true; ++p;} |
|
||||||
else p=cursors.erase(p); |
|
||||||
} |
|
||||||
|
|
||||||
// Increment cursors
|
|
||||||
Cursors upd; // New cursors
|
|
||||||
p=cursors.begin(); |
|
||||||
while(p!=cursors.end()) |
|
||||||
{ |
|
||||||
// Increment cursor on one position
|
|
||||||
if(p->offset+1>=blockchain[p->block].len) // Go to next block
|
|
||||||
{ |
|
||||||
Cursors cs=InitCursors(p->block+1); // Get cursors for next block
|
|
||||||
p=cursors.erase(p); // Erase current cursor
|
|
||||||
for(const auto& cur: cs) upd.insert(cur); // Copy cursors to new set
|
|
||||||
continue; |
|
||||||
} |
|
||||||
else upd.insert({p->block,p->offset+1}); |
|
||||||
if(blockchain[p->block].optional) // If current block is optional next symbol may be from next block
|
|
||||||
{ |
|
||||||
Cursors cs=InitCursors(p->block+1); // Get cursors for next blockchain
|
|
||||||
for(const auto& cur: cs) upd.insert(cur); // Copy cursors to new set
|
|
||||||
} |
|
||||||
++p; |
|
||||||
} |
|
||||||
|
|
||||||
cursors=upd; |
|
||||||
return res; |
|
||||||
} |
|
||||||
|
|
||||||
}; |
|
||||||
|
|
||||||
struct State st(expr); |
|
||||||
for(size_t pos=0; pos<str.length(); ++pos) |
|
||||||
{ |
|
||||||
if(!st.CmpSmb(str[pos])) return false; |
|
||||||
} |
|
||||||
|
|
||||||
return true; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char** argv) |
|
||||||
{ |
|
||||||
if(argc!=3) return 1; |
|
||||||
std::cout<<"Compare "<<argv[1]<<" with template "<<argv[2]<<": "<<(CmpStrEx(argv[2],argv[1])?"match":"not match")<<std::endl; |
|
||||||
return 0; |
|
||||||
} |
|
@ -1,287 +0,0 @@ |
|||||||
#include <iostream> |
|
||||||
#include <memory> |
|
||||||
#include <set> |
|
||||||
#include <string> |
|
||||||
#include <vector> |
|
||||||
|
|
||||||
bool CmpStrEx(const std::string& expr, const std::string& str) |
|
||||||
{ |
|
||||||
if(expr.empty() || str.empty()) return false; |
|
||||||
|
|
||||||
struct State |
|
||||||
{ |
|
||||||
struct Block |
|
||||||
{ |
|
||||||
using pBlock=std::unique_ptr<struct Block>; |
|
||||||
enum Type {NOTDEF,TEXT,OPTIONAL,VARIANTS,DELIM}; |
|
||||||
size_t b,e; |
|
||||||
Type type; |
|
||||||
const struct Block* parent; |
|
||||||
pBlock next,child; |
|
||||||
|
|
||||||
Block() = delete; |
|
||||||
Block(const struct Block&) = delete; |
|
||||||
Block(struct Block&&) = delete; |
|
||||||
|
|
||||||
bool isText() const {return type==TEXT;} |
|
||||||
|
|
||||||
Block(Type t, const struct Block* p=nullptr):b(0),e(0),type(t),parent(p),next(nullptr),child(nullptr) {} |
|
||||||
Block(size_t bb, size_t ee, const struct Block* p=nullptr):b(bb),e(ee),type(TEXT),parent(p),next(nullptr),child(nullptr) {} |
|
||||||
}; |
|
||||||
|
|
||||||
Block::pBlock Parse(const std::string& str) |
|
||||||
{ |
|
||||||
size_t e=0; |
|
||||||
struct Block* blk; |
|
||||||
struct Block* root; |
|
||||||
auto c=str[e]; |
|
||||||
bool init,next; |
|
||||||
|
|
||||||
// First symbol
|
|
||||||
if('['==c || '('==c) blk=new Block(('['==c)?Block::OPTIONAL:Block::VARIANTS); |
|
||||||
else blk=new Block(e,e+1); |
|
||||||
root=blk; |
|
||||||
init=!root->isText(); |
|
||||||
next=!init; |
|
||||||
|
|
||||||
e++; |
|
||||||
while(e<str.length()) |
|
||||||
{ |
|
||||||
c=str[e]; |
|
||||||
|
|
||||||
switch(c) |
|
||||||
{ |
|
||||||
case '[': |
|
||||||
case '(': |
|
||||||
{ |
|
||||||
(next?blk->next:blk->child).reset(new Block(('['==c)?Block::OPTIONAL:Block::VARIANTS,(next?blk->parent:blk))); |
|
||||||
blk=(next?blk->next:blk->child).get(); |
|
||||||
init=true; |
|
||||||
next=false; |
|
||||||
break; |
|
||||||
} |
|
||||||
case ']': |
|
||||||
case ')': |
|
||||||
{ |
|
||||||
blk=const_cast<struct Block*>(blk->parent); |
|
||||||
init=true; |
|
||||||
next=true; |
|
||||||
break; |
|
||||||
} |
|
||||||
case '|': {blk->next.reset(new Block(Block::DELIM,blk->parent)); blk=blk->next.get(); init=next=true; break;} |
|
||||||
default: |
|
||||||
{ |
|
||||||
if(init) |
|
||||||
{ |
|
||||||
(next?blk->next:blk->child).reset(new Block(e,e+1,(next?blk->parent:blk))); |
|
||||||
blk=(next?blk->next:blk->child).get(); |
|
||||||
} |
|
||||||
else blk->e=e+1; |
|
||||||
init=false; |
|
||||||
next=true; |
|
||||||
} |
|
||||||
} |
|
||||||
e++; |
|
||||||
} |
|
||||||
return Block::pBlock(root); |
|
||||||
} |
|
||||||
|
|
||||||
struct Cursor |
|
||||||
{ |
|
||||||
const struct Block* block; |
|
||||||
size_t offset; |
|
||||||
bool operator <(const struct Cursor& c) const {return block<c.block;} |
|
||||||
bool compare(const std::string& str, const char c) const {return c==str[block->b+offset];} |
|
||||||
Cursor(const struct Block* b, size_t o):block(b),offset(o) {} |
|
||||||
}; |
|
||||||
|
|
||||||
using Cursors=std::set<struct Cursor>; |
|
||||||
using pCursor=std::set<struct Cursor>::const_iterator; |
|
||||||
|
|
||||||
Block::pBlock root; |
|
||||||
Cursors cursors; |
|
||||||
const std::string& s; |
|
||||||
|
|
||||||
void InitCursors(const struct Block* blk) |
|
||||||
{ |
|
||||||
switch(blk->type) |
|
||||||
{ |
|
||||||
case Block::TEXT: {cursors.insert({blk,0}); break;} |
|
||||||
case Block::OPTIONAL: |
|
||||||
{ |
|
||||||
auto b=blk; |
|
||||||
InitCursors(b->child.get()); |
|
||||||
while(true) |
|
||||||
{ |
|
||||||
if(!b->next) break; |
|
||||||
b=b->next.get(); |
|
||||||
InitCursors(b); |
|
||||||
if(b->type!=Block::OPTIONAL) break; |
|
||||||
} |
|
||||||
break; |
|
||||||
} |
|
||||||
case Block::VARIANTS: |
|
||||||
{ |
|
||||||
auto b=blk->child.get(); |
|
||||||
while(true) |
|
||||||
{ |
|
||||||
InitCursors(b); |
|
||||||
while(b->type!=Block::DELIM) |
|
||||||
{ |
|
||||||
if(!b->next) break; |
|
||||||
b=b->next.get(); |
|
||||||
} |
|
||||||
if(!b->next) break; |
|
||||||
b=b->next.get(); |
|
||||||
} |
|
||||||
} |
|
||||||
default: {} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
State(const std::string& str):root(Parse(str)),s(str) {InitCursors(root.get());} |
|
||||||
|
|
||||||
std::string Name() const |
|
||||||
{ |
|
||||||
const struct Block* b=root.get(); |
|
||||||
std::string res; |
|
||||||
while(true) |
|
||||||
{ |
|
||||||
// Processing current block
|
|
||||||
switch(b->type) |
|
||||||
{ |
|
||||||
case(Block::TEXT): {res+=s.substr(b->b,b->e-b->b); break;} |
|
||||||
case(Block::OPTIONAL): {b=b->child.get(); goto next;} |
|
||||||
case(Block::VARIANTS): {b=b->child.get(); goto next;} |
|
||||||
case(Block::DELIM): {b=b->parent; break;} |
|
||||||
default: {} |
|
||||||
} |
|
||||||
// Go to next block
|
|
||||||
while(true) |
|
||||||
{ |
|
||||||
if(nullptr!=b->next) {b=b->next.get(); goto next;} |
|
||||||
if(nullptr!=b->parent) b=b->parent; |
|
||||||
else break; |
|
||||||
} |
|
||||||
if(nullptr==b->next && nullptr==b->parent) break; |
|
||||||
next: ; |
|
||||||
} |
|
||||||
return res; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
bool CmpSmb(const char c) |
|
||||||
{ |
|
||||||
pCursor p=cursors.cbegin(); |
|
||||||
bool res=false; |
|
||||||
|
|
||||||
// Compare symbol with all cursors
|
|
||||||
|
|
||||||
std::cout<<"--------------\n"; |
|
||||||
std::cout<<"Symbol: "<<c<<"\n"; |
|
||||||
|
|
||||||
while(p!=cursors.end()) |
|
||||||
{ |
|
||||||
std::cout<<p->block->b+p->offset<<" "<<s[p->block->b+p->offset]<<"\n"; |
|
||||||
if(p->compare(s,c)) {res=true; p++;} |
|
||||||
else p=cursors.erase(p); |
|
||||||
} |
|
||||||
|
|
||||||
Cursors old(std::move(cursors)); |
|
||||||
for(const auto& p:old) |
|
||||||
{ |
|
||||||
auto blk=p.block; |
|
||||||
// Increment cursors
|
|
||||||
if(blk->b+p.offset+1<blk->e) cursors.insert({blk,p.offset+1}); // Advance in current block
|
|
||||||
else // Move to next block
|
|
||||||
{ |
|
||||||
if(!blk->next || blk->next->type==Block::DELIM) // End of chain, must go up
|
|
||||||
{ |
|
||||||
while(blk->parent!=nullptr) |
|
||||||
{ |
|
||||||
blk=blk->parent; |
|
||||||
if(!blk->next || blk->next->type==Block::DELIM) continue; |
|
||||||
InitCursors(blk->next.get()); |
|
||||||
} |
|
||||||
} |
|
||||||
else InitCursors(blk->next.get()); // Next block in chain
|
|
||||||
} |
|
||||||
|
|
||||||
// Try to leave optional blocks
|
|
||||||
blk=p.block; |
|
||||||
while(blk->parent!=nullptr) |
|
||||||
{ |
|
||||||
blk=blk->parent; |
|
||||||
if(blk->type!=Block::OPTIONAL || !blk->next || blk->next->type==Block::DELIM) continue; |
|
||||||
InitCursors(blk->next.get()); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
return res; |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
|
|
||||||
// Main function
|
|
||||||
struct State st(expr); |
|
||||||
std::cout<<"Name is "<<st.Name()<<std::endl; |
|
||||||
|
|
||||||
// Dump code
|
|
||||||
{ |
|
||||||
std::cerr<<"digraph main\n{\nrankdir=TB pack=\"true\" packmode=\"node\";\n"; |
|
||||||
std::cerr<<"node [fontsize=30, shape=rectangle, style=\"filled,rounded\", fillcolor=azure2, fixedsize=\"false\", margin=0.2, width=1, penwidth=3, fontname=\"Times New Roman\"];\n"; |
|
||||||
std::cerr<<"edge [arrowsize=1.5, penwidth=3];\n"; |
|
||||||
|
|
||||||
const struct State::Block* r=st.root.get(); |
|
||||||
std::set<const struct State::Block*> visited; |
|
||||||
visited.insert(nullptr); |
|
||||||
while(true) |
|
||||||
{ |
|
||||||
if(visited.count(r)==0) |
|
||||||
{ |
|
||||||
std::string label; |
|
||||||
if(r->type==State::Block::OPTIONAL) label="[]"; |
|
||||||
if(r->type==State::Block::VARIANTS) label="()"; |
|
||||||
if(r->type==State::Block::DELIM) label="|"; |
|
||||||
if(r->type==State::Block::TEXT) label=expr.substr(r->b,r->e-r->b); |
|
||||||
std::cerr<<"\""<<r<<"\" [label=\""<<label<<"\""<<((r->type==State::Block::TEXT)?",fontcolor=\"red\"":"")<<"];\n"; |
|
||||||
if(r->child) std::cerr<<"\""<<r<<"\" -> \""<<r->child.get()<<"\";\n"; |
|
||||||
if(r->next) |
|
||||||
{ |
|
||||||
std::cerr<<"\""<<r<<"\" -> \""<<r->next.get()<<"\" [color=\"blue\"];\n"; |
|
||||||
std::cerr<<"{rank=same; "<<"\""<<r<<"\"; \""<<r->next.get()<<"\";}\n"; |
|
||||||
} |
|
||||||
if(r->parent!=nullptr) std::cerr<<"\""<<r<<"\" -> \""<<r->parent<<"\" [color=\"green\", penwidth=1];\n"; |
|
||||||
visited.insert(r); |
|
||||||
} |
|
||||||
if(r->child && visited.count(r->child.get())==0) r=r->child.get(); |
|
||||||
else if(r->next) r=r->next.get(); |
|
||||||
else |
|
||||||
{ |
|
||||||
while(r->parent!=nullptr) |
|
||||||
{ |
|
||||||
r=r->parent; |
|
||||||
if(r->next) {r=r->next.get(); break;} |
|
||||||
} |
|
||||||
} |
|
||||||
if(visited.count(r)!=0 && r->parent==nullptr && visited.count(r->next.get())!=0 && visited.count(r->child.get())!=0) break; |
|
||||||
} |
|
||||||
std::cerr<<"}\n"; |
|
||||||
} |
|
||||||
|
|
||||||
for(size_t pos=0; pos<str.length(); ++pos) |
|
||||||
{ |
|
||||||
if(!st.CmpSmb(str[pos])) return false; |
|
||||||
} |
|
||||||
|
|
||||||
return true; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char** argv) |
|
||||||
{ |
|
||||||
if(argc!=3) return 1; |
|
||||||
std::cout<<"Compare "<<argv[1]<<" with template "<<argv[2]<<": "<<(CmpStrEx(argv[2],argv[1])?"match":"not match")<<std::endl; |
|
||||||
return 0; |
|
||||||
} |
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,297 @@ |
|||||||
|
#ifndef MODGMT_PARAM_H |
||||||
|
#define MODGMT_PARAM_H |
||||||
|
#include "modgmt_strcomp.h" |
||||||
|
#include "common.h" |
||||||
|
|
||||||
|
// Common ancestor for all parameters
|
||||||
|
template<class Converter, bool Optional> |
||||||
|
class Parameter |
||||||
|
{ |
||||||
|
using ValueType=typename Converter::ValueType; |
||||||
|
std::string name; // Used for error reporting
|
||||||
|
bool initialised; |
||||||
|
Converter conv; |
||||||
|
ValueType val; |
||||||
|
|
||||||
|
template<bool hasDefault, class Conv=Converter> |
||||||
|
struct Adapter; |
||||||
|
template<class Conv> |
||||||
|
struct Adapter<true,Conv> {static const typename Conv::ValueType& Val(const Conv& cnv) {return cnv.Default();}}; |
||||||
|
template<class Conv> |
||||||
|
struct Adapter<false,Conv> {static typename Conv::ValueType Val(const Conv& cnv) {return typename Conv::ValueType();}}; |
||||||
|
|
||||||
|
template<class C> |
||||||
|
struct CheckDefault |
||||||
|
{ |
||||||
|
private: |
||||||
|
static void detect(...); |
||||||
|
template<class T> static decltype(std::declval<T>().Default()) detect(T); |
||||||
|
public: |
||||||
|
static constexpr bool value=std::is_same<ValueType, typename std::decay<decltype(detect(std::declval<C>()))>::type>::value; |
||||||
|
}; |
||||||
|
|
||||||
|
protected: |
||||||
|
Parameter(Parameter&&) = delete; |
||||||
|
Parameter(const Parameter&) = delete; |
||||||
|
Parameter() = delete; |
||||||
|
|
||||||
|
template<class... Args> |
||||||
|
Parameter(std::string&& str, Args... args): name(std::move(str)), initialised(false), conv(args...) |
||||||
|
{ |
||||||
|
val=Adapter<CheckDefault<Converter>::value>::Val(conv); |
||||||
|
} |
||||||
|
template<class... Args> |
||||||
|
Parameter(const std::string& str, Args... args): name(str), initialised(false), conv(args...) |
||||||
|
{ |
||||||
|
val=Adapter<CheckDefault<Converter>::value>::Val(conv); |
||||||
|
} |
||||||
|
|
||||||
|
void SetState(bool newini) {initialised=newini;} |
||||||
|
|
||||||
|
public: |
||||||
|
bool Init(const ObjectBase* p, std::string& err) |
||||||
|
{ |
||||||
|
std::string cerr; |
||||||
|
bool res=true; |
||||||
|
ValueType tval=conv.Convert(p,&res,cerr); |
||||||
|
SetState(res); |
||||||
|
if(res) val=std::move(tval); |
||||||
|
else err=std::move(cerr); |
||||||
|
return res; |
||||||
|
} |
||||||
|
bool Initialised() const {return initialised;} |
||||||
|
bool Exist() const {return initialised;} |
||||||
|
const std::string& Name() const {return name;} |
||||||
|
constexpr bool isOptional() const {return Optional;} |
||||||
|
const ValueType& Value() {return val;} |
||||||
|
const ValueType* operator->() const {return &val;} |
||||||
|
operator const ValueType&() {return val;} |
||||||
|
void Reset() {initialised=false; val=Adapter<CheckDefault<Converter>::value>::Val(conv);} |
||||||
|
|
||||||
|
static constexpr bool optional=Optional; |
||||||
|
using ConverterType=Converter; |
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
// Class for parameter which must be in named pair
|
||||||
|
template <class Converter, bool O> |
||||||
|
class NamedParameter: public TemplateComparator, public Parameter<Converter,O> |
||||||
|
{ |
||||||
|
public: |
||||||
|
using AcceptableObject=void; |
||||||
|
template<class... Args> |
||||||
|
NamedParameter(const std::string& t, Args... args):TemplateComparator(t),Parameter<Converter,O>(Template2Name(),args...) {} |
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
// Class for parameter which can be in named pair or as object of type Object
|
||||||
|
template <class Converter, bool O, class Object> |
||||||
|
class NamedFreeParameter: public NamedParameter<Converter,O> |
||||||
|
{ |
||||||
|
public: |
||||||
|
using AcceptableObject=Object; |
||||||
|
template<class... Args> |
||||||
|
NamedFreeParameter(Args... args):NamedParameter<Converter,O>(args...) {} |
||||||
|
}; |
||||||
|
|
||||||
|
// Class for parameter which can be in some positions in list
|
||||||
|
template <class Converter, bool O> |
||||||
|
class PositionalParameter: public Parameter<Converter,O> |
||||||
|
{ |
||||||
|
public: |
||||||
|
template<class... Args> |
||||||
|
PositionalParameter(Args... args):Parameter<Converter,O>(args...) {} |
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
// Base class for ParseNamedParameters and ParsePositionalParameters
|
||||||
|
class ParseParameters |
||||||
|
{ |
||||||
|
protected: |
||||||
|
std::string err; |
||||||
|
ParseParameters():err() {} |
||||||
|
ParseParameters(const ParseParameters&) = delete; |
||||||
|
ParseParameters(ParseParameters&&) = delete; |
||||||
|
|
||||||
|
public: |
||||||
|
std::string Error() const {return err;} |
||||||
|
bool Ok() const {return err.empty();} |
||||||
|
operator bool() const {return Ok();} |
||||||
|
}; |
||||||
|
|
||||||
|
// Parsing positional parameters
|
||||||
|
class ParsePositionalParameters: public ParseParameters |
||||||
|
{ |
||||||
|
ParsePositionalParameters() = delete; |
||||||
|
ParsePositionalParameters(const ParsePositionalParameters&) = delete; |
||||||
|
ParsePositionalParameters(ParsePositionalParameters&&) = delete; |
||||||
|
|
||||||
|
// Main parsing function
|
||||||
|
template <class Par, class... Args> |
||||||
|
void Parse(ObjectList::IndexType i, ObjectList::IndexType max, const ObjectList* ol, Par& param, Args&... args) |
||||||
|
{ |
||||||
|
// Check types of arguments
|
||||||
|
static_assert(std::is_same<PositionalParameter<typename Par::ConverterType, Par::optional>,Par>::value,"ParsePositionalParameters argument(s) must be PositionalParameter"); |
||||||
|
|
||||||
|
// Check if parameter already initialised. This is code error.
|
||||||
|
if(param.Initialised()) |
||||||
|
{ |
||||||
|
err="Parameter "+param.Name()+" already initialised. This is code error."; |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
// List is ended
|
||||||
|
if(i>=max) |
||||||
|
{ |
||||||
|
// Parameter is optional, skip it
|
||||||
|
if(Par::optional) Parse(i,max,ol,args...); |
||||||
|
// Parameter is required, this is an error
|
||||||
|
else err="Parameter "+param.Name()+" is required, but can't be setted because list is ended"; |
||||||
|
} |
||||||
|
// Initialise from some list element
|
||||||
|
else |
||||||
|
{ |
||||||
|
bool res=param.Init(ol->At(i),err); |
||||||
|
// All Ok, continue to next element in list
|
||||||
|
if(res) Parse(i+1,max,ol,args...); |
||||||
|
else |
||||||
|
{ |
||||||
|
// All Ok, optional parameter may be absent, try to initialise next parameter by same list element
|
||||||
|
if(Par::optional) Parse(i,max,ol,args...); |
||||||
|
// Error, required parameter not initialised
|
||||||
|
else err="Can't initialise parameter "+param.Name()+" from list element number "+ToString(i)+": "+err; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
// Bottom of recursion
|
||||||
|
void Parse(ObjectList::IndexType i, ObjectList::IndexType max, const ObjectList* ol) {if(i<max) err="There are excess elements in list";} |
||||||
|
|
||||||
|
public: |
||||||
|
template <class Converter, bool optional, class... Args> |
||||||
|
ParsePositionalParameters(const ObjectList* ol, PositionalParameter<Converter,optional>& p1, Args&... args) {Parse(0,ol->Size(),ol,p1,args...);} |
||||||
|
template <class Converter, bool optional, class... Args> |
||||||
|
ParsePositionalParameters(const ObjectList* ol, ObjectList::IndexType min, ObjectList::IndexType max, PositionalParameter<Converter,optional>& p1, Args&... args) {Parse(min,std::min(max,ol->Size()),ol,p1,args...);} |
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
// Parsing named parameters
|
||||||
|
class ParseNamedParameters: public ParseParameters |
||||||
|
{ |
||||||
|
ParseNamedParameters() = delete; |
||||||
|
ParseNamedParameters(const ParseNamedParameters&) = delete; |
||||||
|
ParseNamedParameters(ParseNamedParameters&&) = delete; |
||||||
|
|
||||||
|
// Parsing function for elements without names
|
||||||
|
// ob - object from which we initialise parameter param.
|
||||||
|
// init - is ob was already used for initialise something.
|
||||||
|
// args - other parameters
|
||||||
|
// Function try to initialise parameter param, if param accepted real type of ob for initialisation, else function try to initialise next parameter in args.
|
||||||
|
// Function return error if initialisation of parameter failed or if two parameters can be initialised from ob.
|
||||||
|
template <class Par, class... Args> |
||||||
|
bool ParseSingle(const ObjectBase* ob, bool init, Par& param, Args&... args) |
||||||
|
{ |
||||||
|
// Check types of arguments
|
||||||
|
static_assert(std::is_same<NamedParameter<typename Par::ConverterType, Par::optional>,Par>::value || std::is_same<NamedFreeParameter<typename Par::ConverterType, Par::optional, typename Par::AcceptableObject>,Par>::value,"ParseNamedParameters argument(s) must be NamedParameter or NamedFreeParameter"); |
||||||
|
|
||||||
|
OBType<typename Par::AcceptableObject> o(ob); |
||||||
|
if(o && init) |
||||||
|
{ |
||||||
|
err="Object of type "+ob->Type()+" used for initialisation of two parameters. This is code error."; |
||||||
|
return false; |
||||||
|
} |
||||||
|
if(!o) return ParseSingle(ob,init,args...); // Type mismatch, goto next parameter
|
||||||
|
if(param.Initialised()) |
||||||
|
{ |
||||||
|
err="Parameter "+param.Name()+" can't be initialised from object of type "+ob->Type()+" because it already initialised."; |
||||||
|
return false; |
||||||
|
} |
||||||
|
std::string ierr; |
||||||
|
if(!param.Init(ob,ierr)) |
||||||
|
{ |
||||||
|
err="Parameter "+param.Name()+" can't be initialised from object of type "+ob->Type()+": "+ierr; |
||||||
|
return false; |
||||||
|
} |
||||||
|
return ParseSingle(ob,true,args...); |
||||||
|
} |
||||||
|
// Bottom of recursion
|
||||||
|
bool ParseSingle(const ObjectBase* ob, bool init) const {return true;} |
||||||
|
|
||||||
|
// Parsing function for elements in pairs
|
||||||
|
// op - pair from which we initialise parameter param.
|
||||||
|
// pname - name of parameter already initialised from op (or empty string).
|
||||||
|
// args - other parameters
|
||||||
|
// Function try to initialise parameter param, if pair name corresponding to param template, else function try to initialise next parameter in args.
|
||||||
|
// Function return error if initialisation of parameter failed or if two parameters can be initialised from op.
|
||||||
|
template <class Par, class... Args> |
||||||
|
bool ParsePair(const ObjectPair* op, std::string& pname, Par& param, Args&... args) |
||||||
|
{ |
||||||
|
// Check types of arguments
|
||||||
|
static_assert(std::is_same<NamedParameter<typename Par::ConverterType, Par::optional>,Par>::value || std::is_same<NamedFreeParameter<typename Par::ConverterType, Par::optional, typename Par::AcceptableObject>,Par>::value,"ParseNamedParameters argument(s) must be NamedParameter or NamedFreeParameter"); |
||||||
|
|
||||||
|
bool cmp=param.Compare(op->Name()); |
||||||
|
if(cmp && !pname.empty()) |
||||||
|
{ |
||||||
|
err="Element "+op->Name()+" can be used for initialisation of two parameters: "+pname+" and "+param.Name(); |
||||||
|
return false; |
||||||
|
} |
||||||
|
if(!cmp) return ParsePair(op,pname,args...); // Name mismatch, goto next parameter
|
||||||
|
pname=param.Name(); |
||||||
|
if(param.Initialised()) |
||||||
|
{ |
||||||
|
err="Parameter "+param.Name()+" can't be initialised from element "+op->Name()+" because it already initialised."; |
||||||
|
return false; |
||||||
|
} |
||||||
|
std::string ierr; |
||||||
|
if(!param.Init(op->Value(),ierr)) |
||||||
|
{ |
||||||
|
err="Parameter "+param.Name()+" can't be initialised from element "+op->Name()+": "+ierr; |
||||||
|
return false; |
||||||
|
} |
||||||
|
return ParsePair(op,pname,args...); |
||||||
|
} |
||||||
|
// Bottom of recursion
|
||||||
|
bool ParsePair(const ObjectPair* op, std::string& pname) const {return true;} |
||||||
|
|
||||||
|
template <class Par, class... Args> |
||||||
|
void CheckRequired(const Par& param, Args&... args) |
||||||
|
{ |
||||||
|
if((Par::optional || param.Initialised())) CheckRequired(args...); |
||||||
|
else err="Parameter "+param.Name()+" is required, but not initialised"; |
||||||
|
} |
||||||
|
// Bottom of recursion
|
||||||
|
void CheckRequired() const {} |
||||||
|
|
||||||
|
public: |
||||||
|
template <class... Args> |
||||||
|
ParseNamedParameters(const ObjectList* ol, Args&... args) |
||||||
|
{ |
||||||
|
// Initialisation
|
||||||
|
std::string pname; |
||||||
|
for(ObjectList::const_iterator i=ol->begin();i!=ol->end();++i) |
||||||
|
{ |
||||||
|
pname.erase(); |
||||||
|
OBType<ObjectPair> p(*i); |
||||||
|
if( !(p?ParsePair(p,pname,args...):ParseSingle(*i,false,args...)) ) break; |
||||||
|
} |
||||||
|
if(!Ok()) return; // Error on initialisation phase
|
||||||
|
// Check if all required parameters are initialised
|
||||||
|
CheckRequired(args...); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
template<class Converter> |
||||||
|
using ONPar=NamedParameter<Converter,true>; |
||||||
|
template<class Converter> |
||||||
|
using RNPar=NamedParameter<Converter,false>; |
||||||
|
|
||||||
|
template<class Converter, class Object> |
||||||
|
using ONFPar=NamedFreeParameter<Converter,true,Object>; |
||||||
|
template<class Converter, class Object> |
||||||
|
using RNFPar=NamedFreeParameter<Converter,false,Object>; |
||||||
|
|
||||||
|
template<class Converter> |
||||||
|
using OPosPar=PositionalParameter<Converter,true>; |
||||||
|
template<class Converter> |
||||||
|
using RPosPar=PositionalParameter<Converter,false>; |
||||||
|
|
||||||
|
#endif |
@ -0,0 +1,139 @@ |
|||||||
|
#include "modgmt_strcomp.h" |
||||||
|
|
||||||
|
TemplateComparator::Block::pBlock TemplateComparator::Parse() |
||||||
|
{ |
||||||
|
size_t e=0; |
||||||
|
struct Block* blk; |
||||||
|
struct Block* root; |
||||||
|
auto c=s[e]; |
||||||
|
bool init,next; |
||||||
|
|
||||||
|
// First symbol
|
||||||
|
if('['==c || '('==c) blk=new Block(('['==c)?Block::OPTIONAL:Block::VARIANTS); |
||||||
|
else blk=new Block(e,e+1); |
||||||
|
root=blk; |
||||||
|
init=root->type!=Block::TEXT; |
||||||
|
next=!init; |
||||||
|
|
||||||
|
e++; |
||||||
|
while(e<s.length()) |
||||||
|
{ |
||||||
|
c=s[e]; |
||||||
|
|
||||||
|
switch(c) |
||||||
|
{ |
||||||
|
case '[': |
||||||
|
case '(': |
||||||
|
{ |
||||||
|
(next?blk->next:blk->child).reset(new Block(('['==c)?Block::OPTIONAL:Block::VARIANTS,(next?blk->parent:blk))); |
||||||
|
blk=(next?blk->next:blk->child).get(); |
||||||
|
init=true; |
||||||
|
next=false; |
||||||
|
break; |
||||||
|
} |
||||||
|
case ']': |
||||||
|
case ')': |
||||||
|
{ |
||||||
|
blk=const_cast<struct Block*>(blk->parent); |
||||||
|
init=true; |
||||||
|
next=true; |
||||||
|
break; |
||||||
|
} |
||||||
|
case '|': {blk->next.reset(new Block(Block::DELIM,blk->parent)); blk=blk->next.get(); init=next=true; break;} |
||||||
|
default: |
||||||
|
{ |
||||||
|
if(init) |
||||||
|
{ |
||||||
|
(next?blk->next:blk->child).reset(new Block(e,e+1,(next?blk->parent:blk))); |
||||||
|
blk=(next?blk->next:blk->child).get(); |
||||||
|
} |
||||||
|
else blk->e=e+1; |
||||||
|
init=false; |
||||||
|
next=true; |
||||||
|
} |
||||||
|
} |
||||||
|
e++; |
||||||
|
} |
||||||
|
return Block::pBlock(root); |
||||||
|
} |
||||||
|
|
||||||
|
void TemplateComparator::InitCursors(const struct TemplateComparator::Block* blk) |
||||||
|
{ |
||||||
|
switch(blk->type) |
||||||
|
{ |
||||||
|
case Block::TEXT: {cursors.insert({blk,0}); break;} |
||||||
|
case Block::OPTIONAL: |
||||||
|
{ |
||||||
|
auto b=blk; |
||||||
|
InitCursors(b->child.get()); |
||||||
|
while(true) |
||||||
|
{ |
||||||
|
if(!b->next) break; |
||||||
|
b=b->next.get(); |
||||||
|
InitCursors(b); |
||||||
|
if(b->type!=Block::OPTIONAL) break; |
||||||
|
} |
||||||
|
break; |
||||||
|
} |
||||||
|
case Block::VARIANTS: |
||||||
|
{ |
||||||
|
auto b=blk->child.get(); |
||||||
|
while(true) |
||||||
|
{ |
||||||
|
InitCursors(b); |
||||||
|
while(b->type!=Block::DELIM) |
||||||
|
{ |
||||||
|
if(!b->next) break; |
||||||
|
b=b->next.get(); |
||||||
|
} |
||||||
|
if(!b->next) break; |
||||||
|
b=b->next.get(); |
||||||
|
} |
||||||
|
} |
||||||
|
default: {} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
bool TemplateComparator::CmpSmb(const char c) |
||||||
|
{ |
||||||
|
pCursor p=cursors.cbegin(); |
||||||
|
bool res=false; |
||||||
|
|
||||||
|
// Compare symbol with all cursors
|
||||||
|
while(p!=cursors.end()) |
||||||
|
{ |
||||||
|
if(p->compare(s,c)) {res=true; p++;} |
||||||
|
else p=cursors.erase(p); |
||||||
|
} |
||||||
|
|
||||||
|
Cursors old(std::move(cursors)); |
||||||
|
for(const auto& p:old) |
||||||
|
{ |
||||||
|
auto blk=p.block; |
||||||
|
// Increment cursors
|
||||||
|
if(blk->b+p.offset+1<blk->e) cursors.insert({blk,p.offset+1}); // Advance in current block
|
||||||
|
else // Move to next block
|
||||||
|
{ |
||||||
|
if(!blk->next || blk->next->type==Block::DELIM) // End of chain, must go up
|
||||||
|
{ |
||||||
|
while(blk->parent!=nullptr) |
||||||
|
{ |
||||||
|
blk=blk->parent; |
||||||
|
if(!blk->next || blk->next->type==Block::DELIM) continue; |
||||||
|
InitCursors(blk->next.get()); |
||||||
|
} |
||||||
|
} |
||||||
|
else InitCursors(blk->next.get()); // Next block in chain
|
||||||
|
} |
||||||
|
|
||||||
|
// Try to leave optional blocks
|
||||||
|
blk=p.block; |
||||||
|
while(blk->parent!=nullptr) |
||||||
|
{ |
||||||
|
blk=blk->parent; |
||||||
|
if(blk->type!=Block::OPTIONAL || !blk->next || blk->next->type==Block::DELIM) continue; |
||||||
|
InitCursors(blk->next.get()); |
||||||
|
} |
||||||
|
} |
||||||
|
return res; |
||||||
|
} |
@ -0,0 +1,98 @@ |
|||||||
|
#ifndef MODGMT_STRCOMP_H |
||||||
|
#define MODGMT_STRCOMP_H |
||||||
|
#include <memory> |
||||||
|
#include <set> |
||||||
|
#include <string> |
||||||
|
|
||||||
|
// Compare string with template
|
||||||
|
class TemplateComparator |
||||||
|
{ |
||||||
|
TemplateComparator() = delete; |
||||||
|
TemplateComparator(const TemplateComparator&) = delete; |
||||||
|
TemplateComparator(TemplateComparator&&) = delete; |
||||||
|
|
||||||
|
struct Block |
||||||
|
{ |
||||||
|
using pBlock=std::unique_ptr<struct Block>; |
||||||
|
enum Type {NOTDEF,TEXT,OPTIONAL,VARIANTS,DELIM}; |
||||||
|
size_t b,e; |
||||||
|
Type type; |
||||||
|
const struct Block* parent; |
||||||
|
pBlock next,child; |
||||||
|
|
||||||
|
Block() = delete; |
||||||
|
Block(const struct Block&) = delete; |
||||||
|
Block(struct Block&&) = delete; |
||||||
|
|
||||||
|
Block(Type t, const struct Block* p=nullptr):b(0),e(0),type(t),parent(p),next(nullptr),child(nullptr) {} |
||||||
|
Block(size_t bb, size_t ee, const struct Block* p=nullptr):b(bb),e(ee),type(TEXT),parent(p),next(nullptr),child(nullptr) {} |
||||||
|
}; |
||||||
|
|
||||||
|
struct Cursor |
||||||
|
{ |
||||||
|
const struct Block* block; |
||||||
|
size_t offset; |
||||||
|
bool operator <(const struct Cursor& c) const {return block<c.block;} |
||||||
|
bool compare(const std::string& str, const char c) const {return c==str[block->b+offset];} |
||||||
|
Cursor(const struct Block* b, size_t o):block(b),offset(o) {} |
||||||
|
}; |
||||||
|
|
||||||
|
using Cursors=std::set<struct Cursor>; |
||||||
|
using pCursor=std::set<struct Cursor>::const_iterator; |
||||||
|
|
||||||
|
Block::pBlock Parse(); |
||||||
|
void InitCursors(const struct Block* blk); |
||||||
|
bool CmpSmb(const char c); |
||||||
|
|
||||||
|
Block::pBlock root; |
||||||
|
Cursors cursors; |
||||||
|
const std::string s; |
||||||
|
|
||||||
|
void Reset() |
||||||
|
{ |
||||||
|
cursors.clear(); |
||||||
|
InitCursors(root.get()); |
||||||
|
} |
||||||
|
|
||||||
|
public: |
||||||
|
TemplateComparator(const char* str):s(str) {root=Parse();} |
||||||
|
TemplateComparator(const std::string& str):s(str) {root=Parse();} |
||||||
|
TemplateComparator(std::string&& str):s(std::move(str)) {root=Parse();} |
||||||
|
|
||||||
|
bool Compare(const std::string& str) |
||||||
|
{ |
||||||
|
Reset(); |
||||||
|
for(size_t pos=0; pos<str.length(); ++pos) if(!CmpSmb(str[pos])) return false; |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
std::string Template2Name() const |
||||||
|
{ |
||||||
|
const struct Block* b=root.get(); |
||||||
|
std::string res; |
||||||
|
while(true) |
||||||
|
{ |
||||||
|
// Processing current block
|
||||||
|
switch(b->type) |
||||||
|
{ |
||||||
|
case(Block::TEXT): {res+=s.substr(b->b,b->e-b->b); break;} |
||||||
|
case(Block::OPTIONAL): |
||||||
|
case(Block::VARIANTS): {b=b->child.get(); goto next;} |
||||||
|
case(Block::DELIM): {b=b->parent; break;} |
||||||
|
default: {} |
||||||
|
} |
||||||
|
// Go to next block
|
||||||
|
while(true) |
||||||
|
{ |
||||||
|
if(nullptr!=b->next) {b=b->next.get(); goto next;} |
||||||
|
if(nullptr!=b->parent) b=b->parent; |
||||||
|
else break; |
||||||
|
} |
||||||
|
if(nullptr==b->next && nullptr==b->parent) break; |
||||||
|
next: ; |
||||||
|
} |
||||||
|
return res; |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
#endif |
@ -0,0 +1,11 @@ |
|||||||
|
# Description: Coord tests. Must passed. |
||||||
|
# Status: ok |
||||||
|
# Output hash: 1a1ca4aba24d0fe39407eef250167aca5c21373722f5f2a9bd6495cee34abaf2 |
||||||
|
@use "gmt" |
||||||
|
|
||||||
|
a=Coord("10:30:18"); |
||||||
|
b=Coord(10.5); |
||||||
|
c=Coord(":10:10"); |
||||||
|
d=Coord("-0:15:18"); |
||||||
|
|
||||||
|
print(a,a.n,b,b.n,c,c.n,d,d.n); |
@ -0,0 +1,8 @@ |
|||||||
|
# Description: Non-integer degrees in dd:mm:ss mode. |
||||||
|
# Status: fail |
||||||
|
# Output hash: 9469953f706df02349e019f8b47a499d169113b654aee46cacb966d01a27848c |
||||||
|
@use "gmt" |
||||||
|
|
||||||
|
a=Coord("1.0:10"); |
||||||
|
|
||||||
|
print(a); |
@ -0,0 +1,18 @@ |
|||||||
|
# Description: Projections test |
||||||
|
# Status: ok |
||||||
|
# Output hash: 18656de8c59c9a218b71dc730a3a1e8f1016179622392b11f052c64210f6fa2d |
||||||
|
@use "gmt" |
||||||
|
|
||||||
|
r=Region("130",150,30,50); |
||||||
|
|
||||||
|
px=Projection("dec",10,(10,20,10,20),15); |
||||||
|
p=Projection(r,type="cyl equid",h=10,stpar=0); |
||||||
|
p1=Projection(p,type="m",w=10); |
||||||
|
p2b=Projection("ob",10,r,"eq",(r.xe.n+r.xb.n)/2,(r.ye.n+r.yb.n)/2,140,15); |
||||||
|
p2=Projection(p2b,he=10); |
||||||
|
p3=Projection("cas",11,r); |
||||||
|
p4=Projection(r,type="cequa",11); |
||||||
|
p5=Projection(p4,type="j",centralm="130:30"); |
||||||
|
p6=Projection("cylstereo",10,r); |
||||||
|
|
||||||
|
print(px,p,p1,p2,p3,p4,p5,p6); |
@ -0,0 +1,10 @@ |
|||||||
|
# Description: Global regions test. |
||||||
|
# Status: ok |
||||||
|
# Output hash: e661246caef9b2a5fa5a96b9d75c0542d2e0e655de9d63d755aff01cd3b4ceba |
||||||
|
@use "gmt" |
||||||
|
|
||||||
|
r1=Region("global"); |
||||||
|
r2=Region("global360"); |
||||||
|
r3=Region("global180"); |
||||||
|
|
||||||
|
print(r1,r1.xb,r1.xe,r2,r2.xb,r2.xe,r3,r3.xb,r3.xe); |
@ -0,0 +1,9 @@ |
|||||||
|
# Description: Test sequential form of Region. |
||||||
|
# Status: ok |
||||||
|
# Output hash: a8006abe2c42b9e34c692ab88cf2f869ad6a01d1f32e6da842c1320f0d253d1c |
||||||
|
@use "gmt" |
||||||
|
|
||||||
|
r1=Region("10:30",20.5,-10.5,100,"bbox"); |
||||||
|
r2=Region("10:30",-10.5,20.5,100); |
||||||
|
|
||||||
|
print(r1,r2,r1.yb,r2.yb); |
@ -0,0 +1,13 @@ |
|||||||
|
# Description: Check named pairs form of Region. |
||||||
|
# Status: ok |
||||||
|
# Output hash: cf4acbeb2da3156fe52f1f374d4dc83a1aa0ee129a8aa2b1975ec828dd23cabe |
||||||
|
@use "gmt" |
||||||
|
|
||||||
|
r=Region("10:30",-10.5,20.5,100); |
||||||
|
r1=Region(r,type="bbox"); |
||||||
|
r2=Region(r,type="global180"); |
||||||
|
r3=Region(r,ye=80.5); |
||||||
|
l=(xb=r.xb.n-0.5,(xe=20+r.xb.n-10,yb=-10),(ye="11:30:28")); |
||||||
|
rr=Region(l, type="bbox"); |
||||||
|
|
||||||
|
print(r,r1,r2,r3,rr); |
Loading…
Reference in new issue